Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/facebook/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么我的f2py程序比python程序慢_Python_Performance_Fortran_F2py - Fatal编程技术网

为什么我的f2py程序比python程序慢

为什么我的f2py程序比python程序慢,python,performance,fortran,f2py,Python,Performance,Fortran,F2py,我最近用python编写了一个耗时的程序,并决定用fortran重写最耗时的部分 然而,用f2py包装的fortran代码比python代码慢,有人能告诉我如何找到这里发生的事情吗 以下是python函数供参考: def iterative_method(alpha0, beta0, epsilon0, epsilons0, omega, smearing=0.01, precision=0.01, max_step=20, flag=0): # alpha0, beta0, epsil

我最近用python编写了一个耗时的程序,并决定用fortran重写最耗时的部分

然而,用f2py包装的fortran代码比python代码慢,有人能告诉我如何找到这里发生的事情吗

以下是python函数供参考:

def iterative_method(alpha0, beta0, epsilon0, epsilons0, omega, smearing=0.01, precision=0.01, max_step=20, flag=0):
    # alpha0, beta0, epsilon0, epsilons0 are numpy arrays
    m, n = np.shape(epsilon0)
    Omega = np.eye(m, dtype=np.complex) * (omega + smearing * 1j)
    green = LA.inv(Omega - epsilon0) # LA is numpy.linalg
    alpha = np.dot(alpha0, np.dot(green, alpha0))
    beta = np.dot(beta0, np.dot(green, beta0))
    epsilon = epsilon0 + np.dot(alpha0, np.dot(green, beta0)) + np.dot(beta0, np.dot(green, alpha0))
    epsilons = epsilons0 + np.dot(alpha0, np.dot(green, beta0))

    while np.max(np.abs(alpha0)) > precision and np.max(np.abs(beta0)) > precision and flag < max_step:
        flag += 1
        return iterative_method(alpha, beta, epsilon, epsilons, omega, smearing, precision, min_step, max_step, flag)
return epsilon, epsilons, flag
在一次测试中,python代码使用了大约5秒,而fortran代码使用了大约7秒,这是很难接受的。此外,我几乎看不到fortran代码中的任何开销。这是包装纸的错吗

编辑:我没有对
matmul
使用
BlAS
。使用
BLAS
后,fortran和python的性能都在5秒左右。

首先,对python代码进行测试,以便准确了解它是如何使用时间的。 然后,如果愿意,可以使用调试器对Fortran代码执行类似的操作

我怀疑基本上所有的时间都花在矩阵运算上,所以任何速度的差异都是由于数学库,而不是调用它的语言。 传达了我在这方面的一些经验。 通常,执行矩阵乘法、求逆或Cholesky变换等操作的例程被设计为对大型矩阵有效,但对小型矩阵无效

例如,LAPACK矩阵乘法例程DGEMM有两个字符参数TRANSA和TRANSB,它们可以是大写或小写,指定每个输入矩阵是否被转置。 为了检查这些参数的值,它调用函数LSAME。 我发现,如果我把大部分时间花在乘法小矩阵上,比如4x4,那么程序实际上几乎所有时间都在调用LSAME,而实际乘法矩阵的时间很少。 您可以看到如何轻松地解决这个问题。

首先,对python代码进行修改,以便您确切地知道它是如何花费时间的。 然后,如果愿意,可以使用调试器对Fortran代码执行类似的操作

我怀疑基本上所有的时间都花在矩阵运算上,所以任何速度的差异都是由于数学库,而不是调用它的语言。 传达了我在这方面的一些经验。 通常,执行矩阵乘法、求逆或Cholesky变换等操作的例程被设计为对大型矩阵有效,但对小型矩阵无效

例如,LAPACK矩阵乘法例程DGEMM有两个字符参数TRANSA和TRANSB,它们可以是大写或小写,指定每个输入矩阵是否被转置。 为了检查这些参数的值,它调用函数LSAME。 我发现,如果我把大部分时间花在乘法小矩阵上,比如4x4,那么程序实际上几乎所有时间都在调用LSAME,而实际乘法矩阵的时间很少。
您可以看到如何轻松地解决这个问题。

您的matmul是否使用BLAS?Python代码中的
return
语句似乎放错了位置,因为它位于
while
循环中。这肯定会让它看起来更快…@martineau,为什么?这是一个迭代,与他们的fortran版本做了相同的事情。对不起,我错过了它向自身返回递归调用的事实……尽管我仍然觉得它是一个奇怪的实现,因为(afaik)。@VladimirF,问题已编辑。matmul是否使用BLAS?Python代码中的
return
语句似乎放错了位置,因为它位于
while
循环中。这肯定会让它看起来更快…@martineau,为什么?这是一个迭代,与他们的fortran版本做了相同的事情。抱歉,我错过了它向自身返回递归调用的事实…尽管我仍然觉得它是一个奇怪的实现,因为(afaik)。@VladimirF,问题编辑。我发现很难计算在
f2py
包装器中花费了多少时间。有什么方便的方法吗?@ChongWang:你能在GDB和。如果这样做20次,包含矩阵运算的样本分数等于它们所用时间的分数。这不是一个高精度的测量,但你不需要高精度。我发现很难计算在
f2py
包装中花费了多少时间。有什么方便的方法吗?@ChongWang:你能在GDB和。如果这样做20次,包含矩阵运算的样本分数等于它们所用时间的分数。这不是一个高精度的测量,但你不需要高精度。
SUBROUTINE iterate(eout, esout, alpha, beta, e, es, omega, smearing, prec, max_step, rank)
    INTEGER, PARAMETER :: dp = kind(1.0d0)
    REAL(kind=dp) :: omega, smearing, prec
    INTEGER :: max_step, step, rank, cnt
    COMPLEX(kind=dp) :: alpha(rank,rank), beta(rank,rank), omega_mat(rank, rank),&
     green(rank, rank), e(rank,rank), es(rank,rank)
    COMPLEX(kind=dp), INTENT(out) :: eout(rank, rank), esout(rank, rank)
    step = 0
    omega_mat = 0
    DO cnt=1, rank
        omega_mat(cnt, cnt) = 1.0_dp
    ENDDO
    omega_mat = omega_mat * (omega + (0.0_dp, 1.0_dp) * smearing)
    DO WHILE (maxval(abs(alpha)) .gt. prec .or.  maxval(abs(beta)) .gt. prec .and. step .lt. max_step)
        green = zInverse(rank, omega_mat - e) ! zInverse is calling lapack to compute inverse of the matrix
        e = e + matmul(alpha, matmul(green, beta)) + matmul(beta, matmul(green, alpha))
        es = es + matmul(alpha, matmul(green, beta))
        alpha = matmul(alpha, matmul(green, alpha))
        beta = matmul(beta, matmul(green, beta))
        step = step + 1
    ENDDO
    print *, step
    eout = e
    esout = es
END SUBROUTINE iterate