我一直在尝试使用f2py将优化的Fortran代码与Python接口化,用于向量和矩阵乘法。
为了获得对比性能的数据,我在循环中执行相同的乘积100000次。
使用完整的Fortran代码,乘积需要2.4秒(ifort),而使用f2py需要大约11秒。仅供参考,使用numpy需要约20秒。
我要求Fortran和Python部分在循环前后写入时间差异,使用f2py时它们都写入11秒,因此代码没有在传递数组时浪费时间。我试图理解是否是numpy数组存储方式引起的问题,但我无法理解问题所在。
你有任何想法吗?
提前致谢
program Main
implicit none
save
integer :: seed, i, j, k
integer, parameter :: states =15
integer, parameter :: tessere = 400
real, dimension(tessere,states,states) :: matrix
real, dimension(states) :: vector
real :: start, finish
real :: prod(tessere)
do i=1,tessere
do j=1,states
do k=1,states
matrix(i,j,k) = i+j+k
end do
enddo
end do
do i=1,states
vector(i) = i
enddo
call doubleSum(vector,vector,matrix,states,tessere,prod)
end program
Fortran子程序:
subroutine doubleSum(ket, bra, M , states, tessere,prod)
integer :: its, j, k,t
integer :: states
integer :: tessere
real, dimension(tessere,states,states) :: M
real, dimension(states) :: ket
real, dimension(states) :: bra
real, dimension(tessere) :: prod
real,dimension(tessere,states) :: ctmp
call cpu_time(start)
do t=1,100000
ctmp=0.d0
do k=1,states
do j=1,states
do its=1,tessere
ctmp(its,k)=ctmp(its,k)+ M(its,k,j)*ket(j)
enddo
enddo
enddo
do its=1,tessere
prod(its)=dot_product(bra,ctmp(its,:))
enddo
enddo
call cpu_time(finish)
print '("Time = ",f6.3," seconds.")',finish-start
end subroutine
Python脚本
import numpy as np
import time
import cicloS
M= np.random.rand(400,15,15)
ket=np.random.rand(15)
#M=np.asfortranarray(M)
#ket=np.asfortranarray(ket)
import time
start=time.time()
prod=cicloS.doublesum(ket,ket,M)
end=time.time()
print(end-start)
使用f2py生成并编辑的.pyf文件
! -*- f90 -*-
! Note: the context of this file is case sensitive.
python module cicloS
interface
subroutine doublesum(ket,bra,m,states,tessere,prod)
real dimension(states),intent(in) :: ket
real dimension(states),depend(states),intent(in) :: bra
real dimension(tessere,states,states),depend(states,states),intent(in) :: m
integer, optional,check(len(ket)>=states),depend(ket) :: states=len(ket)
integer, optional,check(shape(m,0)==tessere),depend(m) :: tessere=shape(m,0)
real dimension(tessere),intent(out) :: prod
end subroutine doublesum
end interface
end python module cicloS
integer,dimension(tessere):: prod
应该是real,dimension(tessere):: prodotto
,并且子程序中所有出现的prod
都应替换为prodotto
。您使用什么编译标志来编译ifort版本的代码,并且是否对f2py使用相同的标志?(使用gfortran -O3 sub.f90 main.f90
进行编译,我得到了与纯Fortran相同的运行时间,与f2py版本大约为1.3秒) - jbdvifort
vs.gfortran
!)肯定可以解释您观察到的时间差异。 您可以通过在f2py命令中添加例如--opt='-O1'
来指定(附加)编译器标志,并搜索--help-fcompiler
以了解如何指定f2py应使用哪个Fortran编译器。 - jbdv