计算化学公社

 找回密码 Forget password
 注册 Register
Views: 5856|回复 Reply: 27
打印 Print 上一主题 Last thread 下一主题 Next thread

[Fortran] Fortran OpenMP求助 第二弹

[复制链接 Copy URL]

257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

跳转到指定楼层 Go to specific reply
楼主
本帖最后由 wxhwbh 于 2020-6-12 16:17 编辑

上次在这个贴子http://bbs.keinsci.com/thread-16841-1-1.html问了关于openmp的一些问题,学了不少关于私有/公有变量的知识,非常感谢大家。由于我的程序基本全部重写,发个新帖问一个我新遇到的问题。
还是一个动力学程序,对不同的轨迹做演化,大致如下:

  1. !$OMP PARALLEL DO private(...) shared(...)
  2. do itraj=1,Ntraj

  3.      call sub1 !抽样
  4.     call sub2(itraj) !演化
  5. end do
  6. !$OMP END PARALLRL DO
复制代码


变量的 private 和 shared已经正确声明过了,但程序还是不对。后来我发现了问题所在:一次循环里必须要在同一个线程内先抽样再演化,而我的程序却做不到这一点,比如如果改成下面这样测试:
  1. !$OMP PARALLEL DO private(...) shared(...)
  2. do itraj=1,Ntraj
  3. write(*,*) "itraj=",itraj
  4. call sub1 !抽样
  5. write(*,*) 1,itraj
  6. call sub2(itraj) !演化
  7. write(*,*) 2,itraj
  8. end do
  9. !$OMP END PARALLRL DO
复制代码

则输出结果就会为

  1. ...
  2. itraj=          47
  3.            1          47
  4.            2        1547
  5. itraj=        1548
  6.            1        1548
  7.            2         546
  8. itraj=         547
  9.            1         547
  10.            2        1048

  11. ...
复制代码

也就是同一次循环内两个子程序处的线程是不一样的。但我翻了一下OpenMP的手册,没有找到可以强制一个线程内循环顺序执行的命令。请问有什么方法可以解决吗?



贫困U 退学与疯子工程学院

831

帖子

1

威望

7183

eV
积分
8034

Level 6 (一方通行)

2#
发表于 Post on 2020-6-12 16:24:31 | 只看该作者 Only view this author
你这个需求非常适合用MPI解决,可以保证先抽样再演化。

使用openmp的时候最好使并行粒度小一点,例如itraj的循环搞成串行的,sub1和sub2的内部做并行。

257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

3#
 楼主 Author| 发表于 Post on 2020-6-12 16:44:23 | 只看该作者 Only view this author
hebrewsnabla 发表于 2020-6-12 16:24
你这个需求非常适合用MPI解决,可以保证先抽样再演化。

使用openmp的时候最好使并行粒度小一点,例如itr ...

本身并行的目的就是减少轨迹数大的时候计算所需的时间。如果itraj串行了而里面的sub1和sub2并行的话对结果不会有更大的影响吗?
贫困U 退学与疯子工程学院

831

帖子

1

威望

7183

eV
积分
8034

Level 6 (一方通行)

4#
发表于 Post on 2020-6-12 17:43:46 | 只看该作者 Only view this author
本帖最后由 hebrewsnabla 于 2020-6-12 18:53 编辑
wxhwbh 发表于 2020-6-12 16:44
本身并行的目的就是减少轨迹数大的时候计算所需的时间。如果itraj串行了而里面的sub1和sub2并行的话对结 ...

怎么可能影响结果?结果不对肯定是程序没写对。我举个例子

  1. do i=1,N
  2.   ! 一堆事情
  3.   do j=1,M
  4.   ! 一大堆事
  5.     do k=1,P
  6.      !一大堆事情
  7.     enddo
  8.   enddo
  9. enddo
复制代码

请问把omp控制命令写在哪个do前面比较省事?当然是最内层循环了,这样需要处理的private/shared问题最少。
效率应该是差不多的。除非你的sub1,sub2里面没有循环,没法做并行。

当然,对这个问题MPI可能更省事。搞不定就用MPI

另外我觉得你的输出有的奇怪,难道不应该是各个线程先输出一批itraj,再输出一批1,itraj么,你这个看起来像是是串行的。
你要确认对于某个itraj,第一步和第二步是同一个线程,应该用OMP_GET_THREAD_NUM()输出线程号看看。



257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

5#
 楼主 Author| 发表于 Post on 2020-6-12 18:52:07 | 只看该作者 Only view this author
hebrewsnabla 发表于 2020-6-12 17:43
怎么可能影响结果?结果不对肯定是程序没写对。我举个例子

请问把omp控制命令写在哪个do前面比较省事 ...

但是,sub2的循环是时间演化,也就是下一次循环需要上一次的信息。这样直接做并行能得到正确的结果吗?
贫困U 退学与疯子工程学院

831

帖子

1

威望

7183

eV
积分
8034

Level 6 (一方通行)

