单Wave并行归约的共享内存写回问题及优化方案咨询
并行归约的编译器优化问题与简洁修复方案
问题背景
在并行归约的实现中,处理最后2*WaveGetLaneCount()个元素时需要避免使用GroupMemoryBarrierWithGroupSync,对应的原始HLSL代码如下:
for (unsigned int s=groupDim_x/2; s>32; s>>=1) { if (tid < s) sdata[tid] += sdata[tid + s]; GroupMemoryBarrierWithGroupSync(); } if (tid < 32) { sdata[tid] += sdata[tid + 32]; sdata[tid] += sdata[tid + 16]; sdata[tid] += sdata[tid + 8]; sdata[tid] += sdata[tid + 4]; sdata[tid] += sdata[tid + 2]; sdata[tid] += sdata[tid + 1]; }
编译器会对这段代码进行优化,将共享内存的连续读写转换为使用局部变量暂存后一次性写回,这会破坏归约逻辑:
if (tid < 32) { float ldata = sdata[tid]; ldata += sdata[tid + 32]; ldata += sdata[tid + 16]; ldata += sdata[tid + 8]; ldata += sdata[tid + 4]; ldata += sdata[tid + 2]; ldata += sdata[tid + 1]; sdata[tid] = ldata; }
目前已知一种修复方法是给每个内存操作添加if(tid < s)前缀,但这种写法冗余繁琐,请问是否有更简洁的修复方案?
补充提示
Shader Model 6环境下,应优先使用WaveActiveSum这类wave内在函数实现归约,而非WaveReadLaneAt和WaveGetLaneIndex。
内容的提问来源于stack exchange,提问作者Tom Huntington
相关产品推荐
相关产品推荐

