1

我正在尝试使用 OpenMP/CilkPlus 将 test_function main 内部的 for 循环中的函数调用并行(如 C 代码所示)。对于每次迭代,读/写操作仅发生在 2d_array 的一行上,因此迭代中没有数据依赖性(2d_array 在可用线程之间共享,默认情况下 i 是私有的)。

void test_function(int *in, int len)
{
    int i, value; 
    int *x, *low, *high;
    x = x_alloc + 4;
    for (i=0; i<len; i++)
        x[i] = in[i];

    for(i=1;i<=4;i++) 
    {
        x[-i] = x[i];
        x[(len-1) + i] = x[(len-1) - i];
    }

    high = malloc(sizeof(int)*((len>>1) + 1));

    for(i=0; i < ((len>>1) + 1); i++)
    {
        value = x[-4 + 2*i] + x[2 + 2*i] + x[-2 + 2*i] + x[2*i];
        high[i] = x[-1 + 2*i] - value;
    }

    low = malloc(sizeof(int)*(len>>1));

    for(i = 0; i < (len>>1); i++) 
    {
        value = high[i] + high[i + 1];
        low[i] = x[2*i] - value;
    }
    for (i=0; i<(len>>1); i++)
        in[i] = low[i];
        in[i+(len>>1)] = high[i+1];

    free(low);
    free(high);
}

int main{...}
...
int **2d_array;

...
#pragma omp parallel for
for(i = 0; i < height; i++){
    test_function(2d_array[i], width);
}

无论如何,结果是错误的。还尝试了 cilk_for 而不是 OpenMP 编译指示。在每次迭代期间更改每一行时,是否有特定的方法来处理 2D 数组?

4

2 回答 2

1

问题是变量x指向每个线程的相同内存地址。要解决此问题,请执行以下操作

x = malloc(sizeof(int)*(len+8));

里面test_function

这是在 OpenMP 中使用指针的常见错误来源。如果你这样做&x,你会看到每个线程都有不同的内存地址x。因此,指针实际上是私有的,但是当您执行x = x_alloc + 4;每个指针指向的内存地址时,它们是相同的。这实际上就像拥有一个共享数组,但您确实希望每个线程都有一个私有数组。因此,您必须为线程分配空间并将每个私有指针设置为该私有空间。

如果您想避免x为每次迭代分配和取消分配,您可以尝试这样的事情

#pragma omp parallel
{
    int *x;
    x = malloc(sizeof(int)*(len+8));
    #pragma omp for
    for(i = 0; i < height; i++){
        test_function(2d_array[i], width, x);
    }
    free(x);
}

现在test_funciton需要x作为参数的地方。

于 2014-09-30T09:56:03.150 回答
1

请注意,对 malloc 的调用可能是线程安全的,但可能会锁定堆,从而产生争用并限制加速。

  • 巴里
于 2014-09-30T20:43:11.353 回答