NumPy中滥用as_strided的迭代算法



我想知道是否可以在不使用for循环的情况下编写迭代算法,使用as_strided和一些编辑内存的操作。

例如,如果我想编写一个算法,将数组中的数字替换为其邻居的和。我想出了这个令人讨厌的东西(是的,它将一个元素与两个正确的邻居相加,但它只是为了得到一个想法(:

import numpy as np
a = np.arange(10)
ops = 2
a_view_window = np.lib.stride_tricks.as_strided(a, shape = (ops,a.size - 2, 3), strides=(0,) + 2*a.strides)
a_view = np.lib.stride_tricks.as_strided(a, shape = (ops,a.size - 2), strides=(0,) + a.strides)
np.add.reduce(a_view_window, axis = -1, out=a_view)
print(a)

所以我取了一个由10个数字组成的数组,创建了这个奇怪的视图,它在不改变步幅的情况下增加了维度。因此,我的想法是,它将在伪新维度上运行,并重写以前的值,因此,当它到达下一个主要维度时,它将不得不从它重写的数据中读取,从而迭代地执行添加。

遗憾的是,这不起作用:(

(是的,我知道这是一种糟糕的做事方式,但我很好奇底层的numpy东西是如何工作的,以及它是否可以用这种方式被黑客入侵(

此代码导致Numpy 1.13之前的未定义行为,并且在较新版本中工作不合适以避免重叠/别名问题。实际上,您不能假设Numpy在输入/输出数组视图上按给定顺序迭代。事实上,Numpy经常使用SIMD指令来加速代码,有时还会告诉编译器视图之间没有重叠/混叠(使用restrict关键字(,这样它们可以生成更高效的代码。有关更多信息,您可以阅读ufuncs上的文档(以及本期(:

由于数据依赖性问题,ufunc输入和输出操作数内存重叠的操作在以前的NumPy版本中产生了未定义的结果。在NumPy 1.13.0中,这种操作的结果现在被定义为与没有内存重叠的等效操作相同
受影响的操作现在根据需要制作临时副本,以消除数据依赖关系。由于检测这些情况在计算上是昂贵的,因此使用了启发式方法,这在极少数情况下可能导致不必要的临时复制。对于数据相关性足够简单以便启发式分析的操作,即使阵列重叠,也不会进行临时复制,如果可以推断出不需要复制的话。

最新更新