0

我有一个非常基本的问题,在浏览文件后我无法理解。我在执行我的一个项目时遇到了这个问题,因为我得到的输出完全损坏了,我相信问题要么出在内存分配上,要么出在线程同步上。好的,问题是:每个线程都可以创建传递给内核函数的所有变量和指针的单独副本吗?或者它只是创建变量的副本,但我们传递该内存的指针在所有线程之间共享。例如

int main()
{
  const int DC4_SIZE = 3;
  const int DC4_BYTES = DC4_SIZE * sizeof(float);
  float * dDC4_in;
  float * dDC4_out;
  float hDC4_out[DC4_SIZE];
  float hDC4_out[DC4_SIZE];

  gpuErrchk(cudaMalloc((void**) &dDC4_in, DC4_BYTES));
  gpuErrchk(cudaMalloc((void**) &dDC4_out, DC4_BYTES));
  // dc4 initialization function on host which allocates some values to DC4[] array

  gpuErrchk(cudaMemcpy(dDC4_in, hDC4_in, DC4_BYTES, cudaMemcpyHostToDevice));
  mykernel<<<10,128>>>(VolDepth,dDC4_in);
  cudaMemcpy(hDC4_out, dDC4_out, DC4_BYTES, cudaMemcpyDeviceToHost);
}

__global__ void mykernel(float VolDepth,float * dDC4_in,float * dDC4_out)
{
    for(int index =0 to end)
      dDC4_out[index]=dDC4_in[index] * VolDepth;
}

所以我将 dDC4_in 和 dDC4_out 指针传递给 GPU,其中 dDC4_in 用一些值初始化并计算 dDC4_out 并复制回主机,所以我的所有 1280 个线程都将具有单独的 dDC4_in/out 副本,或者它们都将在 GPU 上的相同副本上工作覆盖其他线程的值?

4

1 回答 1

3

全局内存由网格中的所有线程共享。您传递给内核的参数(您已分配cudaMalloc)在全局内存空间中。

线程确实有自己的内存(本地内存),但在您的示例中dDC4_in并由dDC4_out您的所有线程共享。

作为一般性的失败(取自CUDA 最佳实践文档):

在此处输入图像描述

在 DRAM 方面:本地内存(和寄存器)是每个线程的,共享内存是每个块的,全局、常量和纹理是每个网格的。

此外,可以在主机上读取和修改全局/常量/纹理内存,而本地和共享内存仅在内核运行期间存在。也就是说,如果您在本地或共享内存中有一些重要信息并且您的内核完成了,那么该内存将被回收并且您的信息会丢失。此外,这意味着从主机获取数据到内核的唯一方法是通过全局/常量/纹理内存。

无论如何,就您而言,建议如何修复代码有点困难,因为您根本没有考虑线程。不仅如此,在您发布的代码中,您只向内核传递了 2 个参数(它需要 3 个参数),因此您的结果有些不足也就不足为奇了。即使您的代码有效,您也会让每个线程从 0 循环到end并将其写入内存中的同一位置(这将被序列化,但您不知道哪个写入将是最后一个要通过的)。除了那个竞争条件,你让每个线程都做同样的计算;您的 1280 个线程中的每一个都将执行该 for 循环并执行相同的步骤。您必须决定线程到数据元素的映射,根据线程到元素的映射划分内核中的工作,并在此基础上执行计算。

例如,如果您有 1 个线程:1 个元素映射,

__global__ void mykernel(float VolDepth,float * dDC4_in,float * dDC4_out)
{
    int index = threadIdx.x + blockIdx.x*blockDim.x;
    dDC4_out[index]=dDC4_in[index] * VolDepth;
}

当然,这也需要更改内核启动配置以拥有正确数量的线程,如果线程和元素不是精确的倍数,您将需要在内核中添加一些边界检查。

于 2013-04-19T00:15:10.177 回答