gpt4 book ai didi

cuda - CUDA 线程如何工作

转载 作者:行者123 更新时间:2023-12-05 00:52:59 31 4
gpt4 key购买 nike

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

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

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

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

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

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

我的主要问题是:

我不明白线程如何知道要操作哪些元素。

最佳答案

您的卡具有计算能力 3.0,请参阅 here .

根据 CUDA C 编程指南的表 12,您提到的计算能力的 2048 线程数是指每个多处理器的最大常驻线程数。这并不意味着您不能启动超过 2048 个线程。例如,从该表上方的几行中,您可以看到线程 block 网格的最大 x 维数是 2^31-1。这意味着启动 1d 线程网格(例如 8192 线程)是完全合法的。原因是该卡将在线程扭曲之间执行上下文切换,如本文所述:What is the context switching mechanism in GPU? .

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

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

上面写法的意思是:每个线程都会执行两次赋值,即

    int i = threadIdx.x;
c[i] = a[i] + b[i];

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

请注意,上面的解释过于简单了。我建议您阅读一些基础教科书,例如著名的 CUDA By Example。

关于cuda - CUDA 线程如何工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21721577/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com