Cuda 一个函数调用产生了三次执行
我调用了Cuda 一个函数调用产生了三次执行,cuda,cublas,Cuda,Cublas,我调用了cublas_Sgemm_v2函数10236次,第一个矩阵未转置,第二个矩阵转置。然而,在nvprof结果中,我看到了从该函数调用生成的三个项。函数调用的(m,n,k)值是(588588,20) nvprof结果中列出了一些项目 Time(%) Time Calls Avg Min Max Name 12.32% 494.86ms 10236 48.344us 47.649us 49.888us sgemm_sm
cublas_Sgemm_v2
函数10236次,第一个矩阵未转置,第二个矩阵转置。然而,在nvprof
结果中,我看到了从该函数调用生成的三个项。函数调用的(m,n,k)值是(588588,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\u sm35\u ldg\u nt\u 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)=(588100588)的情况,我在调用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
抱歉,不是答案-但评论的篇幅稍长: 关于编辑,关于“转置”状态的影响:转置矩阵可能会导致访问模式在内存合并方面更糟糕。快速的websearch会带来一些关于此()的结果,但设置与您的略有不同: DGEMM在K20c上的性能 参数:ta=N tb=N m=4096 N=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 运行时间=0.13280010秒GFLOPS=1034.93 参数:ta=T tb=N m=4096 N=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 已用时间=0.13872910秒GFLOPS=990.7 参数:ta=N tb=T m=4096 N=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 经过时间=0.12521601秒GFLOPS=1097.61 参数:ta=T tb=T m=4096 n=4096 k=4096 alpha=-1 beta=2 lda=4096 ldb=4096 ldc=4096 经过时间=0.13652611秒GFLOPS=1006.69 在这种情况下,更改矩阵存储(例如,从列主存储更改为行主存储,以避免变换矩阵)的麻烦似乎并不值得,因为所有模式似乎都以相似的速度运行。但是你的里程数可能会有所不同——特别是,(t,n)和(n,n)之间的测试差异非常大(548毫秒对340毫秒),这让我感到非常惊讶。如果您可以选择在矩阵的各种表示之间轻松切换,那么覆盖所有四种情况的基准可能是值得的
在任何情况下,关于在那里调用的函数的问题:CUBLAS 1.1中的
sgemm
函数的CUBLAS代码已经充满了展开的循环,并且已经包含了80个(!)版本的sgemm
函数,用于使用\define
-hell组装的不同情况。必须假设,在较新的CUBLAS版本中,这一点变得更加不可读,必须考虑到较新的计算能力,并且您在其中找到的函数名表明确实如此:
sgemm\u sm35\u ldg\u nt\u 64x16x128x8x32
:在具有计算能力3.5的设备上运行sm35
:?非纹理内存版本?(CUBLAS 1.1包含名为ldg
的函数,这些函数用于纹理内存,而sgemm\u main\u tex\u*
函数用于普通全局内存)sgemm\u main\u gld\u*
:第一个矩阵未转置,第二个矩阵已转置nt
-可能与磁贴大小、共享内存等有关64x16x128x8x32
sgemm
的一次调用导致调用其中三个内部函数是令人惊讶的。但正如评论中提到的:我假设他们试图用专门、高效的版本来处理矩阵的“主要”部分,并用能够进行范围检查和/或处理未满扭曲的版本来处理“边界块”。(不是很精确,只是想暗示一下:对于大小为256x256的矩阵,一个有效的核心可以处理大小为288x288的矩阵,对于剩余的32x288和288x32条目,可以进行两次调用)
但所有这一切也是为什么我想关于矩阵大小几乎没有一个通用的指导原则的原因:就计算时间而言,相对于矩阵大小,“最佳”矩阵大小至少取决于
- 目标系统的硬件版本(计算能力)
- 换位旗
- 库布拉斯版本
关于注释的编辑:可以想象,转换和非转换处理之间应该有相当大的区别。当两个矩阵相乘时
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
读取连续值。但是从b
读取的值不是连续的。相反,它们是“每行中的第一个值”。有人认为这会对记忆整合产生负面影响。当然,英伟达工程师们已经努力避免了任何负面影响,在CuBLAS中实现