Debian下Fortran代码性能测试与优化实践
一 环境准备与基线计时
- 安装工具链:sudo apt update && sudo apt install -y gfortran linux-tools-common linux-tools-generic linux-tools-$(uname -r)。
- 基线计时示例(wall-clock 与 CPU 时间):
program baseline
implicit none
real :: t0, t1, cpu0, cpu1, wall
call cpu_time(cpu0)
t0 = second()
call work()
t1 = second()
call cpu_time(cpu1)
wall = t1 - t0
print '("Wall: ", F0.4, " s, CPU: ", F0.4, " s")', wall, cpu1 - cpu0
contains
subroutine work()
integer, parameter :: n = 100_000_000
real :: s, x
s = 0.0
do i = 1, n
x = sin(real(i))*cos(real(i))
s = s + x
end do
end subroutine work
function second() result(t)
real :: t
call cpu_time(t)
end function second
end program baseline
- 编译与运行:gfortran -O3 -o baseline baseline.f90 && ./baseline。建议固定CPU亲和性与电源策略(如 performance 模式),并在释放模式下测试(关闭调试、日志、额外打印)。多核/并行场景请控制线程数(如 OMP_NUM_THREADS),并做多次运行取中位数以减小噪声。
二 工具链与适用场景
| 工具 |
主要用途 |
关键要点与局限 |
| gprof |
函数级热点、调用图 |
编译加**-pg**;仅统计用户态,对并行/内核态占比高的程序不准确;MPI/多进程需汇总各 rank 的 gmon.out |
| perf |
硬件事件采样、火焰图 |
编译加**-g**;系统级,能看指令/缓存/分支;适合定位热点与系统瓶颈 |
| Valgrind/Massif |
堆内存分配与峰值 |
编译无需特殊选项;开销大,适合功能正确性与内存热点定位,非纯 CPU 吞吐基准 |
| Intel VTune |
深度硬件分析 |
支持多语言/HPC;需安装;适合复杂瓶颈剖析 |
| TAU、HPCtoolkit |
大规模并行/HPC 分析 |
多用于集群/HPC 场景;部署复杂 |
| 以上工具在 Linux(含 Debian)上均可使用,选择时优先考虑:gprof(轻量函数热点)、perf(系统级热点与火焰图)、Valgrind(内存分配与泄漏)。 |
|
|
三 逐步操作示例
- gprof 函数级热点
- 编译:gfortran -O3 -pg -g -o app app.f90(多文件需对所有源文件加 -pg)。
- 运行:./app(正常退出才会生成 gmon.out)。
- 报告:gprof app gmon.out -b > analysis.txt;常用选项:-p(flat profile)、-q(调用图)、-A(源码注释,需 -g)。
- 注意:gprof 主要覆盖用户态,对并行/长时间内核态的程序不敏感;MPI 需合并各 rank 的 gmon.out 再分析。
- perf 采样与火焰图
- 编译:gfortran -g -O3 -o app app.f90。
- 采样:perf record -e cpu-clock -g ./app(可用 -e cycles/instructions/cache-misses 等事件)。
- 生成火焰图:
perf script -i perf.data > perf.unfold
~/FlameGraph/stackcollapse-perf.pl perf.unfold > perf.folded
~/FlameGraph/flamegraph.pl perf.folded > perf.svg
- 查看:浏览器打开 perf.svg,定位占比最高的函数路径。
- Valgrind/Massif 内存分配热点
- 运行:valgrind --tool=massif ./app。
- 分析:ms_print massif.out.xxx 查看堆分配随时间/调用栈的变化,定位大块分配与峰值。
四 并行与 MPI/OpenMP 的测试要点
- OpenMP:设置环境变量(如 OMP_NUM_THREADS、OMP_PROC_BIND、OMP_SCHEDULE),编译时加 -fopenmp;用 perf/VTune 观察线程负载均衡与并行效率。gprof 对多线程支持有限,优先用采样类工具。
- MPI:mpifort/mpicc 编译时各 rank 均需 -pg;运行后每个 rank 生成 gmon.out,需合并/分别分析;更推荐 perf 或 Intel VTune 做系统级热点与硬件事件分析。
- 通用建议:保持相同输入/随机种子、固定线程绑定、预热(先跑若干次再计时)、隔离环境(避免后台任务)、多次取中位数;报告需注明编译器版本、优化级别、CPU 型号、线程数/进程数与运行命令。