我对用python编写代码感到内as,就好像它是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
实际上,我的函数调用了一些取决于part和“ 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”交互。
答案 0 :(得分:1)
我很惊讶能找到一个答案-我不是故意回答自己的问题...我只是一段时间以来一直在思考这个问题。
创建从0到nmol的整数数组,而不是从索引0到nmol的for循环。只需通过传递整数数组来调用函数。因此,数组输入接收数组输出。我修改了函数,使其不需要常量“ part”
此矢量化解决方案比for循环快〜27倍,这为我提供了所需的数量级。
随着nmol大小的数组长度变大,速度增加,反之亦然。
code-runner.executorMapByFileExtension
答案 1 :(得分:1)
根据您的矢量化解决方案,您可以使用pythran
来提高速度原始代码:
import numpy as np
def function(i, part):
for k in range(10000):
ener = (i + part) + (i * part)
return ener
和相关基准:
python -m timeit -s 'import numpy as np; part = 3; nmol = 1000; part_list = np.arange(0,nmol,1); part_list = np.delete(part_list, part); from a import function' 'function(part_list, part)'
10 loops, best of 3: 37.3 msec per loop
然后添加一个pythran export
评论
import numpy as np
#pythran export function(int64[], int64)
def function(i, part):
for k in range(10000):
ener = (i + part) + (i * part)
return ener
并使用以下命令编译模块:
pythran a.py
带来额外的提升:
python -m timeit -s 'import numpy as np; part = 3; nmol = 1000; part_list = np.arange(0,nmol,1); part_list = np.delete(part_list, part); from a import function' 'function(part_list, part)'
1000000 loops, best of 3: 1.53 usec per loop