首页 > 解决方案 > 有没有办法提高在 Windows 下的 Fortran 中处理数组的速度,比如 Python numpy?

问题描述

抱歉可能出现重复。关于问题。与 Windows 下的 GNU Fortran(9.2.0 MinGW.org GCC Build-20200227-1)相比,python 3.8.2 中的 numpy(1.18.2)为矩阵产品提供了非常高的模拟速度(快 3 倍)。我使用了gfortran.exe test.f没有任何附加选项的命令。

有谁知道是什么原因造成的,是否可以提高 Fortran 的模拟速度?

这是fortran代码:

program product_test
    INTEGER :: N,N_count,i,j,k,nc
    REAL*8 :: t1,t2
    REAL*8,dimension (:,:), allocatable :: a,b,c

    N = 200
    N_count = 10

    allocate ( a(N,N) )
    allocate ( b(N,N) )
    allocate ( c(N,N) ) 

    call RANDOM_NUMBER(a)
    call RANDOM_NUMBER(b)

    print *, 'Matrix Multiplication: C = A * B for size (',N,',',N,')'
    call CPU_TIME ( time_begin )
    do nc=1,N_count
        c = MATMUL(a,b)
    end do
    call CPU_TIME ( time_end )
    t2 = (time_end - time_begin)/N_count
    print *, 'Time of operation was ', t2, ' seconds'

end

这是输出:

矩阵乘法: C = A * B for size ( 200 , 200 )
运算时间为 9.3749E-003

这是python 3代码:

import numpy as np
import time

N = 200
N_count = 10

a = np.random.rand(N,N)
b = np.random.rand(N,N)
c = np.zeros([N,N], dtype = float)


print('Matrix product in python (using numpy): c= a*b for size (',N,',',N,')')
start_time = time.time()
for nc in range(N_count):
    c = a@b
t2 = (time.time() - start_time)/N_count
print('Elapsed time = ',t2,'s')

这是输出:

python中的矩阵产品(使用numpy):c = a * b for size(200,200)
经过时间= 0.0031252 s


**附加测试。** 在“roygvib”和“Vladimir F”的评论之后,我用 blas/lapack 完成了测试:

gfortran test.f -lopenblas -o test.exegfortran test.f -ffast-math -o test.exegfortran test.f -lblas -o test.exe 或给我0.0063sgfortran test.f -llapack -o test.exe的计算时间,用于大小 ( 200 x 200 ) 的方阵的矩阵乘法。

不幸的是,我已经删除了之前版本的 mingw,并且在 GNU Fortran(x86_64-posix-seh-rev0,由 MinGW-W64 项目 8.1.0 构建)下执行了新的测试。可能是我做错了什么,因为 -llapack, -lblas, . 之间没有区别-lopenblas。对于时间测量,我SYSTEM_CLOCK按照“Vladimir F”的建议使用。

现在,它更好,但 numpy 仍然比 fortran 快(不是三倍而是两倍)。继“Vladimir F”的最后一条评论之后,我发现与 Python 不同的是,Fortran 主要使用一个逻辑核心(我的 PC 上的 intel i3 CPU 有 4 个逻辑核心)。因此,这是我的 PC (Windows8.1) 上未正确配置 MinGW 的问题。

在此处输入图像描述

标签: pythonnumpyfortran

解决方案


在 Fortran 中使用MATMUL或BLAS等外部库进行矩阵乘法,我们有很多问题涉及矩阵乘法的性能

Fortran矩阵运算在不同优化
性能下的Fortran矩阵乘法性能
BLAS是如何获得如此极致的性能的?

你应该先阅读它们。您永远不应该在幼稚的 for 循环中进行矩阵乘法,这总是很慢。矩阵乘法有特殊的算法。它们以有效的方式使用内存带宽,并使用向量化指令(通常直接用汇编编写)。


许多 Fortran 编译器允许您直接通过 MATMUL 调用 BLAS xGEMM。在 gfortran-fexternal-blas中,roygvib 提到了它是可能的。如果您对此有任何疑问,请直接致电 DGEMM。

某些 BLAS 实现能够使用多个线程。如果您尝试使用 CPU_TIME 来测量速度,则必须使用 SYSTEM_CLOCK 或替代方法。


此外,您没有报告使用任何优化标志,如-O3. 除非优化的外部库完成所有工作,否则这些对于任何良好的性能都是必需的。


推荐阅读