Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/340.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/8/python-3.x/18.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
Python:通过内部函数调用(仅依赖于循环索引)提高for循环的性能_Python_Python 3.x_Performance_Vectorization - Fatal编程技术网

Python:通过内部函数调用(仅依赖于循环索引)提高for循环的性能

Python:通过内部函数调用(仅依赖于循环索引)提高for循环的性能,python,python-3.x,performance,vectorization,Python,Python 3.x,Performance,Vectorization,我对用python编写代码感到内疚,就好像它是Fortran一样。我正在重写我自己用Fortran编写的一段长代码的许多部分,因为我想显著地扩展代码,而且用python进行概念验证工作要容易得多。但是,如果速度足够快的话,我将简单地使用python,我实际上对一遍又一遍地启动程序并不感兴趣。一旦一个想法被证明有效,我就进入下一个问题。这就是我希望使用python的原因。不幸的是,现在,用python编写的程序需要几个星期才能运行。即使在下面的for循环上进行一个数量级的加速,也会使它成为一个可行

我对用python编写代码感到内疚,就好像它是Fortran一样。我正在重写我自己用Fortran编写的一段长代码的许多部分,因为我想显著地扩展代码,而且用python进行概念验证工作要容易得多。但是,如果速度足够快的话,我将简单地使用python,我实际上对一遍又一遍地启动程序并不感兴趣。一旦一个想法被证明有效,我就进入下一个问题。这就是我希望使用python的原因。不幸的是,现在,用python编写的程序需要几个星期才能运行。即使在下面的for循环上进行一个数量级的加速,也会使它成为一个可行的测试平台

对于R语言也提出了类似的问题

但令人惊讶的是,我没有看到python的。这个类似,但是for循环中的函数有依赖项,而我的函数没有

一个巨大的瓶颈是单for循环

简单代码 加速功能本身是另一个独立的问题。必须有一种方法可以使用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”的函数

完整的工作示例是:
我使用的是Python版本3.6。循环中的索引“i”不能与索引“part”交互,这一点非常重要。

我很惊讶我是一个能够找到答案的人——我不是故意回答我自己的问题。。。我只是一个人想了一会儿

创建一个从0到nmol的整数数组,而不是从索引0到nmol的for循环。只需通过传递整数数组来调用函数。因此,数组输入接收数组输出。我修改了函数,使其不需要常量“part”

此矢量化解决方案比for循环快约27倍,为我提供了所需的数量级

随着size nmol的阵列长度变大,速度增益增加,反之亦然

import numpy as np
import time as time

def function(i):
    for k in range(10000):
        ener = (i + part) + (i * part) # entirely arbitrary and not my real problem
    return ener

part  = 3 # a random index of an array, fixed here for example purposes
nmol = 1000

start = time.time()

part_list = np.arange(0,nmol,1)
part_list = np.delete(part_list,part)  # remove the self index

energy =function(part_list) # calls the function in a vectorized form.

end = time.time()
time2 = end-start

基于矢量化解决方案,您可以使用

原始代码:

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导出
注释

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

你对多重处理持开放态度吗?如果是,您可以参考。很难看出如何提高循环的迭代速度。我不确定您是否可以使用列表理解,因为energy是一个numpy对象energy只是在每个元素中保存浮点标量。。。它可以是一个列表或数组,也可以是速度所需的任何内容:)。我愿意接受任何能让我的代码更快的东西!
函数(i,j)
中的
for
循环是冗余的。你知道的,对吧?用麻木。或者,如果限制太多,使用cython。此外,julia生态系统变得越来越强大,加上(编译的)julia代码可以直接调用python代码。您不想调用的函数是否包含任何非numpy代码?否则,使用@J_H已经提到的Numba,这个问题将很容易解决。
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