CUDA线程如何工作

mas*_*141 3 cuda

我对线程的形成和执行方式有很多疑问.

首先,文档将GPU线程描述为轻量级线程.假设我希望将两个100*100矩阵相乘.100*100如果每个元素都由不同的线程计算,这将需要线程.但是,我的GPU(NVIDIA GT 640M LE)规格显示了两个SM,每个SM只能支持2048个线程.考虑到我的GPU不能支持如此多的线程,如何计算其余的并行元素是两个可能的.

还要考虑基本的矢量添加代码.假设我调用一个包含1个块和64个线程的内核来添加两个包含100个元素的数组,如下所示:

    __global__ void add(int* a,int* b,int* c)
    {
        int i = threadIdx.x;
        for(i<100)
        {
            c[i] = a[i] + b[i];
        {    
     }
Run Code Online (Sandbox Code Playgroud)

由于只初始化了64个线程,我假设并行添加了64个元素.

  • 如何添加其余元素?
  • warp调度程序如何决定分配哪些线程来添加最后36个元素?

我的主要问题是:

我不明白线程如何知道要操作的元素.

Jac*_*ern 6

您的卡具有计算能力3.0,请参见此处.

从"CUDA C编程指南"的表12中,2048您提到的计算能力的线程数是指每个多处理器的最大驻留线程数.这并不意味着您无法启动超过2048整体线程.例如,从该表的上面几行中,您可以读到x线程块网格的最大最大维数2^31-1.这意味着启动例如1d线程的线程网格是完全合法的8192.原因是该卡将在线程扭曲之间执行上下文切换,如本文所示:GPU中的上下文切换机制是什么?.

关于问题的第二部分,您对该add功能的实现在概念上是错误的.您将索引i用作线程索引和for循环索引.更正确的实现如下

__global__ void add(int* a,int* b,int* c)
{
    int i = threadIdx.x;
    c[i] = a[i] + b[i];
}
Run Code Online (Sandbox Code Playgroud)

上面的写法意味着:每个线程将执行两个赋值,即

    int i = threadIdx.x;
    c[i] = a[i] + b[i];
Run Code Online (Sandbox Code Playgroud)

现在,例如,对于线程#3,threadIdx.x变量的值将是3.因此,线程#3将处理一个局部变量i,该变量是其内存空间的私有变量,其值将被赋值给3.此外,它将加载a[3]b[3]从全局内存中添加它们,将结果分配给全局内存,c[3]然后将最终结果存储到全局内存中.因此,当您启动网格时,您当然不能100仅通过64线程填充整个元素数组,您将需要100线程.

请注意,上述说明过于简单.我建议你阅读一些基本的教科书作为着名的CUDA示例.