我想问下,fermi下同一个warp中的前半束和后半束有没有可能出现访问冲突问题?因为我看到cuda4.0里有一句话:
“共享存储器有32个存储体,存储体的组织使得相邻的32位字被分配到相邻的存储体中。每个存储体带宽为每2个时钟周期32位字。因此不像低计算能力的设备,前半束内的线程和后半束的线程可能发生存储体冲突。”
但在紧接着的例子里(中间的访存方式却存在冲突):
[attach]3098[/attach]
fermi下前半束内的线程和后半束的线程到底有没有可能发生冲突呢?
我想问下,fermi下同一个warp中的前半束和后半束有没有可能出现访问冲突问题?因为我看到cuda4.0里有一句话:
“共享存储器有32个存储体,存储体的组织使得相邻的32位字被分配到相邻的存储体中。每个存储体带宽为每2个时钟周期32位字。因此不像低计算能力的设备,前半束内的线程和后半束的线程可能发生存储体冲突。”
但在紧接着的例子里(中间的访存方式却存在冲突):
[attach]3098[/attach]
fermi下前半束内的线程和后半束的线程到底有没有可能发生冲突呢?
楼主您好,关于您的问题“fermi下前半束内的线程和后半束的线程到底有没有可能发生冲突呢?”,更给予如下解答:
1个warp内的前16个线程和后16个线程对shared memory的访问,的确有可能导致冲突。
例如: (下文使用tid作为线程的线性id)
shared int chenchao[…];
int td = chenchao[tid * 2]; //冲突
您看到了,这样是的确可以冲突的。
请勿重复发帖,这是第二次劝告。建议听取。
对不起,我实在是搞不懂。请版主解释下:
“因此不像低计算能力的设备,前半束内的线程和后半束的线程可能发生存储体冲突。”这句话的意思,到底是低计算能力的设备会冲突还是fermi会冲突?
楼主您好,此句话非来自任何官方资料。无法为您提供任何解释。如果需要解释清楚歧义,请直接联系翻译者。
以及,实际在2#中的我的例子中,已经演示的足够明白了。请重新阅读。谢谢!
引用:
楼主您好,关于您的问题“fermi下前半束内的线程和后半束的线程到底有没有可能发生冲突呢?”,更给予如下解答:
1个warp内的前16个线程和后16个线程对shared memory的访问,的确有可能导致冲突。
例如: (下文使用tid作为线程的线性id)
shared int chenchao[…];
int td = chenchao[tid * 2]; //冲突
您看到了,这样是的确可以冲突的。
–引用完毕。
–那么谁会冲突,我想您是知道的。我说的是中文,您应该能理解。
Also, unlike for devices of compute capability 1.x, there may be bank conflicts between a thread belonging to the first half of a warp and a thread belonging to the second half of the same warp.
这句是来自官方资料。意思应该是1.x的前半束和后半束没有冲突,而2.x的就可能有冲突了吧?
然后,在64位访问时,不知什么原因的在某些本应该有冲突的情况下又没有冲突了吧?
那是不是将float型的数组采用double的指针进行访问时就可以避免一些情况下的冲突了(当然还要位运算的配合)?那这种没有冲突的访问方式的访存效率与有冲突的原始的访问方法相比(单比访存效率),哪个更高一些呢?
(1)楼主您的理解是正确。
(2)因为拆分成了2次访问了。
(3)这样的确可以。但会导致效率实际上和2x冲突一样。(因为你无冲突的读取了2次和你2x冲突的读取一次没区别。)
Thanks,明白了
LZ您好,在横扫斑竹的回答上,我来稍微补充下,以及换一些说法,希望能有助于你的理解。
1:手册资料建议看第一手的原版资料,翻译资料因为语言习惯的问题,可能造成理解上的问题,此时建议找到原版资料,相互比对。您也使用此方法解决了一个理解问题,这是一个好习惯。
2:在CUDA的硬件发展过程中,shared memory的bank数量是变化过的。早期的计算能力为1.x的硬件有16个banks,每次只能为一个half-warp服务,所以一个warp里面前面的half-warp和后面的half-warp是分开两次访问shared memory的,无论如何两者之间不会造成冲突。但是从计算能力2.x的fermi核心开始,shared memory的bank数量变成了32,此时如果还按照之前1.x的访问形式,可能会造成后面的half-warp和前面的half-warp访问同样banks的不同数据,从而造成2-way bank conflict。
一般的建议是改写代码,消除该bank conflict。
3:fermi下一个warp能否出现前half-warp和后half-warp产生bank conflict?
这个完全可能,您顶楼的图片和2#横扫斑竹的例子都说明了这一点。
4:在64bit数据访问的时候,官方手册指明,此时某些情况下原本有冲突的情况,现在又没有冲突了。但并未指明原因。
一个估计的原因在于,因为fermi的bank是4B宽度的,如果访问8B宽度的数据,需要2个banks为一个线程服务,此时同时只能为half-warp服务,因此前haif-warp和后half-warp是分开处理的,不可能出现相互影响。
以及顺便说一句,kepler的shared memory有了新的强化,在此种情况下可以一次性服务一个warp。
5:对float数据使用double指针并采取后处理的方法,其实 没有 什么实际意义,如同横扫斑竹在8#指出的那样,两种情况下读取效率是一样的。(以及你还引入了后处理,也有开销。)
这个问题的实质在于,如何理解“消除 bank conflict”。消除bank conflict的目的是为了提升shared memory的访问效率,而改成double再后处理,虽然没有了conflict,但是一开始将访存效率降低了一半,最后并不能带来好处。
LZ的各个问题大致总结如上,供参考。
祝您编码顺利~