CUDA shuffle warp reduce不作为内联设备功能使用

CUDA shuffle warp reduce不作为内联设备功能使用,cuda,Cuda,我正在对翘曲进行如下缩减: __global__ void summation1(double *nBodies) { ... for (int offset = warpSize/2; offset > 0; offset /= 2) { elements.x += __shfl_down(elements.x, offset); } ... } 上述措施效果良好。然后我将代码放入如下函数中: __inline__ __devic

我正在对翘曲进行如下缩减:

__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);

    ...

}
然而,上面的方法不起作用-我没有得到一个总和,只有原始值。任何关于为什么会发生这种情况的想法都将不胜感激

扭曲混洗操作不适用于64位数量。请参阅。例如:

必须首先强制转换int或float以外的类型才能使用_shfl()intrinsic

但根据评论,您正在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);
而实际的乱序值实际上不是
元素.x
,而是它的一些副本

修复方法可能很简单,如下所示:

elements.x = warpReduceSum(elements.x);
您也可以尝试通过引用传递数量:

double warpReduceSum(double &val) {
我已经测试了这两个建议。任何一个似乎都适用于我的测试用例

请注意,SO需要一个完整的问题代码来寻求调试帮助。从

寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建一个最小、完整且可验证的示例


因此,如果上述建议没有帮助(即,在你回来说“我做了那个更改,它不起作用了”)之前,我会建议一个完整的代码来证明问题是正确的。

我在/usr/local/cuda-6.5/targets/x86_64-linux/include/sm_30_intrinsics.h:static device inline double\u shfl\u down中找到了这个函数(双变量,无符号int-delta,int-width=warpSize){float-lo,hi;asm-volatile(“mov.b64{%0,%1},%2;”:“=f”(lo),“=f”(hi):“d”(var));hi=uu-shfl_u-down(hi,delta,width);lo=u-shfl-down(lo,delta,width);asm-volatile(“mov.b64%0,{%1,%2};”:“=d”(var):“f):“f”(var):“f”(lo),“f),“f”(hi));返回var;)是的,它是无文档的,但我认为它应该是可用的。我的答案不正确。我修改了它。啊,当然。我犯了一个愚蠢的错误,对不起。它正在工作。谢谢你的回答!如果你使用无文档的函数,它总是有可能被删除(基本上没有通知)或者在未来的CUDA版本中修改,因此可能会破坏任何使用它的代码。这对我来说似乎不太可能,但我觉得有义务提及它。(即使使用有文档记录的功能,这样的免责声明也是可能的,但在这种情况下,我想说的是,可能的删除可能性更小,而且几乎可以肯定会提前发出某种形式的弃用通知。)