openMP 并行部分中的共享变量有些奇怪

Posted

技术标签:

【中文标题】openMP 并行部分中的共享变量有些奇怪【英文标题】:Something strange with shared variable in openMP parallel sections 【发布时间】:2015-01-15 02:36:02 【问题描述】:

我在openMP 发现了一个奇怪的现象,带有共享货币和打印功能。

我在C++Fortran 都测试过这个问题。

在 C++ 中:

#include <omp.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h> 
int main (int argc, char *argv[]) 

int i=1;

#pragma omp parallel sections shared(i)
  
    #pragma omp section
    while(true)
        i = 1;
        printf("thread 1: %i\n", i);
    
    #pragma omp section
    while(true)
        i = i - 1000;
        printf("thread 2: %i\n", i);
    
  


这段代码很简单,预期的结果是这样的:

thread 1: 1
thread 2: -999
thread 1: 1
thread 2: -999
thread 2: -1999
thread 1: 1

但是,我可以得到这个结果:

thread 1: 1
thread 2: -1726999
thread 2: -1727999
thread 2: -1728999
thread 2: -1729999
thread 2: -1730999
thread 2: -1731999
thread 2: -1732999

这很混乱,看起来我没有共享!我试图评论这一行:

printf("thread 1: %i\n", i);

得到:

thread 2: 1
thread 2: -999
thread 2: 1
thread 2: 1
thread 2: -999
thread 2: 1

现在看起来不错。

在 Fortan:

OpenMP 在 Fortran 中的表现略有不同。

PROGRAM test
implicit none
integer*8 i
i = 1
 !$OMP parallel sections shared(i)
    !$OMP section
        do 
            i = 1 
            print *, "thread 1" ,i
            !call sleep(1)
        end do
    !$OMP section
        do 
            i = i-1000
            print *, "thread 2" ,i
            !call sleep(1)
        end do
 !$OMP end parallel sections
END PROGRAM

此代码导致与上述相同的问题。但是如果我评论线程1的打印,问题仍然存在。

我必须添加sleep 子程序作为注释行以获得预期的结果。

有人知道原因吗?

另一个问题,变量在一个线程中被修改的同时在另一个线程中被读取吗?

【问题讨论】:

【参考方案1】:

您正在从多个线程修改共享变量,但没有同步。这被称为数据竞赛。您的程序的结果是未指定的 - 任何事情都可能发生。如果您在一个线程中写入变量并在没有同步的情况下从另一个线程中读取,这同样适用。

有关详细信息,请参阅the OpenMP 4.0 standard 的第 1.4.1 节。

【讨论】:

谢谢,所以在我的程序中,如果我必须在多线程中访问变量,推荐使用哪种方法?锁还是屏障? @PaleNeutron 在你的程序中,看到“大图”有点困难......通常存在多个线程只是为了改变同一个变量的值。通常,这正是要避免的。

以上是关于openMP 并行部分中的共享变量有些奇怪的主要内容,如果未能解决你的问题,请参考以下文章

如何并行化使用 boost?

OpenMP的主要功能,基本构成体都有哪些

如果共享堆栈或数据变量,OpenMP 是不是会将它们移动到堆中?

多个 OpenMP 线程读取(不写入)共享变量的性能成本?

OpenMP数据处理子句

Chapel中的共享记忆n体仿真