使用CUDA并行化四个或更多嵌套循环

时间:2016-06-08 16:31:34

标签: c++ loops parallel-processing cuda

我正在研究生成并行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线程,因为所有迭代都是独立的,并且可以同时执行。

1 个答案:

答案 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和更多维度。