Configuration 如何适当调整CUDA网格的大小并启动它?

Configuration 如何适当调整CUDA网格的大小并启动它?,configuration,cuda,shared-memory,Configuration,Cuda,Shared Memory,第一个问题: 假设我需要在具有1.3计算能力的特斯拉C1060上启动一个包含229080个线程的内核 因此,根据文档,这台机器有240个内核,每个对称多处理器上有8个内核,总共有30个SMs 对于“并发”运行的30720个线程,每个SM最多可以使用1024个线程 现在,如果我定义256个线程的块,这意味着每个SM可以有4个块,因为1024/256=4。因此,这些30720个线程可以在所有SMs的120个块中排列 现在以229080线程为例,我需要229080/256=~895(四舍五入)块来处理

第一个问题:

假设我需要在具有1.3计算能力的特斯拉C1060上启动一个包含229080个线程的内核

因此,根据文档,这台机器有240个内核,每个对称多处理器上有8个内核,总共有30个SMs

对于“并发”运行的30720个线程,每个SM最多可以使用1024个线程

现在,如果我定义256个线程的块,这意味着每个SM可以有4个块,因为1024/256=4。因此,这些30720个线程可以在所有SMs的120个块中排列

现在以229080线程为例,我需要229080/256=~895(四舍五入)块来处理所有线程

现在让我们假设我想调用一个内核,我必须使用那些229080线程,所以我有两个选择。第一个是将问题分解,以便在一个for循环中调用内核~8次,每次调用120个块和30720个线程(229080/30720)。这样我就可以确保设备完全被占用。另一个选项是使用895个块的网格为整个229080线程调用内核,在这种情况下,许多块将保持空闲,直到SM使用它拥有的8个块完成

那么,哪一个是首选方案?那些街区闲置等待有什么区别吗?他们需要资源吗

第二个问题

假设在我调用的内核中,我需要访问非合并的全局内存,因此可以选择使用共享内存

然后我可以使用每个线程从全局内存上的数组中提取一个值,比如说
global\u array
,它的长度是229080。现在,正如我正确理解的那样,在复制到共享内存时必须避免分支,因为块上的所有线程都需要到达
syncthreads()
调用,以确保它们都可以访问共享内存

这里的问题是,对于229080线程,我需要的正是229080/256=894.84375块,因为有216个线程的剩余。我可以将这个数字四舍五入,得到895个块,最后一个块将只使用216个线程

但是由于我需要从
global_array
中提取共享内存的值,该值的长度为229080,并且我不能使用条件语句来防止最后40个线程(256-216)访问
global_array
上的非法地址,那么在处理共享内存加载时,我如何避免这个问题呢

那么,哪一个是首选方案?那些街区闲置等待有什么区别吗?他们需要资源吗

根据您的描述,单个内核是首选的。排队但未分配给SM的ThreadBlock不会占用您需要担心的任何资源,而且机器的设计绝对可以处理类似的情况。在其他条件相同的情况下,8个内核调用的开销肯定会更慢

现在,正如我正确理解的那样,在复制到共享内存时必须避免分支,因为块上的所有线程都需要到达syncthreads()调用,以确保它们都可以访问共享内存

这种说法表面上是不正确的。您可以在复制到共享内存时进行分支。您只需确保:

  • \uuu syncthreads()
    在分支构造之外,或者
  • 分支构造中的所有线程都可以访问
    \uuuuxynchthreads()
    (这实际上意味着对于块中的所有线程,至少在
    \uxynchthreads()
    障碍所在的点上)
  • 请注意,上面的选项1通常是可以实现的,这使得代码更易于遵循,并且易于验证所有线程都可以到达屏障

    但是,由于我需要从长度为229080的全局_数组中提取共享内存的值,并且我不能使用条件语句来防止最后40个线程(256-216)访问全局_数组上的非法地址,那么在处理共享内存加载时,我如何避免这个问题呢

    这样做:

    int idx = threadIdx.x + (blockDim.x * blockIdx.x);
    if (idx < data_size)
      shared[threadIdx.x] = global[idx];
    __syncthreads();
    
    int-idx=threadIdx.x+(blockDim.x*blockIdx.x);
    if(idx<数据大小)
    共享的[threadIdx.x]=全局的[idx];
    __同步线程();
    
    这是完全合法的。块中的所有线程,无论它们是否参与到共享内存的数据复制,都将到达屏障

    那么,哪一个是首选方案?那些街区闲置等待有什么区别吗?他们需要资源吗

    根据您的描述,单个内核是首选的。排队但未分配给SM的ThreadBlock不会占用您需要担心的任何资源,而且机器的设计绝对可以处理类似的情况。在其他条件相同的情况下,8个内核调用的开销肯定会更慢

    现在,正如我正确理解的那样,在复制到共享内存时必须避免分支,因为块上的所有线程都需要到达syncthreads()调用,以确保它们都可以访问共享内存

    这种说法表面上是不正确的。您可以在复制到共享内存时进行分支。您只需确保:

  • \uuu syncthreads()
    在分支构造之外,或者
  • 分支构造中的所有线程都可以访问
    \uuuuxynchthreads()
    (这实际上意味着对于块中的所有线程,至少在
    \uxynchthreads()
    障碍所在的点上)
  • 请注意,上面的选项1通常是可以实现的,这使得代码更易于遵循,并且易于验证所有线程都可以到达屏障

    但是,由于我需要从长度为229080的全局_数组中提取共享内存的值,并且我不能使用条件语句来阻止最后40个线程(256-216)访问全局_数组上的非法地址,那么我如何才能绕过这个pro