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

时间:2014-03-01 18:54:19

标签: cuda cublas

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

nvprof结果中列出了一些项目。

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所说,我在这里提出了更多结果:

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:

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结果中只有一个项目。所花费的时间仅比上表中两个项目的总和少一点。因此,这样做没有太大的性能提升。

Time(%)      Time     Calls       Avg       Min       Max  Name
--------------------------------------------------------------------------------
 31.65%  810.59ms     15968  50.763us  21.505us  72.098us  sgemm_sm35_ldg_nn_64x16x64x16x16

1 个答案:

答案 0 :(得分:2)

对不起,不是答案 - 但评论时间太长了:

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

  

K20c上的DGEMM性能

     

args:ta = N tb = N m = 4096 n = 4096 k = 4096 alpha = -1 beta = 2 lda = 4096 ldb = 4096 ldc = 4096   elapsed = 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   elapsed = 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   elapsed = 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   elapsed = 0.13652611秒GFLOPS = 1006.69

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


在任何情况下,关于你在那里调用的函数的问题:CUBLAS 1.1中sgemm函数的CUBLAS代码已经充满了展开的循环,并且已经包含了{{{)版本的{{1} 1}}用于使用sgemm组装的不同案例的函数 - 地狱。必须假设这在新的CUBLAS版本中变得更加难以理解,在这些版本中必须考虑更新的计算能力 - 并且您在那里找到的函数名称表明确实如此:

#define

  • sgemm_sm35_ldg_nt_64x16x128x8x32:在具有计算能力3.5
  • 的设备上运行
  • sm35 :?非纹理内存版本? (CUBLAS 1.1包含名为ldg的函数,它们用于纹理内存,函数sgemm_main_tex_*用于正常的全局内存)
  • sgemm_main_gld_*:第一个矩阵未转置,第二个矩阵为转置
  • nt - 可能与磁贴大小相关,可能是共享内存等...

尽管如此,我认为单次调用64x16x128x8x32导致调用这些内部函数的三个是令人惊讶的。但正如评论中所提到的:我假设他们尝试使用专门的高效版本处理矩阵的“主要”部分,并使用能够进行范围检查和/或应对经线的“边界瓷砖”。不满。 (不是很精确,只是为了暗示:大小为288x288的矩阵可以由大小为256x256的矩阵的高效核心处理,并且对剩余的32x288和288x32条目进行两次调用)。

但所有这些也是为什么我猜几乎没有关于矩阵大小的一般准则的原因:就矩阵大小的计算时间而言,“最佳”矩阵大小至少取决于

  • 目标系统的硬件版本(计算能力)
  • transposing-flags
  • CUBLAS版本

编辑关于评论:可以想象,转换和非转置处理之间应该存在相当大的差异。乘以两个矩阵时

sgemm

然后结果的第一个元素是

a00 a01 a02     b00 b01 b02
a10 a11 a12  *  b10 b11 b12
a20 a21 a22     b20 b21 b22

(它只是a00 * b00 + a01 * b10 + a02 * b20 第一行和a第一列的点积。对于此计算,必须从b读取连续值。但是从a读取的值不是是连续的。相反,它们是“每行中的第一个值”。一个可能认为这会对内存合并产生负面影响。但可以肯定的是,NVIDIA的工程师们已经尽力避免在这里产生任何负面影响,而且CUBLAS中b的实现远远不是“天真的3嵌套循环实现的并行版本”,其中访问模式会有这么明显的缺点。