Fortran OMP:如何做并行和单一任务?
Fortran OMP : how to do a parallel and a single task?
我是并行编程的新手。这是我想要并行化的串行代码
program main
implicit none
integer :: pr_number, i, pr_sum
real :: pr_av
pr_sum = 0
do i=1,1000
! The following instruction is an example to simplify the problem.
! In the real case, it takes a long time that is more or less the same for all threads
! and it returns a large array
pr_number = int(rand()*10)
pr_sum = pr_sum+pr_number
pr_av = (1.d0*pr_sum) / i
print *,i,pr_av ! In real case, writing a huge amount of data on one file
enddo
end program main
我想并行化 pr_number = int(rand()*10)
并且每个 num_threads 只有一个 print
。
我尝试了很多东西,但没有用。例如,
program main
implicit none
integer :: pr_number, i, pr_sum
real :: pr_av
pr_sum = 0
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(pr_number) SHARED(pr_sum,pr_av)
!$OMP DO REDUCTION(+:pr_sum)
do i=1,1000
pr_number = int(rand()*10)
pr_sum = pr_sum+pr_number
!$OMP SINGLE
pr_av = (1.d0*pr_sum) / i
print *,i,pr_av
!$OMP END SINGLE
enddo
!$OMP END DO
!$OMP END PARALLEL
end program main
我在编译时收到一条错误消息:工作共享区域可能没有紧密嵌套在工作共享、关键或显式任务区域中。
我怎样才能得到这样的输出(例如,如果我有 4 个线程)?
4 3.00000000
8 3.12500000
12 4.00000000
16 3.81250000
20 3.50000000
...
我再说一遍,我是并行编程的初学者。我在 Whosebug 上阅读了很多东西,但我认为,我还没有理解的技能。我正在努力,但是...
编辑 1
按照评论中的建议进行解释。 A do loop
执行 N 次冗长的计算(N 次马尔可夫链蒙特卡洛),并且在每次迭代时将所有计算的平均值写入文件。之前的平均值被删除,只保留最后一个,所以可以继续处理。我想在 4 个线程上并行执行此计算。
这是我想做的,但也许这不是最好的主意。
感谢您的帮助。
在发生缩减的结构中,缩减变量的值没有很好地定义。带有求和的归约子句通常由每个线程实现,每个线程都有一个归约变量的私有副本,它们用于对那个线程的数字求和。在循环的 and 处,私有副本被加到最终总和中。在实际进行减少之前打印中间值没有什么意义。
您可以在嵌套循环中进行缩减,并每 n 次迭代打印一次中间结果
program main
implicit none
integer :: pr_number, i, j, pr_sum
real :: pr_av
pr_sum = 0
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(pr_number) SHARED(pr_sum,pr_av)
do j = 1, 10
!$OMP DO REDUCTION(+:pr_sum)
do i=1,100
pr_number = int(rand()*10)
pr_sum = pr_sum+pr_number
enddo
!$OMP END DO
!$omp single
pr_av = (1.d0*pr_sum) / 100
print *,j*100,pr_av
!$omp end single
end do
!$OMP END PARALLEL
end program main
我保留了相同的 rand()
,它可能会或可能不会正确并行工作,具体取决于编译器。即使它给出了正确的结果,它实际上可能是使用一些锁或屏障顺序执行的。但是,要点也适用于其他库。
结果
> gfortran -fopenmp reduction-intermediate.f90
> ./a.out
100 4.69000006
200 9.03999996
300 13.7600002
400 18.2299995
500 22.3199997
600 26.5900002
700 31.0599995
800 35.4300003
900 40.1599998
我是并行编程的新手。这是我想要并行化的串行代码
program main
implicit none
integer :: pr_number, i, pr_sum
real :: pr_av
pr_sum = 0
do i=1,1000
! The following instruction is an example to simplify the problem.
! In the real case, it takes a long time that is more or less the same for all threads
! and it returns a large array
pr_number = int(rand()*10)
pr_sum = pr_sum+pr_number
pr_av = (1.d0*pr_sum) / i
print *,i,pr_av ! In real case, writing a huge amount of data on one file
enddo
end program main
我想并行化 pr_number = int(rand()*10)
并且每个 num_threads 只有一个 print
。
我尝试了很多东西,但没有用。例如,
program main
implicit none
integer :: pr_number, i, pr_sum
real :: pr_av
pr_sum = 0
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(pr_number) SHARED(pr_sum,pr_av)
!$OMP DO REDUCTION(+:pr_sum)
do i=1,1000
pr_number = int(rand()*10)
pr_sum = pr_sum+pr_number
!$OMP SINGLE
pr_av = (1.d0*pr_sum) / i
print *,i,pr_av
!$OMP END SINGLE
enddo
!$OMP END DO
!$OMP END PARALLEL
end program main
我在编译时收到一条错误消息:工作共享区域可能没有紧密嵌套在工作共享、关键或显式任务区域中。
我怎样才能得到这样的输出(例如,如果我有 4 个线程)?
4 3.00000000
8 3.12500000
12 4.00000000
16 3.81250000
20 3.50000000
...
我再说一遍,我是并行编程的初学者。我在 Whosebug 上阅读了很多东西,但我认为,我还没有理解的技能。我正在努力,但是...
编辑 1
按照评论中的建议进行解释。 A do loop
执行 N 次冗长的计算(N 次马尔可夫链蒙特卡洛),并且在每次迭代时将所有计算的平均值写入文件。之前的平均值被删除,只保留最后一个,所以可以继续处理。我想在 4 个线程上并行执行此计算。
这是我想做的,但也许这不是最好的主意。
感谢您的帮助。
在发生缩减的结构中,缩减变量的值没有很好地定义。带有求和的归约子句通常由每个线程实现,每个线程都有一个归约变量的私有副本,它们用于对那个线程的数字求和。在循环的 and 处,私有副本被加到最终总和中。在实际进行减少之前打印中间值没有什么意义。
您可以在嵌套循环中进行缩减,并每 n 次迭代打印一次中间结果
program main
implicit none
integer :: pr_number, i, j, pr_sum
real :: pr_av
pr_sum = 0
!$OMP PARALLEL DEFAULT(SHARED) PRIVATE(pr_number) SHARED(pr_sum,pr_av)
do j = 1, 10
!$OMP DO REDUCTION(+:pr_sum)
do i=1,100
pr_number = int(rand()*10)
pr_sum = pr_sum+pr_number
enddo
!$OMP END DO
!$omp single
pr_av = (1.d0*pr_sum) / 100
print *,j*100,pr_av
!$omp end single
end do
!$OMP END PARALLEL
end program main
我保留了相同的 rand()
,它可能会或可能不会正确并行工作,具体取决于编译器。即使它给出了正确的结果,它实际上可能是使用一些锁或屏障顺序执行的。但是,要点也适用于其他库。
结果
> gfortran -fopenmp reduction-intermediate.f90
> ./a.out
100 4.69000006
200 9.03999996
300 13.7600002
400 18.2299995
500 22.3199997
600 26.5900002
700 31.0599995
800 35.4300003
900 40.1599998