c - 我什么时候应该忽略关键部分,什么时候需要 nowait ?OpenMp
问题描述
我正在研究 OpenMP,并且我有一些问题,我相信这些问题会澄清我的想法。
我有一个矩阵乘法 A*B 的小例子,其中 A,B,C 是全局变量。我知道我们如何一次并行化一个for循环,或者同时并行化一个循环,但我的问题是:
如果我使用哪个循环,我#pragma omp for
应该忽略check1中我们需要添加的关键部分,因为 C 是一个全局变量,并且我应该在哪个循环中使用关键字nowait以避免循环中的障碍,因为我知道#pragma omp for
它自动拥有它. 当我试图编程这个嵌套的 for 循环时,我正在这样做:my_approach
int i,j,sum;
for(int i=0;i<N;i++) # loop1
for(j=0;j<N;j++){ #loop2
for(k=sum=0;k<N;k++) #loop3
sum += A[i][j]*B[k][J]
C[i][j] = sum # check1
};
我的方法
#pragma omp parallel num_threads(4)
{
#pragma omp for schedule(static) nowait // **one**
for(int i=0;i<N;i++) # loop1
for(j=0;j<N;j++){ #loop2
for(k=sum=0;k<N;k++) #loop3
sum += A[i][j]*B[k][J]
#pragma omp critical // **two**
C[i][j] = sum # check1
};
}
- 一:我把“nowait”放在那里,因为代码运行得更快,我不知道原因或者我是否做出了正确的决定
- 二:我使用关键部分来思考如何使用线程构建它。
所以让我们说这是正确的,如果将第二个 for 循环或第三个并行化,我是否需要这些东西?如果有人可以在我需要添加关键部分时向我解释,或者如果我一次并行化这个嵌套的 for 循环,我将不胜感激!
解决方案
在您的示例中,您既不需要nowait
也不需要critical
:
#pragma omp parallel for schedule(static) num_threads(4) // **one**
for(int i=0;i<N;i++) # loop1
for(j=0;j<N;j++){ #loop2
for(k=0;k < N;k++) #loop3
C[i][j] += A[i][j]*B[k][J]
没有竞争条件,在更新全局矩阵期间C
,每个线程更新该矩阵的不同位置。但是,您有一个不同的竞争条件,即在更新变量j
和的过程中k
,因为两者都是在线程之间共享的,所以要修复这个竞争条件,只需将它们设为私有,例如,如下所示:
#pragma omp parallel for schedule(static) num_threads(4) // **one**
for(int i=0;i<N;i++) # loop1
for(int j=0;j<N;j++){ #loop2
for(int k=0;k < N;k++) #loop3
C[i][j] += A[i][j]*B[k][J]
一:我把“nowait”放在那里,因为代码运行得更快,我不知道原因或者我是否做出了正确的决定
好吧,您不应该在没有充分理由的情况下盲目地删除它。在这里您可以安全地删除,因为 1)在并行区域和并行区域之间没有使用代码,2)并行区域也有一个隐式屏障。
#pragma omp parallel num_threads(4)
{
#pragma omp for schedule(static) nowait // **one**
...
// There no code here
} // <-- implicit barrier
尽管如此,在您的情况下,您可以将两个 pragma 合并为一个并删除nowait
子句:
#pragma omp parallel for schedule(static) num_threads(4)
因此,假设这是正确的,那么并行化第二个for循环或第三个循环我是否需要这些东西?
一般的答案是取决于。它取决于太多的因素,但通常你应该从最外层的循环开始,因为这些循环会产生具有最高粒度的任务,但这又取决于具体情况。尽管如此,在您的具体示例中,您可以并行化最外层的循环。
您可以尝试并行化嵌套循环,看看您是否有任何性能提升。测试并行化最外层循环与并行化前两个最外层循环,并检查是否获得任何性能提升。
推荐阅读
- javascript - 获取来源时使用 Expo Stripe Payments 时取消重定向
- excel - 从另一个文件复制值
- laravel - Laravel + Inertia + Vuejs:分页
- swift - 迅速。收到 Apple 授权后如何申请成为默认浏览器的权限?
- javascript - 如何在 JavaScript 中将字符串转换为 JSON 对象?
- javascript - 同步函数中的 async/await - JavaScript
- react-native - React Native PanResponder onStartShouldSetPanResponder locationX 因平台而异
- java - performLongClick 在活动 android 中不起作用
- python - 为什么神经网络在正弦波回归上如此困难
- python - 如何在 python 中用不同的值模拟 requests.get.return_value