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

OpenMP nested loop with dynamic array assignment

本文关键字:OpenMP 嵌套循环 分配 数组 动态      更新时间:2023-10-16

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

我想在第一个循环中(在C++中(将值分配给一个具有OpenMP并行的三维动态数组。

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的动态数组?

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

#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;

然后通过建立动态索引来访问CCD_ 3

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;}

然后作为访问CCD_ 4

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

编译器很可能会内联函数,这样函数调用就不会有额外的开销。

尝试将pramga更改为;

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

然而,为了扩展我的评论,您正在对大量线程进行并行化,但给每个线程都提供了少量的工作,这意味着与实际好处相比,调度它们的开销将非常大。

最重要的是,在大多数系统上,2*2*2*sizeof(int(可能小于缓存行,这意味着两个线程可能会同时尝试写入同一行,从而导致错误冲突并在缓存之间对该行进行ping。