cublasSgemm()用法的疑惑

我本来想计算一个C=alphaAB,其中A[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};B[5][3]={{1,2,3},{2,4,6},{3,6,9},{4,8,12},{5,10,15}};alpha=5.0;

我知道cublasSgenmm()中矩阵是按照列为主进行储存的,所以我得写成A[5][3]={{1,2,3},{2,4,6},{3,6,9},{4,8,12},{5,10,15}};B[3][5]={{1,2,3,4,5},{6,7,8,9,10},{11,12,13,14,15}};cublasSgemm(handle,transa,transb,3,3,5,&alpha,dev_A,3,dev_B,5,&beta,dev_C,3);其中beta=0;

感觉这样用起来好麻烦呀,我还得把A,B矩阵进行修改,有没有一种办法直接输入A,B矩阵就能直接计算呢?

楼主您好!

您可以使用"转置“操作来拨乱反正。

举个例子,我有a * b分别为:
1 1
2 2
3 3

1
1
然后乘法的结果应该是C:
2
4
6
您可以自然的用C语言写为:
float a[3][2] = {
{1,1},
{2,2},
{3,3}
};
float b[2][1] = {
{1},
{1}
};
可是这和常见的列优先存储相比,是颠倒的!
那么怎么办?您可以再颠倒过来(CUBLAS_OP_T)。

假设您已经有了handle, 对应的dev_a, dev_b, 和结果dev_c,
您可以cublasSgemm(您的handle, CUBLAS_OP_T, CUBLAS_OP_T, 3, 1, 2, &您的1.0f, dev_a, 2, dev_b, 1, &您的0.0f, dev_c, 3);

您即可直接得到结果[2.0f,4.0f,6.0f]T
(注意结果是列优先存储的).

感谢您来访!
祝您节日愉快!

EDIT:排版有点乱(修改了多次弄不好), 但不影响您看,您将就着点吧。:slight_smile:

好的,非常感谢,我试试看!

嗯嗯。祝您成功!

结果却是如您所说,我现在有两个问题:1.我想写一个函数void matMulmat(){},功能就是C=alphaAB,然后我在这个函数中写一段代码将C转置,这样的话输出的C还是按行排列的,那么加了这段转置后会不会引起效率的明显下降?2.索性我整个算法所有的程序都按列存取,不过这样感觉挺别扭的,用C用习惯了行存取。
我想听听您的建议。

还有一个问题,CULA库中的culaSgemm()应该也是按列存取的吧?下面这段小程序为什么运行结果是错的呢,感觉就是按照CULA手册中进行的参数设置啊!
int main(void)
{
float alpha=1.0;
float beta=0.0;
float A[9]={1,2,3,4,5,6,7,8,9};
float B[9]={2,3,5,3,4,6,4,5,7};
float C[9];
culaSgemm(‘t’,‘t’,3,3,3,alpha,A,3,B,3,beta,C,3);
for(int i=0;i<9;i++)
{
printf(“%f\n”,C[i]);
}
printf(“\n”);
return 0;
}

恭喜楼主!

(1)效率下降是必然的。无论具体实现是(a)此转置是在device里另外开辟缓冲区复制转置结果,还是(b)在读取的时候进行了坐标变化。他们都引入额外的操作。而多干活了,自然不是免费的午餐。

(2)嗯嗯。您可以直接在CUDA里面写的时候是按列的。只要您不觉得麻烦即可。这样机器就少了一步操作。

实际上,麻烦机器是为了让您舒心。或者说,您麻烦了,机器就舒服了。您可以选择其一。

您觉得呢?

您好!我不懂CULA。

我建议您咨询他们的支持。这支持已经包含在您购买CULA的费用里面了。

感谢您的来访。
祝您假日愉快!

好的,还是让机器舒服些吧~

好的,其实我也没有购买,我用学校的邮箱注册的,下载的那个(full-edition)culaR13a竟然能用!像矩阵求逆这些都能够实现,当矩阵维数超过1000的时候,加速很明显!本来以为只能下载(free edtion)cula,那个只有6个函数,功能少的可怜!我到它的论坛去看看~

善哉。未尝不可以让人舒服点。。:frowning:

(AB)^T = B^T A^T, 利用这个可以不用转置。另外建议参考一下SDK下面的例子,我记得有cublas实现矩阵相乘的。

善哉!风大威武87!千秋万代,一统江湖!!

我还得跟楼主道歉!因为我的数学知识不好!白白的让楼主转置3次了!!!(相乘的2个,结果的1个)。风大这个方法甚好!(AB)T = BT * AT!!

因为我们本来用C写的A和B,实际上是AT和BT,(因为C语言是颠倒的),
所以直接我们颠倒2者的相乘顺序即可。直接得到的就是_按行存储_的乘积!!

还是我给楼主您的举例:
我以前建议您使用CUBLAS_OP_T来2次转置,得到结果还需要转一次成C语言的行序。
现在不需要了,您可以直接使用OP_N+调换A和B:
cublasSgemm(您的handle, CUBLAS_OP_N, CUBLAS_OP_N, 1, 3, 2, &您的1.0f, dev_b, 1, dev_a, 2, &您的0.0f, dev_c, 1)来实现直接的C顺序的乘法,结果也是C顺序的!

这个请接受我的歉意。我白白的让您转置3次了。真心不好意思!(不过结果还是对的。只是浪费时间了,也浪费电了)!

感谢风大指出如此捷径。使得此公式从《线性代数》和《矩阵论》的课本里复活!再次感谢。

非常感谢!

非常感谢!去张家界的时候听过您在NVIDIA专场的报告!

呵呵!你的知识和技术一直很让我佩服,很少有人对技术的钻研有你那么深的.

谢谢啊!我表达能力比较差,在现场很好东西可能没有讲清楚.

挺好的呀,又不是竞选美国总统,无需那么出色的表达能力,掌握技术才是王道!:slight_smile:

:handshake