6#
发表于 Post on 2020-6-12 18:55:58 | 只看该作者 Only view this author
本帖最后由 hebrewsnabla 于 2020-6-12 18:57 编辑
wxhwbh 发表于 2020-6-12 18:52
但是,sub2的循环是时间演化,也就是下一次循环需要上一次的信息。这样直接做并行能得到正确的结果吗?

哦你是说sub2内部的循环是时间演化。那应该不能并行。

831

帖子

1

威望

7183

eV
积分
8034

Level 6 (一方通行)

7#
发表于 Post on 2020-6-12 18:59:36 | 只看该作者 Only view this author
wxhwbh 发表于 2020-6-12 18:52
但是,sub2的循环是时间演化,也就是下一次循环需要上一次的信息。这样直接做并行能得到正确的结果吗?

这个情况用MPI比较好。

非要用omp的话,我重复一下我的疑问:
  一楼贴的输出有点奇怪,难道不应该是各个线程先输出一批itraj,再输出一批1,itraj么,你这个看起来像是是串行的。
  你要确认对于某个itraj,第一步和第二步是同一个线程,应该用OMP_GET_THREAD_NUM()输出线程号看看。

评分 Rate

参与人数
Participants 2
eV +7 收起 理由
Reason
thanhtam + 5 我很赞同
wxhwbh + 2 我检查一下

查看全部评分 View all ratings

257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

8#
 楼主 Author| 发表于 Post on 2020-6-12 19:47:54 | 只看该作者 Only view this author
hebrewsnabla 发表于 2020-6-12 18:59
这个情况用MPI比较好。

非要用omp的话,我重复一下我的疑问:

我把程序改成这样输出:
  1. !$OMP PARALLEL DO private(...) shared(...)
  2. do itraj=1,Ntraj
  3. write(*,*) "itraj=",itraj,"id=",omp_get_thread_num()
  4. call sub1 !抽样
  5. write(*,*) "sample finishing,id=",omp_get_thread_num()
  6. call sub2(itraj) !演化
  7. write(*,*) "evolution finishing,id=",omp_get_thread_num()
  8. write(*,*) !空一行
  9. end do
  10. !$OMP END PARALLRL DO
复制代码
用了4个核并行,输出是这样的:
  1. ...
  2. itraj=         533 id=           1
  3. sample finishing,id=           1
  4. evolution finishing,id=           3

  5. itraj=        1532 id=           3
  6. sample finishing,id=           3
  7. evolution finishing,id=           2

  8. itraj=        1033 id=           2
  9. sample finishing,id=           2
  10. evolution finishing,id=           0

  11. itraj=          34 id=           0
  12. sample finishing,id=           0
  13. evolution finishing,id=           3
  14. ...
复制代码
确实采样和演化不在一个线程内。
贫困U 退学与疯子工程学院

257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

9#
 楼主 Author| 发表于 Post on 2020-6-12 20:32:52 | 只看该作者 Only view this author
hebrewsnabla 发表于 2020-6-12 18:59
这个情况用MPI比较好。

非要用omp的话,我重复一下我的疑问:

再检查了一下,前几次的输出可能会有一点不一样,如下:

  1. itraj=           1 id=           0
  2. itraj=        1001 id=           2
  3. itraj=         501 id=           1
  4. sample finishing,id=           0
  5. sample finishing,id=           1
  6. itraj=        1501 id=           3
  7. sample finishing,id=           2
  8. sample finishing,id=           3
  9. evolution finishing,id=           0

  10. itraj=           2 id=           0
  11. sample finishing,id=           0
  12. evolution finishing,id=           3

  13. itraj=        1502 id=           3
  14. sample finishing,id=           3
  15. evolution finishing,id=           1

  16. ...
复制代码
贫困U 退学与疯子工程学院

831

帖子

1

威望

7183

eV
积分
8034

Level 6 (一方通行)

10#
发表于 Post on 2020-6-12 20:42:46 | 只看该作者 Only view this author
wxhwbh 发表于 2020-6-12 19:47
我把程序改成这样输出:
用了4个核并行,输出是这样的:
确实采样和演化不在一个线程内。

你这样还是不对,你要检查的是itraj和进程号是不是对应,每次输出进程号的时候要把itraj一起输出。

257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

11#
 楼主 Author| 发表于 Post on 2020-6-12 21:21:31 | 只看该作者 Only view this author
hebrewsnabla 发表于 2020-6-12 20:42
你这样还是不对,你要检查的是itraj和进程号是不是对应,每次输出进程号的时候要把itraj一起输出。

比如这样
  1. itraj=        1501 id=           3
  2. itraj=           1 id=           0
  3. sample finishing,id=           0 itraj=           1
  4. itraj=        1001 id=           2
  5. sample finishing,id=           2 itraj=        1001
  6. itraj=         501 id=           1
  7. sample finishing,id=           1 itraj=         501
  8. sample finishing,id=           3 itraj=        1501
  9. evolution finishing,id=           0 itraj=           1
  10. itraj=           2 id=           0
  11. sample finishing,id=           0 itraj=           2
  12. evolution finishing,id=           1 itraj=         501
  13. evolution finishing,id=           3 itraj=        1501
  14. evolution finishing,id=           2 itraj=        1001
  15. evolution finishing,id=           0 itraj=           2
  16. ...
