我目前必须执行128个独立的顺序矩阵向量CUBLAS操作。所有矩阵和向量都不同。每个独立矩阵紧接在存储器中存储在下一个矩阵中,并且矢量同样连续地存储在存储器中(全部以行 - 主要形式)。
更多背景信息: 矩阵为(2048 X 8),向量为长度2048.输出均为独立。因为我有超级矩阵,所以我有以下内容:
matrix[(2048*128)x8]
vector[(2048*128)x1]
output[(8*128)x1]
使用 cublasSgemv 我首先在每个迷你矩阵上进行转置,然后将结果添加(而不是替换)到内存中:
cublasSgemv(*handle, CUBLAS_OP_T, Bdim, Adim, scale1, d_matrix + offset1, Bdim, d_vector + offset2, 1, scale2, out + offset3, 1);
我正在进行128次此类通话,我想在一次中进行此操作。
分析器显示这些多次调用会显着降低性能。进行多个矩阵向量运算的最佳方法是什么?有没有办法将它们组合成一个快速呼叫?
流是最好的方式还是有某种方法来调用相关的偏移量(索引到我的矩阵和向量数组)?唯一的其他有效选择似乎是使用CUSPASE调用并将所有矩阵粘在对角线上。
注意:我对于在这个特定问题中获取gemv调用中的转置或行/列主要排序是不正确的。
答案 0 :(得分:1)
事实上,如果你想在这种情况下加速你的代码,你必须特别注意r / c主要订购。
如修订后的问题所示,您使用行主矩阵。那么你有一个超矩阵A [(2048 * 128)x8]和一个超向量V [(2048 * 128)x1]。在这里我假设你想要一个col-major矩阵输出[8x128](可以看作是一个超向量[(8 * 128)x1]),其中每个col是转置的结果(miniA [2048x8])* miniV [2048x1]。
另一方面,CUBLAS假设矩阵存储在column-major中。因此,可能需要一些额外的矩阵转置例程来改变排序。
由于您需要128个独立的[8x1]结果,因此它应该能够在 4 cuda API调用中计算结果,这应该比原来的 128 更有效调用
1. Row-major A[(2048*128)x8] can be seen as colum-major AA[8x(2048*128)]
B[8x(2048*128)] = AA[8x(2048*128)] * diag( V[[(2048*128)x1]] ) by 1 dgmm()
2. C[(2048*128)x8] = transpose( B[8x(2048*128)] ) by 1 geam()
3. Col-major C[(2048*128)x8] can be seen as col-major CC[2048x(8*128)]
O[1x(8*128)] = ones[1x2048] * CC[2048x(8*128)] by 1 gemv()
4. Row vector O[1x(8*128)] can be seen as col-major matrix OO[128x8]
output[8x128] = transpose( OO[128x8] ) by 1 geam()
这个主要输出[8x128]就是你想要的。
由于您需要adding
而不是replacing
,因此您可能需要再拨一次电话才能将原始值添加到output
答案 1 :(得分:1)
我已经快速启动了batchCUBLAS
SDK示例。我已针对大小为128
和2048x8
的矩阵考虑了8x1
次独立运行。以下是NVIDIA GeForce GT 540M(计算能力2.1)和Kepler K20c(计算能力3.5)的结果。
对于NVIDIA GeForce GT 540M案例,针对“非流式”cuBLAS执行的“流式”和“批量”版本没有相关改进。
对于NVIDIA Kepler K20c,我已经获得了
sgemm
1.87 GFlops(非流媒体); 3.08 GFlops(流媒体); 6.58 GFlops(批量);
dgemm
1.00 GFlops(非流媒体); 1.43 GFlops(流媒体); 6.67 GFlops(批量);
流媒体和批处理案例似乎相关地改善了单流精度的非流式情况。
<强>免责声明强>
我希望这些部分结果可以为您提供一些有用的信息。