You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fortran中DO CONCURRENT代码性能评估及异常结果咨询

Fortran DO CONCURRENT 性能疑问解答

背景与测试环境

我正在探索Fortran的新特性,重点研究DO CONCURRENT——该特性据称可通过更简洁的指令达到与OpenACC相当的速度。测试环境为Windows10的WSL虚拟机,使用最新版NVIDIA编译器,编译命令如下:

nvfortran -stdpar=multicore -Minfo=accel myModule.F90 main.F90

测试目的是对比DO CONCURRENT与串行版本的性能提升。

测试代码

主程序代码

1 PROGRAM main
2    USE myModule_m
3    IMPLICIT NONE
4
5    !> declare some variables
6    INTEGER, PARAMETER          :: N  = 500000000
7    REAL(KIND=wp), DIMENSION(N) :: testArray
8    INTEGER                     :: i
9    REAL(KIND=wp)               :: T1,T2,T3,T4
10
11   ! initial condition
12   testArray = 0.0_wp
13   
14   T1 = wtime()
15   ! test the main loop in serial                                  
16   DO i = 1,N
17       testArray(i) = testArray(i) + 1.0_wp
18   END DO
19   T2 = wtime()
20   
21   WRITE(*,*) 'Serial time is = ',T2-T1
22   
23   ! reset initial condition
24   testArray = 0.0_wp
25   
26   T3 = wtime()
27   !! test the main loop in parallel
28   DO CONCURRENT (i=1:N)
29      testArray(i) = testArray(i) + 2.0_wp
30   END DO
31   T4 = wtime()                                                     
32   
33   WRITE(*,*) 'Multi-threaded time is = ',T4-T3
34   WRITE(*,*) 'Result = ',SUM(testArray)
35   STOP
36   END PROGRAM main

模块代码

1 MODULE myModule_m
2    IMPLICIT NONE
3
4    INTEGER, PARAMETER          :: wp = KIND(1.0D0)
5    CONTAINS                                                         
6
7    FUNCTION wtime() RESULT(time)
8       IMPLICIT NONE
9
10       !> local variables
11       INTEGER  :: clock_max, clock_rate, clock_reading
12       REAL(KIND=wp) :: time
13
14       CALL SYSTEM_CLOCK(clock_reading, clock_rate, clock_max)
15
16       time = REAL(clock_reading,KIND=wp)/REAL(clock_rate,kind=wp)
17    END FUNCTION wtime
18
19 END MODULE myModule_m

测试现象

  • 未加-stdpar=multicore编译时,DO CONCURRENT与串行版本耗时相当;
  • 启用该标志后,小数据量下DO CONCURRENT耗时更长,仅在超大数组时性能才接近串行。

疑问解答:这是正常现象

出现上述情况并非操作错误,而是由并行化的固有特性和测试任务类型决定的,具体原因如下:

1. 并行化固定开销不可忽视

启用-stdpar=multicore后,编译器会为DO CONCURRENT生成多线程代码,但线程创建、任务调度、数据分片等操作存在固定开销。当数据量较小时,这些开销会完全覆盖并行计算带来的收益,导致总耗时高于串行版本。只有当数据量足够大,并行计算的收益超过开销时,才能体现出优势。

2. 测试任务属于内存绑定型

你的测试代码是简单的数组元素自增操作,这类任务的性能瓶颈是内存带宽,而非CPU计算能力。即使并行化,也无法突破硬件的内存带宽上限——串行版本的循环可能已经被编译器做了向量化等极致优化,充分利用了内存带宽,因此并行版本的性能很难超越串行版本,只能接近。

3. 串行版本的编译器优化更充分

串行循环的依赖关系简单,编译器可以进行更激进的优化(比如循环展开、向量化、寄存器重用等);而并行版本为了保证线程安全,部分优化会被限制,进一步缩小了与串行版本的性能差距。

优化建议

  • 改用计算密集型任务(如复杂浮点运算、矩阵乘法等)测试并行加速效果,这类任务能更好地发挥多线程的优势;
  • 设置环境变量OMP_NUM_THREADS控制线程数(NVIDIA stdpar底层通常基于OpenMP实现),确保线程数与CPU核心数匹配,避免过度调度;
  • 查看-Minfo=accel的输出,确认编译器是否成功将DO CONCURRENT并行化(若输出无类似DO CONCURRENT transformed to parallel loop的提示,需检查编译选项或循环并行性)。

内容的提问来源于stack exchange,提问作者Principio Tudisco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 02:55:58