在这段源代码中,我们甚至有4个线程,内核函数可以访问所有10个数组。如何做到的?
#define N 10
__global__ void add(int *c){
int tid = threadIdx.x + blockIdx.x * gridDim.x;
if(tid < N)
c[tid] = 1;
while( tid < N)
{
c[tid] = 1;
tid += blockDim.x * gridDim.x;
}
}
int main(void)
{
int c[N];
int *dev_c;
cudaMalloc( (void**)&dev_c, N*sizeof(int) );
for(int i=0; i<N; ++i)
{
c[i] = -1;
}
cudaMemcpy(dev_c, c, N*sizeof(int), cudaMemcpyHostToDevice);
add<<< 2, 2>>>(dev_c);
cudaMemcpy(c, dev_c, N*sizeof(int), cudaMemcpyDeviceToHost );
for(int i=0; i< N; ++i)
{
printf("c[%d] = %d \n" ,i, c[i] );
}
cudaFree( dev_c );
}
为什么我们不创建10个线程,例如
add<<<2,5>>>或add<5,2>>>
?
因为我们必须创建合理数量的线程,如果N大于10,例如33*1024。
这段源代码是这种情况的示例。
数组有10个,CUDA线程有4个。
如何通过4个线程访问所有10个数组。
请参阅CUDA详细信息中关于threadIdx、blockIdx、blockDim、gridDim含义的页面。
在这段源代码中,
gridDim.x : 2 this means number of block of x
gridDim.y : 1 this means number of block of y
blockDim.x : 2 this means number of thread of x in a block
blockDim.y : 1 this means number of thread of y in a block
我们的线程数为4,因为2*2(块数*线程数)。
在添加内核函数时,我们可以访问线程的0、1、2、3索引
->tid = threadIdx.x + blockIdx.x * blockDim.x
①0+0*2=0
②1+0*2=1
③0+1*2=2
④1+1*2=3
如何访问其余的索引4、5、6、7、8、9。这里有一个while循环中的计算方法。
tid += blockDim.x + gridDim.x in while
**内核的第一次调用**
-1循环:0+2*2=4
-2循环:4+2*2=8
-3循环:8+2*2=12(但是这个值是错误的,因为已经超出了范围!)
**内核的第二次调用**
-1循环:1+2*2=5
-2循环:5+2*2=9
-3循环:9+2*2=13(但是这个值是错误的,因为已经超出了范围!)
**内核的第三次调用**
-1循环:2+2*2=6
-2循环:6+2*2=10(但是这个值是错误的,因为已经超出了范围!)
**内核的第四次调用**
-1循环:3+2*2=7
-2循环:7+2*2=11(但是这个值是错误的,因为已经超出了范围!)
因此,所有索引为0、1、2、3、4、5、6、7、8、9的值都可以通过tid值访问。
请参考此页面。
http://study.marearts.com/2015/03/to-process-all-arrays-by-reasonably.html
由于声望不足,我无法上传图片。