Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.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
Numpy 如何使np.roll()更快?_Numpy_Scipy - Fatal编程技术网

Numpy 如何使np.roll()更快?

Numpy 如何使np.roll()更快?,numpy,scipy,Numpy,Scipy,我使用np.roll()来做最近邻平均,但我感觉有更快的方法。这里是一个简化的,但想象一下3维和更复杂的平均“模板”。举个例子,参见本手册第6节 下面是该简化示例中的几行: for j in range(nper): phi2 = 0.25*(np.roll(phi, 1, axis=0) + np.roll(phi, -1, axis=0) + np.roll(phi, 1, axis=1) +

我使用np.roll()来做最近邻平均,但我感觉有更快的方法。这里是一个简化的,但想象一下3维和更复杂的平均“模板”。举个例子,参见本手册第6节

下面是该简化示例中的几行:

for j in range(nper):
    phi2 = 0.25*(np.roll(phi,  1, axis=0) +
                 np.roll(phi, -1, axis=0) +
                 np.roll(phi,  1, axis=1) +
                 np.roll(phi, -1, axis=1) )
    phi[do_me] = phi2[do_me]
那么,我应该寻找返回视图而不是数组的东西吗?在这种情况下,roll是否在每次调用新数组时初始化它?我注意到小型阵列的开销很大

事实上,对于我的笔记本电脑上[100100]到[300300]大小的阵列来说,这是最有效的。可能存在上述问题

scipy.ndimage.interpolation.shift()
的实现方式是否会更好,如果是这样,在上面的链接示例中,我会丢弃包装好的部分,但可能并不总是这样


注意:在这个问题中,我只查找NumPy/SciPy中可用的内容。当然,有很多很好的方法可以加速Python甚至NumPy,但这不是我在这里要寻找的,因为我真的想更好地理解NumPy。谢谢

np.roll
每次都必须创建一个数组副本,这就是它(相对)较慢的原因。使用类似于
scipy.ndimage.filters.convolve()
的函数进行卷积会快一点,但仍可能创建副本(取决于实现)

在这种特殊情况下,我们可以通过在开始时使用和填充原始数组来避免完全复制

将numpy导入为np
def无拷贝卷(nx,ny):
phi_padded=np.零((ny+2,nx+2))
#这些是phi_填充的不同子阵列的视图
#如果两个子数组重叠,则它们共享内存
菲尤北=菲尤加垫[:-2,1:-1]
phi_east=phi_填充[1:-1,2:]
phi_south=phi_填充[2:,1:-1]
phi_west=phi_填充[1:-1,:-2]
φ=φ_填充[1:-1,1:-1]
do_me=np.zero_like(phi,dtype='bool')
Dou me[1:-1,1:-1]=真
x0,y0,r0=40,65,12
x=np.arange(nx,dtype='float')[None,:]
y=np.arange(ny,dtype='float')[:,无]
rsq=(x-x0)**2+(y-y0)**2

circle=rsq到目前为止,我能得到的最快实现是基于您已经提到的
scipy.ndimage.interpolation.shift
的底层实现:

from scipy.ndimage.interpolation import _nd_image, _ni_support

cval = 0.0  # unused for mode `wrap`
mode = _ni_support._extend_mode_to_code('wrap')
_nd_image.zoom_shift(data, None, shift, data, 0, mode, cval)  # in-place update

预先计算
模式
cval
shift
调用低级的
zoom\u shift
方法直接让我了解了x5的加速比wrt。调用
shift
和x10加速wrt
np.roll

进行最近邻平均,您考虑过卷积吗?
np.roll
构造索引数组,并返回
a.take(索引,轴)
。这就是较慢的高级索引<“代码>跨步”
被认为是一种使用滑动窗口的更快方法。可能会给出一些想法,例如,使用跨步和滑动来构造滑动窗口。您的问题并不完全清楚您在寻找什么-如果您向我们展示您当前的解决方案,这将很有帮助。以及
scipy.ndimage.convolve
如果你只想得到最近邻平均值,你可以简单地使用
scipy.ndimage.uniform_filter
+1
哇,感谢你花时间写出如此全面而周到的答案!多年来,我一直在避免学习撇渣,也许这就是我需要深入研究的理由:-)顺便说一句,从五年前发布这个问题到今天,我几乎每天都在使用Python,但我仍然是个业余爱好者。行
Program:timing.py
让我困惑,这是按原样运行的吗?@uhoh
timing.py
是我给上述基准脚本的名称,用于比较代码的原始版本和零拷贝版本。对不起,如果你不明白的话。这是
pyinstrument
一个非常好的python分析器输出的一部分。谢谢,我感谢您的耐心,并将很快尝试所有这些!这个问题每隔一段时间就会出现,下次我会试试,让你知道它是怎么回事。谢谢
37.685 <module>  timing.py:1
├─ 22.413 original_roll  original.py:4
│  ├─ 15.056 [self]
│  └─ 7.357 roll  <__array_function__ internals>:2
│     └─ 7.243 roll  numpy\core\numeric.py:1110
│           [10 frames hidden]  numpy
├─ 14.709 no_copy_roll  mwe.py:4
└─ 0.393 allclose  <__array_function__ internals>:2
   └─ 0.393 allclose  numpy\core\numeric.py:2091
         [2 frames hidden]  numpy
            0.391 isclose  <__array_function__ internals>:2
            └─ 0.387 isclose  numpy\core\numeric.py:2167
                  [4 frames hidden]  numpy
from scipy.ndimage.interpolation import _nd_image, _ni_support

cval = 0.0  # unused for mode `wrap`
mode = _ni_support._extend_mode_to_code('wrap')
_nd_image.zoom_shift(data, None, shift, data, 0, mode, cval)  # in-place update