Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/345.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 如何使用numpy加快for循环速度_Python_Python 3.x_Numpy - Fatal编程技术网

Python 如何使用numpy加快for循环速度

Python 如何使用numpy加快for循环速度,python,python-3.x,numpy,Python,Python 3.x,Numpy,如果输入了numpy 2d数组,例如 100 100 100 100 100 100 0 0 0 100 100 0 0 0 100 100 0 0 0 100

如果输入了numpy 2d数组,例如

                           100   100   100   100   100
                           100    0     0     0    100
                           100    0     0     0    100
                           100    0     0     0    100
                           100   100   100   100   100
应该获得这样的输出

                            100   100   100   100   100
                            100    50    25    50   100
                            100    25     0    25   100
                            100    50    25    50   100
                            100   100   100   100   100
其中除边界外的每个数字都成为其相邻数字的平均值

我当前的代码可以工作,但我需要在不使用for循环的情况下使用它,并使用numpy将其矢量化

我当前的代码:

import numpy as np
def evolve_heat_slow(u):      
    u2 = np.copy(u)
    x=u2.shape[0]
    y=u2.shape[1]
    for i in range(1,x-1):
        for s in range(1,y-1):
            u2[i,s]=(u[i-1,s]+u[i+1,s]+u[i,s+1]+u[i,s-1])/4
    return u2

这几乎就是二维卷积的定义<代码>scipy已涵盖您。我复制
a
以保留边界;
valid
模式下的卷积将生成一个较小的数组(无边框),然后我将其粘贴到准备好的“框架”中


这几乎就是二维卷积的定义<代码>scipy已涵盖您。我复制
a
以保留边界;
valid
模式下的卷积将生成一个较小的数组(无边框),然后我将其粘贴到准备好的“框架”中


尽管Amadan的scipy回答对本案例最有意义,但这里有另一种“手动”的方法:

在这里,我们通过首先取中心3x3“窗口”并在每个方向上移动1来定义组件。然后我们堆叠移位的窗口,取平均值,并用这些值替换中心窗口

在1次迭代之后:

[[ 100. 100. 100. 100. 100.] [ 100. 50. 25. 50. 100.] [ 100. 25. 0. 25. 100.] [ 100. 50. 25. 50. 100.] [ 100. 100. 100. 100. 100.]] [[ 100. 100. 100. 100. 100.] [ 100. 50. 25. 50. 100.] [ 100. 25. 0. 25. 100.] [ 100. 50. 25. 50. 100.] [ 100. 100. 100. 100. 100.]] 经过2次迭代后:

[[ 100. 100. 100. 100. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 50. 25. 50. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 100. 100. 100. 100. ]] [[ 100. 100. 100. 100. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 50. 25. 50. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 100. 100. 100. 100. ]]
尽管Amadan的scipy回答对本案例最有意义,但这里有另一种“手动”的方法:

在这里,我们通过首先取中心3x3“窗口”并在每个方向上移动1来定义组件。然后我们堆叠移位的窗口,取平均值,并用这些值替换中心窗口

在1次迭代之后:

[[ 100. 100. 100. 100. 100.] [ 100. 50. 25. 50. 100.] [ 100. 25. 0. 25. 100.] [ 100. 50. 25. 50. 100.] [ 100. 100. 100. 100. 100.]] [[ 100. 100. 100. 100. 100.] [ 100. 50. 25. 50. 100.] [ 100. 25. 0. 25. 100.] [ 100. 50. 25. 50. 100.] [ 100. 100. 100. 100. 100.]] 经过2次迭代后:

[[ 100. 100. 100. 100. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 50. 25. 50. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 100. 100. 100. 100. ]] [[ 100. 100. 100. 100. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 50. 25. 50. 100. ] [ 100. 62.5 50. 62.5 100. ] [ 100. 100. 100. 100. 100. ]]
虽然不比其他方法好,但您也可以使用
np.在每个方向上滚动
,以执行相同的操作:

