python - 有没有办法提高在 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.exe
或gfortran test.f -ffast-math -o test.exe
或gfortran 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 的问题。
解决方案
在 Fortran 中使用MATMUL或BLAS等外部库进行矩阵乘法,我们有很多问题涉及矩阵乘法的性能
Fortran矩阵运算在不同优化
性能下的Fortran矩阵乘法性能
BLAS是如何获得如此极致的性能的?
你应该先阅读它们。您永远不应该在幼稚的 for 循环中进行矩阵乘法,这总是很慢。矩阵乘法有特殊的算法。它们以有效的方式使用内存带宽,并使用向量化指令(通常直接用汇编编写)。
许多 Fortran 编译器允许您直接通过 MATMUL 调用 BLAS xGEMM。在 gfortran-fexternal-blas
中,roygvib 提到了它是可能的。如果您对此有任何疑问,请直接致电 DGEMM。
某些 BLAS 实现能够使用多个线程。如果您尝试不使用 CPU_TIME 来测量速度,则必须使用 SYSTEM_CLOCK 或替代方法。
此外,您没有报告使用任何优化标志,如-O3
. 除非优化的外部库完成所有工作,否则这些对于任何良好的性能都是必需的。
推荐阅读
- r - 使用 for 循环将数据框中的 NA 值替换为中值
- angular - Angular - 如何更改父组件的内容?
- html - HTML&CSS 和 div 对齐
- java - 如果没有@SpringBootApplication,@EnableFeignClients 可以工作吗?
- c# - Keras.NET 如何使用 KerasIterator
- sql - 函数参数列表中的错误:“=”无法识别。无法解析 SSRS 中的查询
- django - 使用 Django 批量保存编辑过的项目?
- javascript - 单击时播放音频文件的按钮
- javascript - 多页tiff格式节点js
- xamarin.forms - 是否可以为 mapbox 中的一条折线设置更多 Line Dasharray