【发布时间】:2019-01-12 19:46:32
【问题描述】:
我对在 python 中像 Fortran 一样编写代码感到内疚。我正在重写我自己在 Fortran 中编写的长代码的许多部分,因为我想显着扩展代码,并且在 python 中扩展以进行概念验证工作要容易得多。但是,如果可以加快速度,我将简单地使用 python,我实际上对一遍又一遍地启动程序并不感兴趣。一旦一个想法被证明是可行的,我就会转向下一个问题。这就是为什么我希望在 python 中工作。不幸的是,现在,用 python 编写的运行需要几周的时间。即使在以下 for 循环上加速一个数量级,也将使其成为一个可行的测试平台。
针对 R 语言提出了类似的问题
Improving loop performance with function call inside
但令人惊讶的是,我没有看到一个用于 python 的。这个类似,但是for循环中的函数有依赖关系,我的没有
Improve performance of a for loop in Python (possibly with numpy or numba)
一个巨大的瓶颈是单个for循环
简单代码
import numpy as np
part = 3 # a random index of an array, fixed here for example purposes
nmol = 1000
energy = np.zeros((nmol),dtype=np.float_)
for i in range(nmol):
energy[i] = np.where( part != i,function(part,i),0.0) # if i = part, energy = 0.0
加速函数本身是另一个独立的问题。必须有一种方法可以使用 numpy 或其他方法同时运行所有调用
例如,我们可以说
def function(i,j):
for k in range(100000): # this loop is simply to make the time about a second or 2
ener = (i + j) * (i * j) # entirely arbitrary and not my real problem
return ener
实际上,我的函数调用了几个依赖于部分和“i”的函数。
完整的工作示例是:
import numpy as np
import time as time
def function(i,j):
for k in range(10000): # this loop is simply to make the time about a second or 2
ener = (i + j) * (i * j) # entirely arbitrary and not my real problem
return ener
part = 3 # a random index of an array, fixed here for example purposes
nmol = 1000
energy = np.zeros((nmol),dtype=np.float_)
start = time.time()
for i in range(nmol):
energy[i] = np.where( part != i,function(part,i),0.0) # if i = part, energy = 0.0
end = time.time()
print('time: ', end-start)
我使用的是 Python 3.6 版。在循环中,索引“i”必须不与索引“part”交互。
【问题讨论】:
-
您对多处理持开放态度吗?如果是,您可以参考docs.python.org/3.4/library/…。很难看出如何提高循环的迭代速度。我不确定你是否可以使用列表理解,因为能量是一个 numpy 对象
-
energy 只是在每个元素中保存浮点标量......它可以是列表或数组或速度所需的任何东西:)。我愿意接受任何能让我的代码更快的事情!
-
for循环在您的function(i,j)中是多余的。你知道的,对吧? -
使用 numba。或者,如果这太严格,请使用 cython。另外,julia 生态越来越强大,加上(编译后的)julia 代码可以直接调用到 python 代码中。
-
您不想调用的函数是否包含任何非 numpy 代码?否则,使用 Numba 解决这个问题真的很容易,正如 @J_H 已经提到的那样。
标签: python python-3.x performance vectorization