【发布时间】:2012-12-20 18:15:24
【问题描述】:
我正在尝试学习 nditer 以可能用于加快我的应用程序。在这里,我尝试制作一个有趣的重塑程序,该程序将采用大小为 20 的数组并将其重塑为 5x4 数组:
myArray = np.arange(20)
def fi_by_fo_100(array):
offset = np.array([0, 4, 8, 12, 16])
it = np.nditer([offset, None],
flags=['reduce_ok'],
op_flags=[['readonly'],
['readwrite','allocate']],
op_axes=[None, [0,1,-1]],
itershape=(-1, 4, offset.size))
while not it.finished:
indices = np.arange(it[0],(it[0]+4), dtype=int)
info = array.take(indices)
'''Just for fun, we'll perform an operation on data.\
Let's shift it to 100'''
info = info + 81
it.operands[1][...]=info
it.iternext()
return it.operands[1]
test = fi_by_fo_100(myArray)
>>> test
array([[ 97, 98, 99, 100]])
显然,程序将每个结果都覆盖到一行中。所以我尝试使用nditer的索引功能,但仍然没有骰子。
flags=['reduce_ok','c_iter'] --> it.operands[1][it.index][...]=info =IndexError: index out of bounds
flags=['reduce_ok','c_iter'] --> it.operands[1][it.iterindex][...]=info =IndexError: index out of bounds
flags=['reduce_ok','multi_iter'] --> it.operands[1][it.multi_index][...]=info =IndexError: index out of bounds
it[0][it.multi_index[1]][...]=info = IndexError: 0-d arrays can't be indexed
...等等。我错过了什么?提前致谢。
奖金问题
我刚刚遇到this nice article on nditer。我可能是 Numpy 的新手,但这是我第一次看到 Numpy 速度基准如此落后。我的理解是人们选择 Numpy 是因为它的数值速度和能力,但迭代是其中的一部分,不是吗?如果它这么慢,nditer 有什么意义?
【问题讨论】:
-
请记住,
numpy的全部意义在于避免迭代,并通过矢量化操作完成所有操作。虽然nditer被设计为迭代numpy数组的最有效方式,但您仍在执行Python 循环而不是向量操作,因此减速(通常是非常大的减速)几乎是不可避免的。您链接的文章详细解释了这一点(尽管就 PyPy 而言它有点过时......支持不是 100% 完成,但import numpypy; import numpy as np绝对可以玩弄)。 -
另外,我假设您已经知道这一点,并且在这里学习
nditer比找到最快的方法更感兴趣,但以防万一:def fi_by_fo_100(array): return array.reshape(5, 4) + 81。 -
@abarnert 我并没有真正理解他们在那篇文章中所说的一切,但感谢您的总结。是的,我知道
reshape。这只是对我的启迪的一个小教程。但是回到速度这个话题,当你说“矢量化操作”时,你的意思是numpy.vectorize吗?您是否暗示我的努力会更好地用于学习 numpy.vectorize? -
不,我的意思是在
numpy中进行元素操作,就像使用info = info + 81而不是for x in range(info.size): info[x] = info[x] + 81。只要可以用前一种方式写东西,它就会快得多。 -
同时,您的问题是
it.operands[1]是整个输出迭代,并且您每次通过循环重新分配整个事物。您只想分配一行。但是,我可以看到您已经尝试找到方法来做到这一点,所以我猜您已经想通了。您是否对为什么您的尝试不起作用或什么会起作用感兴趣?