在这个源代码中,我们甚至有 4 个线程,内核函数可以访问所有 10 个数组。如何?
#define N 10 //(33*1024)
__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 个线程 ex)add<<<2,5>>> or add<5,2>>>
因为我们必须创建相当少量的线程,如果 N 大于 10 ex) 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(blocks * thread)。
在添加内核函数中,我们可以访问线程的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 loop: 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
我无法上传图片,因为声誉低。