不是所有的线程都在OpenMP中打印



我正在尝试使用OpenMP为工作项目添加多线程。我在Visual Studio 2017中使用Fortran77,在尝试调试时,发现了一个我不完全理解的行为。

我是OpenMP的新手,所以这可能是对多线程机制的误解,但我的理解是,如果我在do循环中有一个写语句,每个线程都应该打印出这个写语句。为了简单起见,我在一个小项目中重新创建了我的问题。

有此问题的子例程应该在调用另一个简单子例程之前打印正在操作的线程,然后打印变量的值(该值为1):

SUBROUTINE TAKEVAR(VAR)
USE OMP_LIB
INTEGER:: VAR

VAR = VAR + 1
!$OMP PARALLEL NUM_THREADS(4)
!$OMP DO
DO i = 1, 5
WRITE(*, *) 'Hello from thread ', OMP_GET_THREAD_NUM()
WRITE(*, *) VAR 
CALL ROUTINE2(VAR)
ENDDO
!$OMP END DO
!$OMP END PARALLEL
END SUBROUTINE

但是,这个子程序的输出如下所示:

输出(还不能嵌入图像)

我看到循环使用4个线程执行了5次,这是正确的,但是每个显示线程号的语句后面都没有变量的值。有办法解决这个问题吗?

由于每个线程与其他线程同时执行,因此无法保证在给定线程的第一次和第二次WRITE之间不会发生其他线程的WRITE操作。

@Laci给出了一个可能的解决方案:

!$OMP CRITICAL
WRITE(*, *) 'Hello from thread ', OMP_GET_THREAD_NUM()
WRITE(*, *) VAR 
!$OMP END CRITICAL

临界区内的代码一次只能由一个线程执行,因此在两次WRITE之间不能执行任何操作。但是临界区会影响性能…

另一个解决方案是使用单个WRITE指令:

WRITE(*, *) 'Hello from thread ', OMP_GET_THREAD_NUM(), VAR

也就是说,我有过在并行区域写的糟糕经历(执行时崩溃),所以我倾向于总是把它们放在临界区。

最新更新