我在warps中做了如下缩小:
__global__ void summation1(double *nBodies)
{
...
for (int offset = warpSize/2; offset > 0; offset /= 2) {
elements.x += __shfl_down(elements.x, offset);
}
...
}
以上工作正常。然后我接受了代码并将其放在这样的函数中:
__inline__ __device__
double warpReduceSum(double val) {
for (int offset = warpSize/2; offset > 0; offset /= 2) {
val += __shfl_down(val, offset);
}
return val;
}
__global__ void summation1(double *nBodies)
{
...
warpReduceSum(elements.x);
...
}
然而,上述情况不起作用 - 我没有得到一笔钱,只是原来的值。关于为什么会发生这种情况的任何想法都将非常感激。
答案 0 :(得分:3)
warp shuffle operations 不适用于64位数量。请参阅documentation。例如:
必须首先转换int或float以外的类型才能使用__shfl()内在函数。
但是根据您在CUDA标头中使用未记录的函数的注释。我相信它应该有用。
经过进一步考虑后,我认为您遇到的问题是传递价值。对于此函数定义:
__inline__ __device__
double warpReduceSum(double val) {
for (int offset = warpSize/2; offset > 0; offset /= 2) {
val += __shfl_down(val, offset);
}
return val;
}
您将val
按值传递给函数,因此该函数具有该值的本地副本。然后你去减少扭曲。但是在主代码中,您忽略了返回值:
warpReduceSum(elements.x);
实际的混洗值 实际上不是elements.x
,而是它的一些副本。
修复可能很简单:
elements.x = warpReduceSum(elements.x);
您也可以尝试按引用传递数量:
double warpReduceSum(double &val) {
我已经测试了这两个建议。任何一个似乎都适用于我的测试用例。
请注意,SO需要一个完整的代码来寻求调试帮助的问题。来自here
寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为,特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用。请参阅:如何创建最小,完整且可验证的示例。
因此,如果上述建议没有帮助(即在你回来之前说“我做了那个改变,它没有用”),我会建议一个完整的代码,证明问题是按顺序。