首先,让我声明我充分意识到我的问题已经被问过了:CUDA中的块约简 然而,正如我希望表明的那样,我的问题是对那个问题的补充,并且我有特殊的需求,使得那个OP找到的解决方案不合适。
那么,让我解释一下。在我的当前代码中,我在while循环的每次迭代中运行一个Cuda内核,对一个数组的值进行一些计算。例如,可以将其视为以下内容:
然而,接下来我需要为GPU执行看似困难的任务。在调用内核的while循环的每次迭代中,我必须对odata生成的所有值求和,并将结果保存在一个名为result的int数组中,该数组的位置对应于当前迭代。这必须在内核内完成,或者至少仍然在GPU中完成,因为由于性能限制,只能在所有迭代完成后才能检索result数组。一个错误的天真尝试可能看起来像以下内容:
当然,由于GPU将代码分配到线程中,上面的代码无法工作。为了学习如何正确地做到这一点,我一直在阅读本站关于使用CUDA进行数组缩减的其他问题。特别是,我发现提到了一份非常好的NVIDIA有关此主题的pdf文档,该文档也在我之前提到的SO问题中讨论:http://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf 然而,虽然我完全理解这些幻灯片中描述的代码步骤以及一般优化,但我不明白如果代码实际输出一个完整的(尺寸不确定的)数组,那种方法如何将一个数组逐个求和并缩减为一个数字。请问有人能够为我解答并举例说明它是如何工作的吗?(即如何从输出数组中获取一个数字)?
现在,回到我之前提到的那个问题(Block reduction in CUDA)。请注意,其被接受的答案仅建议阅读我上面链接的pdf文件 - 该文件没有讨论如何处理代码生成的输出数组。在评论中,该问题的OP提到他/她能够通过在CPU上对输出数组求和来完成任务 - 这是我无法做到的,因为这意味着每次while循环迭代都要下载输出数组。最后,在该链接的第三个答案中,建议使用库来完成此操作 - 但我有兴趣学习本地的实现方式。
或者,我也非常感兴趣听取关于如何实现我所描述的其他建议。
那么,让我解释一下。在我的当前代码中,我在while循环的每次迭代中运行一个Cuda内核,对一个数组的值进行一些计算。例如,可以将其视为以下内容:
int max_iterations = 1000;
int iteration = 0;
while(iteration < max_iterations)
{
__global__ void calcKernel(int* idata, int* odata)
{
int i = blockIdx.x*blockDim.x + threadIdx.x;
if (i < n)
{
odata[i] = (idata[i] + 2) * 5;
}
}
iteration++;
}
然而,接下来我需要为GPU执行看似困难的任务。在调用内核的while循环的每次迭代中,我必须对odata生成的所有值求和,并将结果保存在一个名为result的int数组中,该数组的位置对应于当前迭代。这必须在内核内完成,或者至少仍然在GPU中完成,因为由于性能限制,只能在所有迭代完成后才能检索result数组。一个错误的天真尝试可能看起来像以下内容:
int max_iterations = 1000;
int iteration = 0;
while(iteration < max_iterations)
{
__global__ void calcKernel(int* idata, int* odata, int* result)
{
int i = blockIdx.x*blockDim.x + threadIdx.x;
if (i < n)
{
odata[i] = (idata[i] + 2) * 5;
}
}
result[iteration] = 0;
for(int j=0; j < max_iterations; j++)
{
result[iteration] += odata[j];
}
iteration++;
}
当然,由于GPU将代码分配到线程中,上面的代码无法工作。为了学习如何正确地做到这一点,我一直在阅读本站关于使用CUDA进行数组缩减的其他问题。特别是,我发现提到了一份非常好的NVIDIA有关此主题的pdf文档,该文档也在我之前提到的SO问题中讨论:http://developer.download.nvidia.com/compute/cuda/1.1-Beta/x86_website/projects/reduction/doc/reduction.pdf 然而,虽然我完全理解这些幻灯片中描述的代码步骤以及一般优化,但我不明白如果代码实际输出一个完整的(尺寸不确定的)数组,那种方法如何将一个数组逐个求和并缩减为一个数字。请问有人能够为我解答并举例说明它是如何工作的吗?(即如何从输出数组中获取一个数字)?
现在,回到我之前提到的那个问题(Block reduction in CUDA)。请注意,其被接受的答案仅建议阅读我上面链接的pdf文件 - 该文件没有讨论如何处理代码生成的输出数组。在评论中,该问题的OP提到他/她能够通过在CPU上对输出数组求和来完成任务 - 这是我无法做到的,因为这意味着每次while循环迭代都要下载输出数组。最后,在该链接的第三个答案中,建议使用库来完成此操作 - 但我有兴趣学习本地的实现方式。
或者,我也非常感兴趣听取关于如何实现我所描述的其他建议。