首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >cublas一个函数调用产生了三次执行

cublas一个函数调用产生了三次执行
EN

Stack Overflow用户
提问于 2014-03-01 18:54:18
回答 1查看 372关注 0票数 0

我用第一矩阵非转置和第二转置调用cublas_Sgemm_v2函数10236次。但是,在nvprof结果中,我看到了该函数调用产生的三个项。函数调用的(m,n,k)值为(588,588,20)。

nvprof结果中列出了一些项。

代码语言:javascript
复制
Time(%)      Time     Calls       Avg       Min       Max  Name
 12.32%  494.86ms     10236  48.344us  47.649us  49.888us  sgemm_sm35_ldg_nt_128x8x128x16x16
  8.64%  346.91ms     10236  33.890us  32.352us  35.488us  sgemm_sm35_ldg_nt_64x16x128x8x32
  8.11%  325.63ms     10236  31.811us  31.360us  32.512us  sgemm_sm35_ldg_nt_128x16x64x16x16

这是意料之中的,为什么呢?有人能解释一下函数名(如sgemm_sm35_ldg_nt_128x8x128x16x16 )中的值是什么意思吗?

我还使用不同的转置设置对cublas_Sgemm_v2进行其他函数调用,每个函数调用只看到一个项。

更新:

正如@Marco13 13所问的,我在这里发表了更多的结果:

代码语言:javascript
复制
Time(%)      Time     Calls       Avg       Min       Max  Name
--------------------------------------------------------------------------------

Resulted from 7984 calls with (Trans, NonTrans) with (m, n, k) = (588, 100, 588)
 20.84%  548.30ms      7984  68.675us  58.977us  81.474us  sgemm_sm35_ldg_tn_32x16x64x8x16

Resulted from 7984 calls with (NonTrans, NonTrans) with (m, n, k) = (588, 100, 588)
 12.95%  340.71ms      7984  42.674us  21.856us  64.514us  sgemm_sm35_ldg_nn_64x16x64x16x16

All the following resulted from 3992 calls with (NonTrans, Trans) with (m, n, k) = (588, 588, 100)
  9.81%  258.15ms      3992  64.666us  61.601us  68.642us  sgemm_sm35_ldg_nt_128x8x128x16x16
  6.84%  179.90ms      3992  45.064us  40.097us  49.505us  sgemm_sm35_ldg_nt_64x16x128x8x32
  6.33%  166.51ms      3992  41.709us  38.304us  61.185us  sgemm_sm35_ldg_nt_128x16x64x16x16

另一次运行的588更改为288:

代码语言:javascript
复制
Time(%)      Time     Calls       Avg       Min       Max  Name
--------------------------------------------------------------------------------

Resulted from 7984 calls with (Trans, NonTrans) with (m, n, k) = (288, 100, 288)
 22.01%  269.11ms      7984  33.706us  30.273us  39.232us  sgemm_sm35_ldg_tn_32x16x64x8x16

Resulted from 7984 calls with (NonTrans, NonTrans) with (m, n, k) = (288, 100, 288)
 14.79%  180.78ms      7984  22.642us  18.752us  26.752us  sgemm_sm35_ldg_nn_64x16x64x16x16

Resulted from 3992 calls with (NonTrans, Trans) with (m, n, k) = (288, 288, 100)
  7.43%  90.886ms      3992  22.766us  19.936us  25.024us  sgemm_sm35_ldg_nt_64x16x64x16x16

从最后三行看,某些换位类型可能比其他类型更有效,而某些矩阵大小在计算时间上比矩阵大小更经济。确保经济计算的准则是什么?

更新2:

对于(m,n,k) = (588,100,588)的情况,在调用sgemm函数之前,我手动转换了矩阵,那么nvprof结果中只有一个项。所需时间仅略少于上表中这两项的总和。因此,这样做并没有多少性能上的好处。

代码语言:javascript
复制
Time(%)      Time     Calls       Avg       Min       Max  Name
--------------------------------------------------------------------------------
 31.65%  810.59ms     15968  50.763us  21.505us  72.098us  sgemm_sm35_ldg_nn_64x16x64x16x16
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-03-01 21:21:53

