如果这是一个愚蠢的问题,请原谅我,但我找不到任何类似的问题。
我想在第一个循环(在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中正确使用动态数组?
答案 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响应跨缓存线。