并行化具有依赖性的代码

时间:2016-08-12 19:26:39

标签: parallel-processing cuda openmp hpc

我的代码如下:

数组a包含有关其所属组的信息。即元素i属于组a[i]。每个组可以包含两个元素。我想将这些信息存储在长度为2*number组的b中。因此,b[j]b[j+1]的值会为我提供属于组j/2(整数除法)且j为偶数的元素。

void assign(int *a, int *b){
    for(int i = 0; i<N; i++){
        int group = a[i];
        int posit=2*group;
        if(b[2*i]!=0){
            posit++;
        }
        b[posit] = i;
    }
}

N as is clear length of a.

默认情况下,b []中的值为零,表示没有元素。

有明确的数据依赖性,看起来并不容易并行化。如果有一种我缺少的聪明方式,我正在寻找进一步的建议。

1 个答案:

答案 0 :(得分:1)

通常,您可以尝试在包含对{i, a[i]}的数组上简单地使用并行排序算法。也许有一种更快的通用方法,我目前看不到......

然而,在CUDA中,你可以利用这样一个事实:当你有2个冲突的线程将32位字写入同一个内存位置时 - 一个保证成功(你不知道哪一个虽然)。形式上,它充当Arbitrary CRCW机器。

因此,您可以在2个内核调用中解决您的问题:

__global__ void assign1(int* a, int* b, int elementCount) {
    int idx = threadIdx.x + blockIdx.x*blockDim.x;
    if (idx<elementCount) {
        int group = a[idx];
        b[2*group] = idx;
    }
}

__global__ void assign2(int* a, int* b, int elementCount) {
    int idx = threadIdx.x + blockIdx.x*blockDim.x;
    if (idx<elementCount) {
        int group = a[idx];
        if (b[2*group] != idx)
            b[2*group+1] = idx;
    }
}

__host__ void assign(int* dev_a, int* dev_b, int elementCount) {
    int gridSize = elementCount/512+1;
    int blockSize = 512;
    assign1<<<gridSize,blockSize>>>(dev_a, dev_b, elementCount);
    assign2<<<gridSize,blockSize>>>(dev_a, dev_b, elementCount);
}

assign1中,最多2个线程写入相同的内存位置b[2*group]。其中一个线程保证成功。在assign2写入失败的线程中,使用b[2*group+1]重复该过程。

如果组中最多有3个或4个元素,则可以重复此方法,但随着数字越来越高,它很快就会停止运行。