openmp/C++ 简单并行区域 returns 不一致的结果
openmp/C++ simple parallel region returns incosistent results
所以我正在尝试学习 OpenMP API,我已经掌握了基础知识,但这部分让我感到困惑:(可测试的代码!)
#include <iostream>
#include <cstdlib>
#include <string>
#include <omp.h>
#include <unistd.h>
using namespace std;
const int col = 10, row = 10;
int c[][11] = {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} };
int main(int argc, char** argv)
{
int temp[3] = {-1, -1, -1};
int id;
for (unsigned short i = 0; i < 10; i++){
#pragma omp parallel shared(c) firstprivate(i) private(temp)
{
#pragma ivdep
#pragma omp for schedule(static, 1) //private(id)//,m_i, ind)
for(unsigned short j = 0; j < 10; j++){
// calculate c
/* old
temp[0] = c[i-1][j-1]+3;
temp[1] = c[i-1][j]-4;
temp[2] = c[i][j-1]-5;
c[i][j] = temp[0];
c[i][j] = temp[1];
c[i][j] = temp[2];
*/
temp[0] = c[i][j-1]+3;
c[i][j] = temp[0];
}
}
}
// print c
for (int i = 0; i< row + 1; i++)
{
for (int j = 0; j< col + 1; j++)
{
cout << c[i][j] << "/";
}
cout << endl;
}
} // end main
我相信代码是不言自明的,我只想补充一点,我只想并行化内部循环,因为我希望外部循环与 c
数组中的依赖项一起使用。
另外 row
和 col
变量可用于控制数组的维度。
我使用这个 bash 脚本来 运行 整件事
#!/bin/bash
g++ -O0 -o xx par_test.cpp -fopenmp
export OMP_NUM_THREADS=1 # or 2 or 4
./xx
但是当我使用超过 1 个线程时,输出会有所不同。
OMP_NUM_THREADS=1
的输出(一致)
OMP_NUM_THREADS=2
的输出(每次执行 returns 都不同)
OMP_NUM_THREADS=4
的输出(每次执行 returns 都不同)
我也试过的东西:
- 带和不带矢量化(即带和不带#pragma ivdep)
threadprivate(temp)
这里也没有运气。
由于单线程执行总是有相同的输出,我相当确定我的变量共享有问题,尽管如此我却没有..
提前感谢您的宝贵时间。
您正在此处对 j
进行并行循环:
#pragma omp for schedule(static, 1)
for(unsigned short j = 0; j < 10; j++){
// calculate c
temp[0] = c[i][j-1]+3;
c[i][j] = temp[0];
}
您引用了单元格 c[i][j-1]
,但该值可能是在另一个线程中计算的。你怎么能确定这已经发生了?
所以我正在尝试学习 OpenMP API,我已经掌握了基础知识,但这部分让我感到困惑:(可测试的代码!)
#include <iostream>
#include <cstdlib>
#include <string>
#include <omp.h>
#include <unistd.h>
using namespace std;
const int col = 10, row = 10;
int c[][11] = {{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1} };
int main(int argc, char** argv)
{
int temp[3] = {-1, -1, -1};
int id;
for (unsigned short i = 0; i < 10; i++){
#pragma omp parallel shared(c) firstprivate(i) private(temp)
{
#pragma ivdep
#pragma omp for schedule(static, 1) //private(id)//,m_i, ind)
for(unsigned short j = 0; j < 10; j++){
// calculate c
/* old
temp[0] = c[i-1][j-1]+3;
temp[1] = c[i-1][j]-4;
temp[2] = c[i][j-1]-5;
c[i][j] = temp[0];
c[i][j] = temp[1];
c[i][j] = temp[2];
*/
temp[0] = c[i][j-1]+3;
c[i][j] = temp[0];
}
}
}
// print c
for (int i = 0; i< row + 1; i++)
{
for (int j = 0; j< col + 1; j++)
{
cout << c[i][j] << "/";
}
cout << endl;
}
} // end main
我相信代码是不言自明的,我只想补充一点,我只想并行化内部循环,因为我希望外部循环与 c
数组中的依赖项一起使用。
另外 row
和 col
变量可用于控制数组的维度。
我使用这个 bash 脚本来 运行 整件事
#!/bin/bash
g++ -O0 -o xx par_test.cpp -fopenmp
export OMP_NUM_THREADS=1 # or 2 or 4
./xx
但是当我使用超过 1 个线程时,输出会有所不同。
OMP_NUM_THREADS=1
的输出(一致)
OMP_NUM_THREADS=2
的输出(每次执行 returns 都不同)
OMP_NUM_THREADS=4
的输出(每次执行 returns 都不同)
我也试过的东西:
- 带和不带矢量化(即带和不带#pragma ivdep)
threadprivate(temp)
这里也没有运气。
由于单线程执行总是有相同的输出,我相当确定我的变量共享有问题,尽管如此我却没有..
提前感谢您的宝贵时间。
您正在此处对 j
进行并行循环:
#pragma omp for schedule(static, 1)
for(unsigned short j = 0; j < 10; j++){
// calculate c
temp[0] = c[i][j-1]+3;
c[i][j] = temp[0];
}
您引用了单元格 c[i][j-1]
,但该值可能是在另一个线程中计算的。你怎么能确定这已经发生了?