【问题标题】:cuda programming problemcuda编程问题
【发布时间】:2011-08-26 05:32:31
【问题描述】:

我对 cuda 很陌生。我在设备仿真模式下在我的 ubuntu 10.04 上使用 cuda。 我编写了一个代码来计算以下数组的平方:

#include <stdio.h>
#include <cuda.h>
__global__ void square_array(float *a, int N)
    {
      int idx = blockIdx.x + threadIdx.x;
      if (idx<=N) 
       a[idx] = a[idx] * a[idx];
    }
int main(void)
    {
      float *a_h, *a_d; 
      const int N = 10;  
      size_t size = N * sizeof(float);
      a_h = (float *)malloc(size);        
      cudaMalloc((void **) &a_d, size);   
          for (int i=0; i<N; i++) a_h[i] = (float)i;
      cudaMemcpy(a_d, a_h, size, cudaMemcpyHostToDevice);
           square_array <<< 1,10>>> (a_d, N);

 cudaMemcpy(a_h, a_d, sizeof(float)*N, cudaMemcpyDeviceToHost);
      // Print results
      for (int i=0; i<N; i++) printf(" %f\n",  a_h[i]);

      free(a_h); 
cudaFree(a_d);
  return 0;
    } 

当我运行这段代码时,它显示没有问题,它给了我正确的输出。

现在我的问题是,当我使用 >> 或>> 时,结果是一样的。 gpu 上发生了什么? 我所了解的是,我只是启动了包含 2 个线程的 5 个块的 cuda 内核。 谁能解释一下 Gpu 如何处理这个问题或实现启动(内核调用)?

现在我真正的问题是当我用 >> 调用内核时没问题。它显示了完美的结果。 但是当我用 > 调用内核时,结果如下:

 0.000000
 1.000000
 4.000000
 9.000000
 16.000000
 5.000000
 6.000000
 7.000000
 8.000000
 9.000000

类似地,当我减少或增加内核调用中的第二个参数时,它会显示不同的结果,例如,当我将其更改为 > 时,它会显示以下结果:

 0.000000
 1.000000
 4.000000
 9.000000
 4.000000
 5.000000
 6.000000
 7.000000
 8.000000
 9.000000

为什么会出现这个结果? 任何机构都可以解释内核启动调用的工作原理吗?

blockdim 类型变量包含什么? 请帮助我理解内核调用启动和工作的概念? 我搜索了编程指南,但他们没有很好地解释。

【问题讨论】:

  • 您正在更改 N (10, 4, 5) 的值。那么很明显只需要更新前N个元素。您认为这有什么令人困惑的?!

标签: cuda


【解决方案1】:

您的内核代码中idx 的计算不正确。如果您将其更改为:

int idx = blockDim.x * blockIdx.x + threadIdx.x;

您可能会发现结果更容易理解。

编辑:对于任何给定的内核启动

square_array<<<gridDim,blockDim>>>(...)

在 GPU 中,自动变量 blockDim 将包含在主机端内核启动中传递的 blockDim 参数的 x、y 和 z 分量。类似地,gridDim 将包含在启动时传递的 gridDim 参数的 x 和 y 分量。

【讨论】:

  • 原代码是这样的,但它并没有改变场景,或者在我上次询问blockdim时仔细检查我的问题,你能解释一下内核调用的工作原理吗
  • 我尽力了 - 正如最初发布的那样,您的问题是一堆未格式化、难以理解的垃圾。看看我发布的编辑。
【解决方案2】:

除了 talonmies 所说的,您可能需要执行以下操作才能在实际应用中获得更好的性能。

if (idx < N) {
tmp = a[idx];
a[idx] = tmp * tmp;
}

【讨论】:

    【解决方案3】:

    在 CUDA 中调用内核的方式是这样的:

    kernel<<<numBlocks,numThreads>>>(Kernel arguments);
    

    这意味着将有 numBlocks 个块,每个块中运行 numThreads 个线程。例如,如果您调用

     kernel<<<1,5>>>(Kernel args);
    

    那么 1 个块将与 5 个并行运行的线程一起运行。如果你打电话

     kernel<<<2,5>>>(Kernel args);
    

    那么就会有 2 个块,每个块运行 5 个线程。除非您更改设备代码,否则您“平方”的数组的最大维度是乘积 numBlocks*numThreads。这就解释了为什么不是原始数组中的所有值都是平方的。

    我建议您通读 CUDA 工具包附带的 CUDA_C_Programming_Guide.pdf。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-19
      • 2010-12-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 2010-09-22
      相关资源
      最近更新 更多