Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/fortran/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在没有外部标志的情况下仅在Fortran OpenMP循环中运行一次代码?_Fortran_Openmp_Fortran90 - Fatal编程技术网

如何在没有外部标志的情况下仅在Fortran OpenMP循环中运行一次代码?

如何在没有外部标志的情况下仅在Fortran OpenMP循环中运行一次代码?,fortran,openmp,fortran90,Fortran,Openmp,Fortran90,通过Fortran中的某种模式,是否可以在循环迭代开始时分配变量一次且仅分配一次? 类似于下面的伪代码。我现在有一个If语句,它检查是否设置了一个标志,如果设置了标志,我们将执行If语句。然后我们取消设置它,因为我的程序是并行的,所以我希望避免在最里面的循环中出现条件分支。从我所看到的,在C++中是可能的,但是我想知道我是否可以在FORTRAN中实现同样的事情。 我要找的是: !$OMP DO PRIVATE(variable) DO i = 0, N = 100000 <Set Var

通过Fortran中的某种模式,是否可以在循环迭代开始时分配变量一次且仅分配一次? 类似于下面的伪代码。我现在有一个If语句,它检查是否设置了一个标志,如果设置了标志,我们将执行If语句。然后我们取消设置它,因为我的程序是并行的,所以我希望避免在最里面的循环中出现条件分支。从我所看到的,在C++中是可能的,但是我想知道我是否可以在FORTRAN中实现同样的事情。 我要找的是:

!$OMP DO PRIVATE(variable)
DO i = 0, N = 100000

<Set Variable to a fixed value once and only once at the start of the iteration>

<CODE>

END DO
!$END OMP DO
我所拥有的

!$OMP DO PRIVATE(variable)
DO i = 1, N = 100000 

    IF (FLAG_IS_SET) THEN
       <Set variable>
       <UNSET_THE_FLAG>
    END IF

    <CODE>

END DO
!$END OMP DO

一个简单的解决方案是跨线程手动共享迭代。假设100000是
n_线程的倍数

!$OMP PARALLEL PRIVATE(variable)
i_thread = omp_get_thread_num()
n_threads = omp_get_num_threads()
chunk_size = 100000 / n_threads
i_start = i_thread * chunk_size + 1
<Set variable>
DO i = i_start, i_start + chunk_size - 1
    <CODE>
END DO
!$OMP END PARALLEL

它避免了最内部循环中的条件分支,并且很可能接近编译器对静态调度所做的操作。

一个简单的解决方案是跨线程手动共享迭代。假设100000是
n_线程的倍数

!$OMP PARALLEL PRIVATE(variable)
i_thread = omp_get_thread_num()
n_threads = omp_get_num_threads()
chunk_size = 100000 / n_threads
i_start = i_thread * chunk_size + 1
<Set variable>
DO i = i_start, i_start + chunk_size - 1
    <CODE>
END DO
!$OMP END PARALLEL

它避免了最内层循环中的条件分支,并且很可能接近编译器对静态调度所做的操作。

我不清楚您想做什么。 如果你想按照你说的去做(“在循环迭代开始时只分配一次变量”),这完全是自然而然的

!$OMP DO PRIVATE(variable)
DO i = 0, N = 100000
variable = f(i)        ! Assign value to the local variable at the start of each iteration
<CODE>
END DO
!$END OMP DO
因为变量是线程私有的,所以每个线程中都有一个副本,您可以为变量的每个实例分配一次


但这似乎很容易,也许我不明白你到底想做什么

我不清楚你想做什么。 如果你想按照你说的去做(“在循环迭代开始时只分配一次变量”),这完全是自然而然的

!$OMP DO PRIVATE(variable)
DO i = 0, N = 100000
variable = f(i)        ! Assign value to the local variable at the start of each iteration
<CODE>
END DO
!$END OMP DO
因为变量是线程私有的,所以每个线程中都有一个副本,您可以为变量的每个实例分配一次



但这似乎很容易,也许我不明白你到底想做什么

为什么不能在进入循环之前设置变量?我不知道我有多少线程,我的常量取决于循环生成的I值$OMP DO指令。因此,在执行指令之前,我不知道要分配什么值。建议您编辑问题标题以表明这是一个openmp问题。首先,抱歉,我对openmp了解不多,因此可能是胡说八道。openmp语句中没有
PARALLEL
所以您已经创建了
$OMP PARALLEL
区域优先,如果是这样,在进入循环之前,您不应该知道您有多少线程(允许您在循环之前设置变量)?或者变量既取决于线程的数量,也取决于循环的“分块”方式?如果是这样的话,您使用的是默认(静态?)计划吗?那么它本质上就是OMP运行时分配给每个线程的第一次迭代的次数?如果是这样的话,就像上面一样,使用私有标志并使用该标志的值来检测分配给线程的第一次迭代。为什么不能在进入循环之前设置变量?我不知道我有多少个线程,我的常量取决于$OMP DO指令。因此,在执行指令之前,我不知道要分配什么值。建议您编辑问题标题以表明这是一个openmp问题。首先,抱歉,我对openmp了解不多,因此可能是胡说八道。您的openmp语句中没有
并行
,因此您已经创建了
$OMP PARALLEL
区域优先,如果是这样,在进入循环之前,您不应该知道您有多少线程(允许您在循环之前设置变量)?或者变量既取决于线程的数量,也取决于循环的“分块”方式?如果是这样的话,您使用的是默认(静态?)计划吗?那么它本质上就是OMP运行时分配给每个线程的第一次迭代的次数?如果是这样的话,就像上面所说的那样,使用一个私有标志并使用该标志的值来检测分配给线程的第一次迭代。如果您想这样做,一种更简单、更类似OMP的风格方法是对循环使用静态调度。然后您就可以先验地知道哪些迭代映射到哪个线程。为了保证线程与迭代的映射,静态调度需要指定chunk_大小。否则,根据OpenMP规范,迭代空间被划分为大小大致相等的块。如果您想这样做,一种更简单、更类似OMP的风格方法是对循环使用静态调度。然后您就可以先验地知道哪些迭代映射到哪个线程。为了保证线程与迭代的映射,静态调度需要指定chunk_大小。否则,根据OpenMP规范,迭代空间被划分为大小大致相等的块。他们试图仅在第一次迭代时(对于每个线程)设置
变量
,而不是在每次迭代开始时。他不是这么说的:-)(“在循环迭代开始时设置一次”)。这很公平,但是伪代码证明了他们的意图!我的问题是,另一个请求似乎有悖常理,没有其他理由(没有给出),所以这一切感觉就像有人决定这是一个更高层次问题的解决方案,他们没有解释,可能是有更好的解决方案来解决更高层次的问题。(例如,可能有人正在实现自己的缩减,并希望初始化每个线程的值,但OpenMP已经进行了缩减!)他们试图仅在第一次迭代时(对于每个线程)而不是在每次迭代开始时设置
变量(“循环迭代开始时一次”)。这很公平,但伪代码演示了