我对线程的形成和执行方式有很多疑问.
首先,文档将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 次 |
| 最近记录: |