Fortran 如何使每个线程知道openmp中的变量值

Fortran 如何使每个线程知道openmp中的变量值,fortran,openmp,Fortran,Openmp,下面的伪代码来自我正在运行的Fortran应用程序 我的问题是,当调用子程序a时,j没有取正确的值 !$omp parallel do do i = 1, limit j = i+k call subroutine_a(j) end do !$omp end parallel do 例如,如果它在4个线程中运行,则每个线程必须具有j=1,j=2,j=3,j=4。现在,所有4个线程中的j可能都是1。您所经历的情况称为竞争条件。所有线程都写入相同的共享变量j,因此它或多或少是随机的

下面的伪代码来自我正在运行的Fortran应用程序

我的问题是,当调用
子程序a
时,
j
没有取正确的值

!$omp parallel do
do i = 1, limit
    j = i+k
    call subroutine_a(j)
end do
!$omp end parallel do

例如,如果它在4个线程中运行,则每个线程必须具有
j=1
j=2
j=3
j=4
。现在,所有4个线程中的
j
可能都是
1

您所经历的情况称为竞争条件。所有线程都写入相同的共享变量
j
,因此它或多或少是随机的,哪些值将被赋予子例程

您有两种可能解决此问题:

  • 完全避免(如果可以,即如果以后不再使用
    j
    ):
  • 声明
    j
    private,s.t.每个线程都有自己的
    j
    版本:

  • 我想我也需要保密

    注意,第一个可能不可能,因为参数现在是表达式而不是变量。[完全取决于我们不知道的东西。]@francescalus这通常是正确的(我们不知道用
    j
    还能做些什么),但提供的代码片段1除外。是一个有效选项(
    j
    不再使用)。同意-如果允许,这是一个完全有效的选项。@francescalus I澄清了答案;-)@alexander vogt将其指定为private不起作用,因为j在循环之前和之后都存在。这给了j与预期非常不同的结果。我用一些虚拟代码填充变量以获得输出,我将更新问题以查看。[我不是OpenMP方面的专家,但是…]使用
    j=I+j
    进行编辑是否会在两个方面显著改变问题?有一个私有/现有的问题,在迭代过程中缺乏一个明确的“顺序”。你是对的,可能是这样,但我正在尝试写一些简化的东西,以使其有意义,因为我尝试并行化的代码是5k+行,我以前从未摆弄过openmp。我认为这个问题的前一个版本是有效的,你得到了一个很好的答案,所以后退可能是最好的。你总是可以问一个涉及新领域的新问题(链接回这个问题)。也就是说,Alexander Vogt可能比我更了解这些方面的价值。好的,我将删除多余的内容并输入一个新问题。这不是真的,所有循环计数器在OMP DO中都是隐式私有的。感谢您的澄清!我不知道,但这是有道理的。对于没有并行化的嵌套循环也是这样吗?显然是的,Hristo Iliev在某个地方对此给出了回答或评论,但我通常将它们声明为显式私有。
    !$omp parallel do
    do i = 1, limit
        call subroutine_a(i+k)
    end do
    !$omp end parallel do
    
    !$omp parallel do private(j)
    do i = 1, limit
        j = i+k
        call subroutine_a(j)
    end do
    !$omp end parallel do