我已经使用numpy一段时间了,并且通过使用index
操作来访问数组,就像 python 列表一样,如下所示:
img = np.zeros((640,480,3))
img[34, 19, 2]
但是,在阅读某本书时,我遇到了项目和项集方法.
根据他们的文档,它们提供了性能改进。但是,至少在文档中解释了为什么会发生这种情况.
有人知道它的原因吗?
TL;DR:速度的差异来自item
/itemset
使用的不同类型,以及[]
运算符更通用的事实。实际上,两者都使用 Python 解释器的内置float
类型,同时img[34, 19, 2]
返回 python 对象np.float64
。而且,[]
运算符不仅支持直接索引,还支持数组子视图和数组过滤,这是item
/itemset
不支持的。
要完全理解为什么存在性能差异,应该查看 numpy 代码。item
和itemset
方法分别调用array_toscalar和array_setscalar。或者,直接获取和设置数组元素分别调用array_subscript和array_assign_subscript。
最后两种方法的成本更高一些,因为它们更通用。事实上,通过观察array_toscalar
和array_subscript
之间的差异,可以看到前者执行的计算很少,主要调用PyArray_MultiIndexGetItem调用DOUBLE_getitem,而后者执行更多的检查和分配,主要调用PyArray_Scalar调用scalar_value它本身执行间接跳转以最终生成np.float64
对象。
请注意,尽管item
和itemset
可以比[]
运算符快,但 CPython 中的 numpy 直接索引仍然很慢。Numba可以通过执行本机直接索引来大大加快速度。