在使用共享存储器的矩阵相乘中,最终只是将结果放到了shared memory中。
我想请问,如何才能把shared memory中的小矩阵的值传入global memory呢。
如果只是简单的每个线程写一个值,就应该不需要先写入shared再写入global吧。
(也许硬件会自动合并,一次写入global)
不知道这个是如何实现?
在使用共享存储器的矩阵相乘中,最终只是将结果放到了shared memory中。
我想请问,如何才能把shared memory中的小矩阵的值传入global memory呢。
如果只是简单的每个线程写一个值,就应该不需要先写入shared再写入global吧。
(也许硬件会自动合并,一次写入global)
不知道这个是如何实现?
楼主您好,
(1)我们目前的所有显卡都不支持直接将shared memory中的值写入global memory的。
(2)您可以先读取global memory到寄存器中(普通变量)然后再将此变量写入到global memory的。
(3)关于您的简单每个线程写一个值得问题,您可以直接写入(实际上您根据1和2看出,就算你先写入shared memory的,也需要再从寄存器写入到global memory的。所以一般无需这么做。除非是为了将多个线程中的数据在shared memory中进行手工组合合并,然后再次读取写入global memory)
感谢来访。
第2条中,您应该是手误。我明白了。
手动合并问题我还不懂,不过等到时候自己学了有问题再请教你们。
谢谢您的耐心解释。
LZ您好:
我来稍微解释下手工合并的事情。
假定某算法下,你一个线程生成了最终需要存储在一行中的数据(这里用习惯上的行优先存储)。
那么此时,如果每个线程直接向global memory存储,那么一个warp的线程每次存储的时候,相邻线程的写入位置都离得非常远,这极大地影响存储效率。
此时可以将每个线程的生成数据都写到shared memory中,每个线程写一行,然后在适当同步之后,用一组线程去将shared memory中的一行数据写到global memory中,此时是合并访问的,访存效率较高。
大致如此,供您参考。
祝您好运~
这个真心不好意思,将shared打成了global。不过感谢楼主指正。
您的意思是,如果我的一个warp中的线程往global memory写入数据是连续的,那么硬件会进行一次 global memory 的访问,而如果不连续,就会访问32次是吗?
这个硬件的操作是由谁来完成的呢?
我问题的描述有个地方错误,为以免误导后来人,在此修正一下。
“在使用共享存储器的矩阵相乘中,最终只是将结果放到了shared memory中。”
其实并不是放在了shared memory中,是我自己理解错了。确实是每个线程往global memory中写一个值。而且应该是满足 ice 版主所说的合并访问的。
LZ您好:
您没有给出这个乘法算法实现的任何细节描述。
因此我无法也从来没有表示过您的实现是否满足合并访问的条件。
以及我4#的内容是在做“名词解释”,来补充横扫斑竹2#中的内容。
大致如此。
我指的就是 cuda_c_programming_guide 里面的使用共享存储器的矩阵相乘。
如果您觉得我盗用了您的名义来陈述自己的观点。我表示抱歉。下次我会注意措辞。
感谢您的耐心解释。
LZ您好:
global 访存是一个warp的线程整体通过SM中的硬件访问L2 cache以及global memory实现的。
如果访问是合并的(这需要所访问的数据集中在一定长度的显存范围之内,并且适当对齐),那么SM可以一次性获取所有所需数据。
如果不满足上述要求,比如前面说的相邻线程访问数地址距离很远,将分为多次访问完成,每次丢弃不需要的数据。但并非一定是32次。
大致如此。
LZ您好:
感谢您指明您的具体算法实现来源。
以及澄清若干事实。
祝您好运~
假设我一次访问的数据里面含有两个我所需要的数据,但是却不是连续的,会同时留下这两个数据吗?
LZ您好:
对于当前的主流GPU来说,会留下这两个数据的。
感谢您的耐心指导,以及您的刚正不阿的态度。印象非常深刻。