复制代码

确实不在一个线程里。
或者我还有一个想法,就是让线程在执行完sub1后暂停,待所有线程都执行完sub1后,再开始并行执行sub2。OpenMP有功能可以做到吗?
贫困U 退学与疯子工程学院

831

帖子

1

威望

7183

eV
积分
8034

Level 6 (一方通行)

12#
发表于 Post on 2020-6-12 21:31:10 | 只看该作者 Only view this author
wxhwbh 发表于 2020-6-12 21:21
比如这样

确实不在一个线程里。

这明明是对的啊
itraj=1时,id一直=0;itraj=1001, id=2; itraj=501, id=1; ...

257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

13#
 楼主 Author| 发表于 Post on 2020-6-12 21:41:37 | 只看该作者 Only view this author
本帖最后由 wxhwbh 于 2020-6-12 21:46 编辑
hebrewsnabla 发表于 2020-6-12 21:31
这明明是对的啊
itraj=1时,id一直=0;itraj=1001, id=2; itraj=501, id=1; ...

原来如此,我发现了解决方法。把OMP PARALLRL DO 改成OMP PARALLRL DO ORDERED结果就对了。虽然没有定义ORDERED块,但好像DO ORDERED就能满足顺序执行。
但运行起来好慢啊....
贫困U 退学与疯子工程学院

831

帖子

1

威望

7183

eV
积分
8034

Level 6 (一方通行)

14#
发表于 Post on 2020-6-12 21:47:18 | 只看该作者 Only view this author
本帖最后由 hebrewsnabla 于 2020-6-12 21:49 编辑
wxhwbh 发表于 2020-6-12 21:41
原来如此,我发现了解决方法。把OMP PARALLRL DO 改成OMP PARALLRL DO ORDERED结果就对了。虽然没有定义O ...

不需要ordered,你上面输出的结果就是对的;不使用ordered也可以得到这个结果吧?

ordered等于没并行。

257

帖子

4

威望

4967

eV
积分
5304

Level 6 (一方通行)

15#
 楼主 Author| 发表于 Post on 2020-6-12 22:07:16 | 只看该作者 Only view this author
hebrewsnabla 发表于 2020-6-12 21:47
不需要ordered,你上面输出的结果就是对的;不使用ordered也可以得到这个结果吧?

ordered等于没并行 ...

不行,不用ORDERED的结果不对,上面那个输出是带ORDERED的。不带的是这样
  1. itraj=           1 id=           0
  2. itraj=         501 id=           1
  3. sample finishing,id=           1 itraj=         501
  4. itraj=        1001 id=           2
  5. sample finishing,id=           2 itraj=        1001
  6. itraj=        1501 id=           3
  7. sample finishing,id=           3 itraj=        1501
  8. sample finishing,id=           0 itraj=           1
  9. evolution finishing,id=           3 itraj=        1501
  10. itraj=        1502 id=           3
  11. sample finishing,id=           3 itraj=        1502
  12. evolution finishing,id=           2 itraj=        1001
  13. itraj=        1002 id=           2
  14. sample finishing,id=           2 itraj=        1002
  15. evolution finishing,id=           0 itraj=           1
  16. itraj=           2 id=           0
  17. sample finishing,id=           0 itraj=           2
  18. evolution finishing,id=           1 itraj=         501
  19. itraj=         502 id=           1
  20. sample finishing,id=           1 itraj=         502
  21. evolution finishing,id=           3 itraj=        1502
  22. itraj=        1503 id=           3
  23. sample finishing,id=           3 itraj=        1503
  24. evolution finishing,id=           1 itraj=         502
  25. itraj=         503 id=           1
  26. sample finishing,id=           1 itraj=         503
  27. evolution finishing,id=           0 itraj=           2
  28. itraj=           3 id=           0
  29. sample finishing,id=           0 itraj=           3
  30. evolution finishing,id=           2 itraj=        1002
  31. itraj=        1003 id=           2
  32. sample finishing,id=           2 itraj=        1003
  33. evolution finishing,id=           3 itraj=        1503
  34. itraj=        1504 id=           3
  35. sample finishing,id=           3 itraj=        1504
  36. evolution finishing,id=           1 itraj=         503
  37. ...
复制代码

这样看好像又在一个线程内,但结果就是不对。
贫困U 退学与疯子工程学院

本版积分规则 Credits rule

手机版 Mobile version|北京科音自然科学研究中心 Beijing Kein Research Center for Natural Sciences|京公网安备 11010502035419号|计算化学公社 — 北京科音旗下高水平计算化学交流论坛 ( 京ICP备14038949号-1 )|网站地图

GMT+8, 2024-11-23 21:10 , Processed in 0.193213 second(s), 22 queries , Gzip On.

快速回复 返回顶部 返回列表 Return to list