对不起,我没有回答--但稍微太长了,不能发表评论:

关于编辑,关于“转置”状态的影响:转置矩阵可能会导致访问模式在内存合并方面更糟糕。快速的网络搜索带来了一些关于这一点的结果( https://devtalk.nvidia.com/default/topic/528450/cuda-programming-and-performance/cublas-related-question/post/3734986/#3734986 ),但是与您的设置略有不同:

DGEMM在K20c上的性能 args: ta=N tb=N m=4096 n=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 ldb=4096 ldc=4096= 0.13280010秒GFLOPS=1034.93 args: ta=T tb=N m=4096 n=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 ldb=4096 ldc=4096= 0.13872910秒GFLOPS=990.7 args: ta=N tb=T m=4096 n=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 ldb=4096 ldc=4096= 0.12521601秒GFLOPS=1097.61 args: ta=T tb=T m=4096 n=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 ldb=4096 ldc=4096= 0.13652611秒GFLOPS=1006.69

在这种情况下,这些差异似乎不值得更改矩阵存储(例如,从列主到行主,以避免转换矩阵),因为所有模式似乎都以相似的速度运行。但是您的里程可能会有所不同--特别是,(t,n)和(n,n)之间的测试差别非常大(548 vs对340 vs),我发现这是相当令人惊讶的。如果您可以选择在矩阵的各种表示之间轻松切换,那么一个涵盖这四种情况的基准可能是值得的。

无论如何,关于在那里调用的函数的问题: CUBLAS 1.1中的sgemm函数的CUBLAS代码已经满是展开循环,并且已经包含了80 (!)sgemm函数的版本,用于使用#define-hell组装的不同情况。必须假定,在更新的CUBLAS版本中,这变得更加不可读,必须考虑到较新的计算功能--您在那里发现的函数名表明,情况确实如此:

sgemm_sm35_ldg_nt_64x16x128x8x32

  • sm35:运行在具有计算能力3.5的设备上
  • ldg:?非纹理记忆版本?(CUBLAS1.1包含用于纹理内存的称为sgemm_main_tex_*的函数,以及用于正常全局内存的函数sgemm_main_gld_* )
  • nt:第一个矩阵不是转置的,第二个是转置的
  • 64x16x128x8x32 -可能与瓷砖大小、共享内存等有关.

不过,我认为对sgemm的单个调用会导致调用这些内部函数中的三个,这是令人惊讶的。但是,正如注释中提到的:我假设他们试图用一个专门的、高效的版本来处理矩阵的“主”部分,并使用能够进行范围检查和/或处理不满的翘曲的“边框”。(不太准确,只是为了暗示:大小为288x288的矩阵可以由大小为256x256的矩阵的有效核心来处理,并对其余的32x288和288x32项进行两个调用)。

但是,这也是为什么我认为矩阵大小几乎不可能有一个一般准则的原因:在计算矩阵大小的时间方面,“最佳”矩阵大小至少将取决于

  • 目标系统的硬件版本(计算能力)
  • 换位旗
  • CUBLAS版本

编辑有关评论:可以想象,应该有一个很大的差异,之间的转基因和非转置处理。当两个矩阵相乘时

代码语言:javascript
复制
a00 a01 a02     b00 b01 b02
a10 a11 a12  *  b10 b11 b12
a20 a21 a22     b20 b21 b22

那么结果的第一个元素将是

代码语言:javascript
复制
a00 * b00 + a01 * b10 + a02 * b20

(它只是a的第一行和b的第一列的点乘积)。对于此计算,必须从a读取连续值。但是从b读取的值不是连续的。相反,它们是“每行中的第一个值”。一个可能认为这会对内存合并产生负面影响。但可以肯定的是,NVIDIA的工程师们已经尽力避免了这里的任何负面影响,而在CUBLAS中实现sgemm与“朴素的3嵌套循环实现的并行版本”相去甚远,因为这种访问模式会有如此明显的缺点。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22118822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档