【发布时间】:2017-07-20 10:12:24
【问题描述】:
首先,让我声明我完全知道我的问题已经被问到:Block reduction in CUDA 但是,我希望澄清一下,我的问题是对此的跟进,我有特殊需要使该 OP 找到的解决方案不合适。
那么,让我解释一下。在我当前的代码中,我在 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 的 intarray 中,该数组中的位置对应于当前迭代。它必须在在内核中或至少仍在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 - not 谈论如何处理代码生成的输出数组。在 cmets 中,那里的 OP 提到他/她能够通过在 CPU 上对输出数组求和来完成这项工作——这是我无法做到的,因为这意味着我的 while 循环的每次迭代都下载输出数组。最后,该链接中的第三个答案建议使用库来实现这一点 - 但我有兴趣学习这样做的本机方式。
另外,我也会对有关如何实现我上面描述的内容的任何其他提议非常感兴趣。
【问题讨论】:
-
您会考虑使用多个内核而不是单个内核吗?
-
@RicardoOrtegaMagaña 当然,只要我不从/向 GPU 内存传输,调用多个内核本身不会有问题。
-
我建议使用 2 个内核,1 个用于第一次计算,另一个内核仅用于在主机程序中添加和放置循环。我需要有关您的程序如何工作的更多信息,但是使用您向我们展示的代码,这可能是解决您的问题的一种简单方法。
-
@RicardoOrtegaMagaña 我现在正在尝试这样做,但我在最后一步中挣扎。与我链接到的问题中最初提出的问题完全相同(但在 CPU 端已解决)。是的,我现在使用内核来进行缩减,但最终得到的是一个数组,而不是一个数字,我想在 GPU 中进一步将这个最终数组缩减为一个数字。
-
在我给你的例子中,结果它在数组的第一个元素上,如果你想在单个变量(内存位置)中发送一个指针在内核中,并将该值分配给那个位置,你想要那个值的地方,这样,当你想从主机或设备读取它时,你只需给出那个指针。
标签: arrays cuda sum nvidia reduction