cuda 矩阵计算思路求教!!!

  • 4 replies
  • 630 views
cuda 矩阵计算思路求教!!!
« 于: 六月 08, 2021, 05:49:10 pm »
问题:计算一个960*960的图像矩阵,矩阵的每个元素是一个向量A(1*64)、矩阵M(64*64)和向量A的转置(64*1)这三者的乘积运算得来的,其中图像矩阵的每个元素对应一个向量A,根据其他输入参数得到,矩阵M为固定输入参数。
我目前的方法:一次分配对应960*960个线程,每个线程做 向量*矩阵*向量 这样的运算,然后得到结果,这样这个核函数要耗时8~9ms之久,非常不高效,
不知道大家有什么好的求解思路,感谢留言交流!

Re: cuda 矩阵计算思路求教!!!
« 回复 #1 于: 六月 15, 2021, 04:17:03 pm »
问题:计算一个960*960的图像矩阵,矩阵的每个元素是一个向量A(1*64)、矩阵M(64*64)和向量A的转置(64*1)这三者的乘积运算得来的,其中图像矩阵的每个元素对应一个向量A,根据其他输入参数得到,矩阵M为固定输入参数。
我目前的方法:一次分配对应960*960个线程,每个线程做 向量*矩阵*向量 这样的运算,然后得到结果,这样这个核函数要耗时8~9ms之久,非常不高效,
不知道大家有什么好的求解思路,感谢留言交流!

这大约是960x960x64x64x2 = 7.2G次浮点运算. 如果是最坏9ms的话, 大约是800GFlops的性能.

因为不确定你的数据类型(float or double), 具体用的卡的情况, 也不知道是否使用了常见的优化手段(例如缓冲M矩阵的整体或者部分到shared memory或者到寄存器). 因此暂时不好说你这个性能如何. 不过你总是可以考虑上cublas之类的库的(如果你不想手写的话).

还是欢迎继续讨论的.

Re: cuda 矩阵计算思路求教!!!
« 回复 #2 于: 六月 24, 2021, 09:52:33 am »
这大约是960x960x64x64x2 = 7.2G次浮点运算. 如果是最坏9ms的话, 大约是800GFlops的性能.

因为不确定你的数据类型(float or double), 具体用的卡的情况, 也不知道是否使用了常见的优化手段(例如缓冲M矩阵的整体或者部分到shared memory或者到寄存器). 因此暂时不好说你这个性能如何. 不过你总是可以考虑上cublas之类的库的(如果你不想手写的话).

还是欢迎继续讨论的.

感谢回复,回帖不及时,抱歉!
我的M矩阵包括向量A都是cufftcomplex的浮点复数类型,之前尝试过缓冲M到sharedmemory 或寄存器中,总是会出现内存不够的情形(申请太多资源到共享内存或寄存器),因为每个元素是一个向量矩阵乘,所以可以调用cublas,但这应该属于动态并行了吧,因为程序后面会做移植,所以动态并行还没尝试过,我所用的显卡是普通的丽台P620,512个cuda核心,计算能力6.2,

Re: cuda 矩阵计算思路求教!!!
« 回复 #3 于: 六月 25, 2021, 01:10:14 pm »
感谢回复,回帖不及时,抱歉!
我的M矩阵包括向量A都是cufftcomplex的浮点复数类型,之前尝试过缓冲M到sharedmemory 或寄存器中,总是会出现内存不够的情形(申请太多资源到共享内存或寄存器),因为每个元素是一个向量矩阵乘,所以可以调用cublas,但这应该属于动态并行了吧,因为程序后面会做移植,所以动态并行还没尝试过,我所用的显卡是普通的丽台P620,512个cuda核心,计算能力6.2,

(1)缓冲没有必要一次性全部缓冲完。你可以看一下手册自带的"矩阵乘法"的例子, 里面完全不是一次性缓冲完的(可以将你这个看成它的特例,想法是类似的)。
(2)如果你要缓冲M, 最坏64x64*16B(2个double), 这需要64KB, 一次性放入shared memory不可以,但是可以考虑分片,或者直接读取寄存器中, 这是可以足够放入的. 然后需要跨线程累加起来得到标量不过(直接用shuffle交换累加)。或者如果你适当的转置(和你的存储格式有关),再每次点乘,也可以不用考虑跨线程累加。

(3)从CPU端调用cublas, 和动态并行无关
(4)从设备端如果想调用,还有动态并行方面的顾虑,则现在不支持CUDA DP的显卡已经停止支持了(NV目前的Toolkit从3.5+开始支持,甚至下一个版本3.X将被彻底拿掉). 所以不用考虑这个原因。
« 最后编辑时间: 六月 25, 2021, 01:20:05 pm 作者 屠戮人神 »

Re: cuda 矩阵计算思路求教!!!
« 回复 #4 于: 六月 30, 2021, 05:46:02 pm »
(1)缓冲没有必要一次性全部缓冲完。你可以看一下手册自带的"矩阵乘法"的例子, 里面完全不是一次性缓冲完的(可以将你这个看成它的特例,想法是类似的)。
(2)如果你要缓冲M, 最坏64x64*16B(2个double), 这需要64KB, 一次性放入shared memory不可以,但是可以考虑分片,或者直接读取寄存器中, 这是可以足够放入的. 然后需要跨线程累加起来得到标量不过(直接用shuffle交换累加)。或者如果你适当的转置(和你的存储格式有关),再每次点乘,也可以不用考虑跨线程累加。

(3)从CPU端调用cublas, 和动态并行无关
(4)从设备端如果想调用,还有动态并行方面的顾虑,则现在不支持CUDA DP的显卡已经停止支持了(NV目前的Toolkit从3.5+开始支持,甚至下一个版本3.X将被彻底拿掉). 所以不用考虑这个原因。
对,听了你的建议,把cuda sample好好看了下,终于打开了思路,问题解决了,效率一下提高了不少,感谢!