[英]Avoid warp divergence
我有一个布尔一维数组T[N]
控制shift的值,如下所示:
**a
:指向全局内存中n*n
矩阵的指针的数组,我希望每个矩阵a
构造一个shift * Identity以获得:
a=a-shift*eye(n)
我有:
__device__ bool T[N];
__device__ float shift1[N];
__device__ float shift2[N];
__device__ float* a[N];
如果T [i] == true => shift = shift1否则shift = shift2; shift的值由T控制。
int tid=threadIdx.x;
if(tid < N){
if(T[tid]){
for (int i=0;i<n;i++){
a[tid][i*n+i]=a[tid][i*n+i]-shift1[tid];
}
}
else {
for (int i=0;i<n;i++){
a[tid][i*n+i]=a[tid][i*n+i]-shift2[tid];
}
}
}
__syncthreads();
这将导致翘曲发散并减慢我的代码的速度。 是否有一个技巧可以避免上述循环的翘曲发散?
正如@AnastasiyaAsadullayeva所建议的那样,我相信对代码进行相当简单的转换可能会减少您对翘曲发散的担忧:
int tid=threadIdx.x;
float myshift;
if (T[tid]) myshift = shift1[tid];
else myshift = shift2[tid];
if(tid < N){
for (int i=0;i<n;i++){
a[tid][i*n+i]=a[tid][i*n+i]-myshift;
}
}
__syncthreads();
编译器将预测myshift
的负载(创建已经提到的“条件负载”)。 该预测使负载本身的发散成本最小化。 在此转换下,此代码的其余部分是非散乱的(除非tid >= N
,这应该无关紧要)。
同样,如前所述,编译器可能已经观察到并完成了整个转换。 有可能,但是如果不运行您未提供的实际完整测试用例就无法确认。
更好的方法是以您认为自然的方式编写代码,然后让编译器处理它。 到那时,您可以使用探查器和分析驱动的优化来确定翘曲发散是否实际上是代码中的性能问题(探查器具有度量和其他方法来评估翘曲发散并在代码中指示其严重性。)
问题未解决?试试以下方法:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.