具有动态数组分配功能的OpenMP嵌套循环

时间:2018-07-11 14:22:59

标签: c++ arrays dynamic parallel-processing openmp

如果这是一个愚蠢的问题,请原谅我,但我找不到任何类似的问题。

我想在第一个循环(在C ++中)中使用OpenMP并行将值分配给3d动态数组。

int i, j, k;
int ***data;
const int NEL = 100;
const int NINT = 2;
data = new int**[NEL];
for (i = 0; i < NEL; i++) {
    data[i] = new int*[NINT*NINT*NINT];
    for (j = 0; j < NINT*NINT*NINT; j++) {
        data[i][j] = new int[NINT*NINT*NINT];
    }
}
#pragma omp parallel for 
for (i = 0; i < NEL; i++) {
    for (j = 0; j < NINT*NINT*NINT; j++) {
        for (k = 0; k < NINT*NINT*NINT; k++) {
            data[i][j][k] = 1;
        }
    }
}

我只想让最外面的循环(i)与嵌套循环(j和k)顺序执行并行执行。但是编译器每次都会抛出访问冲突错误。

如果我将动态数组更改为本地数组,它将毫无问题地工作。

int i, j, k;    
const int NINT = 2;
const int NEL = 100;
int data[NEL][NINT*NINT*NINT][NINT*NINT*NINT];
#pragma omp parallel for 
for (i = 0; i < NEL; i++) {
    for (j = 0; j < NINT*NINT*NINT; j++) {
        for (k = 0; k < NINT*NINT*NINT; k++) {
            data[i][j][k] = 123;
        }
    }
}

我正在使用已启用OpenMP功能的Visual Studio 2015。是否因为VS 2015中的OpenMP版本仅为2.0?还是我没有在OpenMP中正确使用动态数组?

2 个答案:

答案 0 :(得分:2)

您需要在并行区域内声明循环变量,最好这样做

 #pragma omp parallel for 
 for (int i = 0; i < NEL; i++) {
    for (int j = 0; j < NINT*NINT*NINT; j++) {
      for (int k = 0; k < NINT*NINT*NINT; k++) {
        data[i][j][k] = 1;
      }
    }
 }

否则,默认情况下将共享循环变量,这可能导致对data的越界访问

通常,这里最好使用std::vector

std::vector<std::vector<std::vector<int >  > > data;

如果您选择性能,则要使用连续内存

std::vector<int> data;

,然后通过动态建立索引来访问data

data[k+pow(NINT,3)*j+pow(NINT,6)*i] = 1;

最好在此处使用小的索引功能,以使数据访问更容易

int dataIndex(int i, int j, int k, int NINT){return k+pow(NINT,3)*j+pow(NINT,6)*i;}

,然后以{p>的身份访问data

data[dataIndex(i,j,k,NINT)]=1;

编译器很可能会内联函数,这样函数调用就不会产生任何额外费用。

答案 1 :(得分:1)

尝试将pramga更改为;

#pragma omp parallel for shared(data) private(i,j,k) 

但是,在我的评论中,您正在并行处理大量线程,但是给每个线程分配少量工作,这意味着与实际收益相比,调度它们的开销将非常大。

最重要的是,在大多数系统上,2 * 2 * 2 * sizeof(int)可能小于高速缓存行,这意味着2个线程可能会尝试同时写入同一行,从而导致错误冲突和ping响应跨缓存线。