【问题标题】:CUDA kernel call in a simple sample简单示例中的 CUDA 内核调用
【发布时间】:2012-07-20 11:26:21
【问题描述】:

这是 cuda 的第一个并行代码示例

谁能描述一下内核调用:>>

这是重点代码:

#define N   10

__global__ void add( int *a, int *b, int *c ) {
    int tid = blockIdx.x;    // this thread handles the data at its thread id
    if (tid < N)
        c[tid] = a[tid] + b[tid];
}

int main( void ) {
    int a[N], b[N], c[N];
    int *dev_a, *dev_b, *dev_c;

    // allocate the memory on the GPU
    // fill the arrays 'a' and 'b' on the CPU
    // copy the arrays 'a' and 'b' to the GPU

    add<<<N,1>>>( dev_a, dev_b, dev_c );

    // copy the array 'c' back from the GPU to the CPU
    // display the results
    // free the memory allocated on the GPU

    return 0;
}

为什么它使用&lt;&lt;&lt; N , 1 &gt;&gt;&gt;,这意味着我们在每个块中使用了N个块和1个线程?因为我们可以写这个&lt;&lt;&lt; 1 , N &gt;&gt;&gt;并在这个块中使用1个块和N个线程来进行更多优化。

【问题讨论】:

  • 没有特别的原因。这是本书中第一个尝试解释 GPU 向量和的示例。在这一点上,他们几乎没有考虑过最佳性能或任何此类概念。这是一个简单的说明性示例。就这样。正如一开始的目标所说“您将使用 CUDA C 编写您的第一个并行代码”。

标签: cuda


【解决方案1】:

对于这个小例子,没有特别的原因(正如 Bart 在 cmets 中已经告诉你的那样)。但是对于更大、更实际的示例,您应该始终牢记每个块的线程数是有限的。也就是说,如果使用 N = 10000,则不能再使用 &lt;&lt;&lt;1,N&gt;&gt;&gt;,但 &lt;&lt;&lt;N,1&gt;&gt;&gt; 仍然可以使用。

【讨论】:

  • 网格大小也有限制。
  • @chaohuang 是的,也有局限性——我没有提到这个,因为我不想让我的回复变得太混乱,但你当然是对的,这是一个重要的事实!但是,最大网格大小远大于每个网格块的线程数。
  • 对不起。如果我想使用&lt;&lt;&lt;1,N&gt;&gt;&gt; 并且N 小于块限制,我必须使用threadIdx 而不是blockIdx 吗?还有一个问题:如果我想使用&lt;&lt;&lt;2 , N/2&gt;&gt;&gt;,谁能帮我写添加函数?
  • @mehD 是的,如果将blockIdx 用于&lt;&lt;&lt;1,N&gt;&gt;&gt;,则必须使用threadIdx。对于您的示例&lt;&lt;&lt;2, N/2&gt;&gt;&gt;,您可以像这样计算索引:uint idx = blockIdx.x * blockDim.x + threadIdx.x;。但是,您始终必须检查索引的范围:如果 N 是奇数,例如5,由于四舍五入,你会得到&lt;&lt;&lt;2,2&gt;&gt;&gt; (=4)。如果你四舍五入,你会得到&lt;&lt;&lt;2,3&gt;&gt;&gt; (=6)。在这种情况下,您必须检查内核中的索引(例如if( idx &gt;= 5 ) return;)。看看 Nvidia GPU Computing SDK 中的示例,它们真的很有帮助和指导!
猜你喜欢
  • 2020-11-25
  • 2023-04-09
  • 2021-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-08
  • 2012-07-26
  • 2013-03-17
相关资源
最近更新 更多