我正在研究生成并行C ++代码的编译器。我是CUDA编程的新手,但我正在尝试将C ++代码与CUDA并行化。
目前,如果我有以下顺序C ++代码:
for(int i = 0; i < a; i++) {
for(int j = 0; j < b; j++) {
for(int k = 0; k < c; k++) {
A[i*y*z + j*z + k*z +l] = 1;
}
}
}
,这会产生以下CUDA代码:
__global__ void kernelExample() {
int _cu_x = ((blockIdx.x*blockDim.x)+threadIdx.x);
int _cu_y = ((blockIdx.y*blockDim.y)+threadIdx.y);
int _cu_z = ((blockIdx.z*blockDim.z)+threadIdx.z);
A[_cu_x*y*z + _cu_y*z + _cu_z] = 1;
}
所以每个循环嵌套都映射到一个维度,但是并行化四个或更多嵌套循环的正确方法是什么:
for(int i = 0; i < a; i++) {
for(int j = 0; j < b; j++) {
for(int k = 0; k < c; k++) {
for(int l = 0; l < d; l++) {
A[i*x*y*z + j*y*z + k*z +l] = 1;
}
}
}
}
有没有类似的方法?值得注意的是:所有循环维度都是并行的,迭代之间没有依赖关系。
提前致谢!
编辑:目标是将所有迭代映射到CUDA线程,因为所有迭代都是独立的,并且可以同时执行。
答案 0 :(得分:4)
你可以保持外环不变。另外,最好使用.x
作为最内层循环,以便access the global memory efficiently。
__global__ void kernelExample() {
int _cu_x = ((blockIdx.x*blockDim.x)+threadIdx.x);
int _cu_y = ((blockIdx.y*blockDim.y)+threadIdx.y);
int _cu_z = ((blockIdx.z*blockDim.z)+threadIdx.z);
for(int i = 0; i < a; i++) {
A[i*x*y*z + _cu_z*y*z + _cu_y*z + _cu_x] = 1;
}
}
但是,如果您的a,b,c,d
非常小,则可能无法获得足够的并行度。在这种情况下,您可以将线性索引转换为n-D索引。
__global__ void kernelExample() {
int tid = ((blockIdx.x*blockDim.x)+threadIdx.x);
int i = tid / (b*c*d);
int j = tid / (c*d) % b;
int k = tid / d % c;
int l = tid % d;
A[i*x*y*z + j*y*z + k*z + l] = 1;
}
但是要小心,计算i,j,k,l
可能会引入很多开销,因为整数除法和mod在GPU上很慢。作为替代方案,您可以将i,j
映射到.z
和.y
,并以类似的方式仅从k,l
计算.x
和更多维度。