Fortran Coder

标题: 并行算法求助 [打印本页]

作者: Kieran    时间: 2020-6-8 07:31
标题: 并行算法求助
大家好,


我想向大家请教一个问题。我的计算需要经两次循环。伪代码如下。

outer Loop i = 1, 200, 1
         inner Loop j= 1, 1000000, 1
                  执行语句块
         End Loopinner
End Loop outer


每运行完一次inner Loop后,都要收集一个数据,在运行完ouerLoop后,一共要收集200个数据。如果用一个CPU仅仅只运行inner Loop,而不运行outer Loop的话,需要三天多(超过72小时)的时间。

我想对inner LoopouterLoop都分别各自使用并行。请问大有哪些建议要如何编写并行代码呢?

是否可以在inner LoopouterLoop中分别使用MPI呢?如果可以,要如何区分哪个CPU执行哪个Loop呢?

另外,我有看到有人提及可以将MPIOpenMP混合在一起编程。那是否可以用MPI并行outerLoop,用OpenMP并行inner Loop呢?如果可以,要如何在每次OpenMP运行完一个innerLoop后收集一个数据到相应的CPU上;然后再在所有的outer Loop运行结束后,从所有使用MPICPU上一共收集200个数据呢?又要如何区分哪个CPU执行MPI中的outerLoop,哪些CPU执行OpenMP中的innerLoop呢?大家有混合并行编程方面的例子,推荐一下吗?

或者大家是否有其它建议,可以使用其它方式并行这个代码,让它运行效率提高吗?谢谢大家啦。


作者: necrohan    时间: 2020-6-9 09:07
建议先试试OpenMP。
MPI要网络传输数据,如果网卡速度慢也会影响计算速度。
作者: Kieran    时间: 2020-6-9 22:23
谢谢你的回复。

我写了一个简短的例子,这个例子与我的程序结构是一样的。代码如下。

PROGRAM MAIN
IMPLICIT NONE
INTEGER          :: i, j, k
DOUBLE PRECISION :: en,ei,es
DOUBLE PRECISION :: ki(1000,2000), et(200),kn(2000)
OPEN(UNIT=3, FILE='output.dat', STATUS='UNKNOWN')
DO i = 1, 1000, 1
   DO j = 1, 2000, 1
      ki(j,k) = DBLE(j) + DBLE(k)
   END DO
END DO
outer_loop DO i = 1, 200, 1
   en = 2.0d0/DBLE(200)*(i-1)-1.0d0
   et(i) = en
   es = 0.0d0
   inner_loop DO j = 1, 1000, 1
      kn=ki(j,:)
      CALL CAL(en,kn,ei)
      es = es + ei
   END DO inner_loop
   WRITE (UNIT=3, FMT=*) et(i), es
END DO outer_loop
CLOSE(UNIT=3)
STOP
END PROGRAM MAIN

SUBROUTINE CAL (en,kn,ei)
IMPLICIT NONE
INTEGER          :: i
DOUBLE PRECISION :: en, ei, gf,p
DOUBLE PRECISION :: kn(2000)
p = 3.14d0
ei = 0.0d0
DO i = 1, 2000, 1
   gf = 1.0d0 / (en - kn(i) * p)
   ei = ei + gf
END DO
RETURN
END SUBROUTINE CAL

请问要如何区分哪个CPU执行哪个循环(inner_loop和outer_loop)呢?尤其是当使用MPI和OpenMP混合编程的时候,要如何修改这个代码呢?能麻烦你帮我做下简短的修改吗?多谢啦。
作者: Kieran    时间: 2020-6-9 22:24
necrohan 发表于 2020-6-9 09:07
建议先试试OpenMP。
MPI要网络传输数据,如果网卡速度慢也会影响计算速度。 ...

谢谢你的回复。

我写了一个简短的例子,这个例子与我的程序结构是一样的。代码如下。

PROGRAM MAIN
IMPLICIT NONE
INTEGER          :: i, j, k
DOUBLE PRECISION :: en,ei,es
DOUBLE PRECISION :: ki(1000,2000), et(200),kn(2000)
OPEN(UNIT=3, FILE='output.dat', STATUS='UNKNOWN')
DO i = 1, 1000, 1
   DO j = 1, 2000, 1
      ki(j,k) = DBLE(j) + DBLE(k)
   END DO
END DO
outer_loop DO i = 1, 200, 1
   en = 2.0d0/DBLE(200)*(i-1)-1.0d0
   et(i) = en
   es = 0.0d0
   inner_loop DO j = 1, 1000, 1
      kn=ki(j,:)
      CALL CAL(en,kn,ei)
      es = es + ei
   END DO inner_loop
   WRITE (UNIT=3, FMT=*) et(i), es
END DO outer_loop
CLOSE(UNIT=3)
STOP
END PROGRAM MAIN

