Fortran链接BLAS编译后matmul性能异常问题求助
我在Fortran中对BLAS的dgemv和dgemm做基准测试,编写了两个程序:
matmul.f90:全程使用Fortran内置的matmul实现矩阵-矩阵、矩阵-向量乘法blas.f90:仅将矩阵-向量乘法替换为BLAS的dgemv,其余逻辑与matmul.f90完全一致
编译命令分别为:
gfortran -o matmul matmul.f90gfortran -o blas blas.f90 -lblas
测试结果显示,blas程序中的matmul矩阵-矩阵乘法耗时远高于matmul程序,与预期不符,求解释该现象的原因。
测试数据
| 矩阵规模 | matmul.f90耗时 | blas.f90耗时 |
|---|---|---|
| 2 | 4.0000000000000105E-005 | 1.7969999999999930E-003 |
| 4 | 1.0999999999999725E-005 | 1.2780000000000014E-003 |
| 8 | 2.3000000000000017E-005 | 8.0599999999997340E-004 |
| 16 | 4.8000000000000299E-005 | 2.4819999999999842E-003 |
| 32 | 1.1799999999999962E-004 | 5.3250000000000242E-003 |
| 64 | 3.4200000000000029E-004 | 1.7175999999999969E-002 |
| 128 | 1.2079999999999999E-003 | 5.3132000000000013E-002 |
| 256 | 4.7889999999999999E-003 | 0.20821500000000004 |
| 512 | 1.2796999999999999E-002 | 1.1222690000000000 |
原因分析
编译优化策略差异
单独编译matmul.f90时,gfortran会自动对matmul启用高度优化(如自动向量化、循环展开,甚至隐式调用系统优化的BLAS实现);而链接-lblas时,编译器可能调整了优化逻辑,禁用了部分针对matmul的自动优化,导致性能下降。BLAS库的兼容性与性能
你链接的可能是系统默认的参考BLAS(如netlib BLAS),这类库性能本身较低,且可能与gfortran对matmul的优化实现冲突,干扰了程序的内存布局、调用约定,间接影响matmul的执行效率。内存布局与临时数组开销
Fortran的matmul会针对列优先存储做优化,而dgemv同样要求列优先输入。如果blas.f90中数组的传递、存储存在细微变化(如隐式类型转换、临时数组生成),会导致matmul执行时需要额外的内存拷贝,增加耗时。编译器的
matmul自动替换逻辑
gfortran在特定条件下会自动将matmul替换为优化的BLAS调用。当手动链接BLAS库时,编译器可能取消了这种自动替换,转而使用原生matmul实现,而原生实现性能远不如编译器绑定的优化BLAS版本。基准测试的计时准确性
小矩阵规模下的耗时易受系统噪声影响,但数据中差异随规模增大而放大,说明并非单纯噪声。需确认两个程序的计时逻辑完全一致——是否仅测量matmul部分的耗时,而非包含dgemv的执行时间。
验证建议
- 给两个程序添加相同的高级优化选项后重新编译测试:
gfortran -O3 -march=native -o matmul matmul.f90gfortran -O3 -march=native -o blas blas.f90 -lblas - 替换为优化BLAS库(如OpenBLAS),指定链接该库后对比性能变化。
- 检查测试代码的计时逻辑,确保两个程序中
matmul的计时范围完全一致。 - 用
-v选项查看编译输出,确认两个编译过程的优化选项、链接库是否存在差异。
内容的提问来源于stack exchange,提问作者pablo

