如何确保在OpenMP中动态分配的数组是私有的

14

我正在使用gcc在Linux机器上用openMP处理C语言。在一个openmp的并行for循环中,我可以将一个静态分配的数组声明为私有的。考虑下面的代码片段:

int a[10];
#pragma omp parallel for shared(none) firstprivate(a)
for(i=0;i<4;i++){

如果我使用动态分配内存而非静态分配,在使用时一切都正常工作。

int * a = (int *) malloc(10*sizeof(int));
#pragma omp parallel for shared(none) firstprivate(a)

a的值(至少a[1...9])没有保护,但它们表现得好像是共享的。这是可以理解的,因为pragma命令中似乎没有告诉omp需要私有化多大的数组a。我应该如何向OpenMP传递这些信息?如何声明整个动态分配的数组为私有?

2个回答

15
我认为你还没有 - 我解决这个问题的方法是使用了一个并行区域 #pragma omp parallel shared(...) private(...) 并在并行区域内动态分配数组。尝试一下这个:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

/* compile with gcc -o test2 -fopenmp test2.c */

int main(int argc, char** argv)
{
    int i = 0;
    int size = 20;
    int* a = (int*) calloc(size, sizeof(int));
    int* b = (int*) calloc(size, sizeof(int));
    int* c;

    for ( i = 0; i < size; i++ )
    {
        a[i] = i;
        b[i] = size-i;
        printf("[BEFORE] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }

    #pragma omp parallel shared(a,b) private(c,i)
    {
        c = (int*) calloc(3, sizeof(int));

        #pragma omp for
        for ( i = 0; i < size; i++ )
        {
            c[0] = 5*a[i];
            c[1] = 2*b[i];
            c[2] = -2*i;
            a[i] = c[0]+c[1]+c[2];

            c[0] = 4*a[i];
            c[1] = -1*b[i];
            c[2] = i;
            b[i] = c[0]+c[1]+c[2];
        }

        free(c);
    }

    for ( i = 0; i < size; i++ )
    {
        printf("[AFTER] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }
}

这对我来说产生了与我之前的实验程序相同的结果:

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

/* compile with gcc -o test1 -fopenmp test1.c */

int main(int argc, char** argv)
{
    int i = 0;
    int size = 20;
    int* a = (int*) calloc(size, sizeof(int));
    int* b = (int*) calloc(size, sizeof(int));

    for ( i = 0; i < size; i++ )
    {
        a[i] = i;
        b[i] = size-i;
        printf("[BEFORE] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }

    #pragma omp parallel for shared(a,b) private(i)
    for ( i = 0; i < size; i++ )
    {
        a[i] = 5*a[i]+2*b[i]-2*i;
        b[i] = 4*a[i]-b[i]+i;
    }

    for ( i = 0; i < size; i++ )
    {
        printf("[AFTER] At %d: a=%d, b=%d\n", i, a[i], b[i]);
    }
}

猜测可能是因为OpenMP无法推断数组的大小,所以它不能是私有的 - 只有编译时数组可以这样做。当我尝试将动态分配的数组设为私有时,会出现段错误,可能是由于访问冲突引起的。在每个线程上分配数组,就好像你使用pthread一样,这是有意义的,并解决了这个问题。

谢谢,将OpenMP声明和并行for循环声明分开似乎完美解决了问题。 - cboettig
@Ninefingers:我知道这篇文章很旧了,但我有一个快速的问题。你真的需要#pragma omp for语句吗?它不会自动并行执行循环吗? - Amit
1
@Amit 不对,你需要告诉编译器退出线程,否则它不会退出。 - user257111

9
您告诉OpenMP指针a是私有的,即在每个线程中复制。您的数组只是一些任意数据a指向的内容,而OpenMP不会复制它(可能是因为这样做会使得必须分配和释放复制的数组)。

1
那么如何让OpenMP为每个线程创建一个数组呢?在我的情况下,有一个缓冲数组,每个线程都需要自己的。 - Royi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接