SUBROUTINE CAL (en,kn,ei)
IMPLICIT NONE
INTEGER          :: i
DOUBLE PRECISION :: en, ei, gf,p
DOUBLE PRECISION :: kn(2000)
p = 3.14d0
ei = 0.0d0
DO i = 1, 2000, 1
   gf = 1.0d0 / (en - kn(i) * p)
   ei = ei + gf
END DO
RETURN
END SUBROUTINE CAL

请问要如何区分哪个CPU执行哪个循环(inner_loop和outer_loop)呢?尤其是当使用MPI和OpenMP混合编程的时候,要如何修改这个代码呢?能麻烦你帮我做下简短的修改吗?多谢啦。
作者: Kieran    时间: 2020-6-9 22:25
necrohan 发表于 2020-6-9 09:07
建议先试试OpenMP。
MPI要网络传输数据,如果网卡速度慢也会影响计算速度。 ...

谢谢你的回复。

我写了一个简短的例子,这个例子与我的程序结构是一样的。代码如下。

PROGRAM MAIN
IMPLICIT NONE
INTEGER          :: i, j, k
DOUBLE PRECISION :: en,ei,es
DOUBLE PRECISION :: ki(1000,2000), et(200),kn(2000)
OPEN(UNIT=3, FILE='output.dat', STATUS='UNKNOWN')
DO i = 1, 1000, 1
   DO j = 1, 2000, 1
      ki(j,k) = DBLE(j) + DBLE(k)
   END DO
END DO
outer_loop DO i = 1, 200, 1
   en = 2.0d0/DBLE(200)*(i-1)-1.0d0
   et(i) = en
   es = 0.0d0
   inner_loop DO j = 1, 1000, 1
      kn=ki(j,:)
      CALL CAL(en,kn,ei)
      es = es + ei
   END DO inner_loop
   WRITE (UNIT=3, FMT=*) et(i), es
END DO outer_loop
CLOSE(UNIT=3)
STOP
END PROGRAM MAIN

SUBROUTINE CAL (en,kn,ei)
IMPLICIT NONE
INTEGER          :: i
DOUBLE PRECISION :: en, ei, gf,p
DOUBLE PRECISION :: kn(2000)
p = 3.14d0
ei = 0.0d0
DO i = 1, 2000, 1
   gf = 1.0d0 / (en - kn(i) * p)
   ei = ei + gf
END DO
RETURN
END SUBROUTINE CAL

请问要如何区分哪个CPU执行哪个循环(inner_loop和outer_loop)呢?尤其是当使用MPI和OpenMP混合编程的时候,要如何修改这个代码呢?能麻烦你帮我做下简短的修改吗?多谢啦。
作者: necrohan    时间: 2020-6-10 08:52
Kieran 发表于 2020-6-9 22:25
谢谢你的回复。

我写了一个简短的例子,这个例子与我的程序结构是一样的。代码如下。

如果你真的要并行,我建议从OpenMP开始,哪个循环由哪个CPU执行是自动分配的,可以输出查看,如何修改建议你看一下最简单的例子,能满足你要求即可。
作者: Kieran    时间: 2020-6-25 01:37
necrohan 发表于 2020-6-10 08:52
如果你真的要并行,我建议从OpenMP开始,哪个循环由哪个CPU执行是自动分配的,可以输出查看,如何修改建 ...

谢谢你的建议。

我试着用OpenMP并行了我的代码,我在主程序文件(sea_MAINp.f90)中通过MPI并行了循环;在子程序文件(sea_CALp.f90)中使用OpenMP分别并行了三段循环。编译可以正常通过。但在运行时,却收到错误信息(std_err.txt),说子程序文件(sea_CALp.f90)里第359行(含有OpenMP命令的一行)有错误。但我反复查验,也没看出那一行有什么问题。

我把我的文件和错误信息文件放在附件里了。能麻烦你帮我看下,具体是哪里出了问题吗?多谢啦。

INPUT.dat

734 Bytes, 下载次数: 1

参数设置文件

std_out.txt

6.21 KB, 下载次数: 1

输出记录文件

std_err.txt

95.29 KB, 下载次数: 1

错误信息文件

sea_CALp.f90

26.46 KB, 下载次数: 2

子程序文件

sea_MAINp.f90

29.32 KB, 下载次数: 2

主程序文件


作者: necrohan    时间: 2020-6-28 09:14
错误信息里有
sea_sot            0000000000420D77  cal_mp_hamsea_            422  sea_CALp.f90
那里涉及矩阵相乘,MATMUL(mt5,mt3),而mt5(nu_wa,nu_wa),mt3(1,nu_wa),这里应该是不能相乘的。
作者: 风平老涡    时间: 2020-8-15 06:11
这取绝于运行平台。如果是分布式多核平台(distributed multicore), 可以选用MPI+OpenMP. 对外循环用MPI指定节点CPU(CPU 绑定),内循环OpenMP.




欢迎光临 Fortran Coder (http://bbs.fcode.cn/) Powered by Discuz! X3.2