c++ - OpenMP For-Loops 在有和没有多线程的情况下产生不同的结果
问题描述
我是多线程的新手,在尝试并行化一些 for 循环时发现了以下问题,我在其中操作 3D 数组。当我只使用一个线程运行代码时,我得到了E_total
我期望的值。但是,当我对多线程和 OpenMP使用相同的代码时,我#pragma omp parallel for
按以下方式设置
// DO FIRST COMPUTATION STEP ON 3D ARRAY
#pragma omp parallel for
for (size_t ix = 0; ix < N; ix++) {
for (size_t iy = 0; iy < N; iy++) {
for (size_t iz = 0; iz < N; iz++) {
A1[ix][iy][iz] = ...;
}
}
}
// DO SECOND COMPUTATION --AFTER-- FIRST COMPUTATION
#pragma omp parallel for
for (size_t ix = 0; ix < N; ix++) {
for (size_t iy = 0; iy < N; iy++) {
for (size_t iz = 0; iz < N; iz++) {
A2[ix][iy][iz] = ...;
E_pot += something * A1[ix][iy][iz];
E_int += something * A2[ix][iy][iz];
}
}
}
E_total += (E_pot + E_int); // This result changes when 'omp parallel for' is used
我看到我得到了不同的结果 E_total
。由于循环操作是附加的或特定于网格点的(独立于不同的ijk
),因此它们不应依赖于循环内的任何排序。
是否有可能在所有先前的第一个循环操作完成之前启动第二个 for 循环?如果是这样,我该如何防止这种情况发生,或者我需要注意哪些其他错误?
抱歉,如果这是一个非常基本的问题,但我在网上找不到相关问题。提前致谢!
解决方案
这段代码的问题是不同线程之间存在竞争条件。和变量在工作线程之间共享E_pot
,E_int
因此线程不时地破坏彼此的值。
要解决此问题,请应用该reduction
子句(请参阅OpenMP API 规范中的Reduction Clauses and Directives ):
// DO SECOND COMPUTATION --AFTER-- FIRST COMPUTATION
#pragma omp parallel for reduction(+:E_pot) reduction(+:E_int)
for (size_t ix = 0; ix < N; ix++) {
for (size_t iy = 0; iy < N; iy++) {
for (size_t iz = 0; iz < N; iz++) {
A2[ix][iy][iz] = ...;
E_pot += something * A1[ix][iy][iz];
E_int += something * A2[ix][iy][iz];
}
}
}
您可以查看更多更改,看看它们是否有帮助:
根据它的值,N
可能值得在指令中添加一个collapse(2)
子句(请参阅Worksharing-Loop Construct)以parallel for
将两个外部循环合并为一个循环,然后运行该循环以进行N*N
迭代。对于 small N
,线程可以更好地工作,因为更多的迭代可以分布在工作线程中。
如果您schedule(static)
明确添加(当您什么都不说时,这是大多数 OpenMP 实现的默认设置,但技术上并不能保证),那么您可以添加nowait
到第一个循环。这样一来,在第一个并行循环结束时就没有隐含的障碍,并且已经完成其工作块的线程可以继续进行第二个循环。这schedule(static)
是需要的,因为第一个和第二个循环都具有相同的并行化,然后这个技巧就起作用了。注意:如果你collapse(2)
为第一个循环添加了,那么第二个循环也需要有,collapse(2)
这样并行化是一样的。
推荐阅读
- c++ - 如何使并行 cudaMalloc 快速?
- php - 单击创建图库按钮后没有响应
- android - 启用自动隐藏/显示后,BottomNavigationView 不显示
- javascript - React Native - “元素类型无效:需要字符串或类/函数但未定义” - 导入自定义库?
- c++ - 显示通用树的元素
- vue.js - Nuxt.js 路由
- python - 无法从 Jupyter Notebook 压缩文件
- javascript - 来自嵌套数组的 HTML 和 JS 随机生成器
- python - 如何用最大运算符制定纸浆目标函数
- r - 使用各种多进程方法在 R 中进行并行计算