我对线程的形成和执行方式有很多疑问.
首先,文档将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个元素.
我的主要问题是:
我不明白线程如何知道要操作的元素.
您的卡具有计算能力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示例.
归档时间: |
|
查看次数: |
1170 次 |
最近记录: |