cuda编程问题

时间:2011-05-16 07:15:54

标签: cuda

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

#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;
    } 

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

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

现在我真正的问题是,当我使用&lt;&lt;&lt;&lt;&lt;&lt;&lt; 1,10&gt;&gt;&gt;调用内核时没关系 。它显示了完美的结果。 但当我用&lt;&lt;&lt;&lt; 1,5&gt;&gt;调用内核时结果如下:

 0.000000
 1.000000
 4.000000
 9.000000
 16.000000
 5.000000
 6.000000
 7.000000
 8.000000
 9.000000

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

 0.000000
 1.000000
 4.000000
 9.000000
 4.000000
 5.000000
 6.000000
 7.000000
 8.000000
 9.000000

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

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

3 个答案:

答案 0 :(得分:5)

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

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

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

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

square_array<<<gridDim,blockDim>>>(...)
在GPU中,自动变量blockDim将包含在主机端内核启动时传递的blockDim参数的x,y和z组件。类似地,gridDim将包含启动时传递的gridDim参数的x和y分量。

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

在CUDA中调用内核的方式如下:

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

这意味着将有每个块中运行numThreads线程的numBlocks块。例如,如果你打电话

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

然后1个块将运行并行运行5个线程。如果你打电话

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

然后有2个块,每个块中运行5个线程。除非您更改设备代码,否则您正在“平方”的数组的最大尺寸是产品numBlocks * numThreads。这解释了为什么原始数组中的所有值都不是平方的。

我建议你仔细阅读CUDA工具包附带的CUDA_C_Programming_Guide.pdf。