def evolve_heat_slow(u):
    u2 = u.copy()
    u2[1:-1, 1:-1] = ((np.roll(u2,1,0) + np.roll(u2,-1,0) 
                        + np.roll(u2,1,1) + np.roll(u2,-1,1))/4)[1:-1, 1:-1]
    return u2
现在使用
u2=evolve\u heat\u slow(u)

u2 =
array([[100, 100, 100, 100, 100],
       [100,  50,  25,  50, 100],
       [100,  25,   0,  25, 100],
       [100,  50,  25,  50, 100],
       [100, 100, 100, 100, 100]])

虽然不比其他方法好,但您也可以使用
np.在每个方向上滚动
,以执行相同的操作:

def evolve_heat_slow(u):
    u2 = u.copy()
    u2[1:-1, 1:-1] = ((np.roll(u2,1,0) + np.roll(u2,-1,0) 
                        + np.roll(u2,1,1) + np.roll(u2,-1,1))/4)[1:-1, 1:-1]
    return u2
现在使用
u2=evolve\u heat\u slow(u)

u2 =
array([[100, 100, 100, 100, 100],
       [100,  50,  25,  50, 100],
       [100,  25,   0,  25, 100],
       [100,  50,  25,  50, 100],
       [100, 100, 100, 100, 100]])

我不明白这是怎么回事,因为每个数字都应该是其相邻数字的平均值,而不是仅仅输入值。如果要将其放入一个定义中,而只输入原始numpy数组,它可能不起作用。对于小型阵列,您的代码可能更快。但我的是矢量化的,没有循环,这就是问题的目的。(将导入计算在基准测试中并不是一个公平的评估。)如果您想要不导入的东西,我假设您可以从
scipy
复制粘贴
convalve2d
和任何必要的支持函数。真的吗<代码>导入使代码速度减慢一次,大约一秒钟。然后你可以在之后的几小时或几天里继续乘法。为什么这一秒是相关的?我正在寻找的代码应该比什么快122倍?你是如何测量它的?(如果您正在执行
time python test.py
,那么这是完全错误的方法)。为什么是122?另外,如果scipy对您来说不够快,您应该将其移动到C或Fortran,因为这可能是Python中最快的方法。我不明白这是如何工作的,因为每个数字都应该是其相邻数字的平均值,而不是仅仅输入值。如果要将其放在定义中,仅输入原始numpy数组,它可能无法工作。对于小型阵列,您的代码可能更快。但我的是矢量化的,没有循环,这就是问题的目的。(将导入计算在基准测试中并不是一个公平的评估。)如果您想要不导入的东西,我假设您可以从
scipy
复制粘贴
convalve2d
和任何必要的支持函数。真的吗<代码>导入使代码速度减慢一次,大约一秒钟。然后你可以在之后的几小时或几天里继续乘法。为什么这一秒是相关的?我正在寻找的代码应该比什么快122倍?你是如何测量它的?(如果您正在执行
time python test.py
,那么这是完全错误的方法)。为什么是122?另外,如果
scipy
对您来说不够快,您应该将它移到C或Fortran,因为这可能是用Python实现它的最快方法。@akhilrastogi您不喜欢Amadan的答案对我来说真的很奇怪。在你的示例阵列上,这个答案比Amadan的慢7倍,在较大的阵列上慢一个数量级以上。@akhilrastogi这比Amadan的快122倍吗?@akhilrastogi你不喜欢Amadan的答案对我来说真的很奇怪。在示例数组中,这个答案比Amadan的慢7倍,在较大的数组中慢一个数量级以上。@akhilrastogi是122倍吗?如果您有这样的代码类型,您可以使用Numba对其进行编译和多线程处理。这通常优于矢量化解决方案,除了BLAS调用(例如np.dot,…)之外。如果您有这种类型的代码,您可以使用Numba进行编译和多线程处理。这通常优于矢量化解决方案,除了BLAS调用(例如np.dot,…)