了解Numpy内部结构以进行分析

了解Numpy内部结构以进行分析,numpy,profiling,Numpy,Profiling,分析一段numpy代码表明,我大部分时间都在这两个函数中 numpy/matrixlib/defmatrix.py.__getitem__:301 numpy/matrixlib/defmatrix.py.__array_finalize__:279 以下是Numpy的来源: 问题1: \uuuu getitem\uuuu似乎每次我使用类似于my\u array[arg]的东西时都会被调用,如果arg不是一个整数而是一个片,那么它的代价会越来越高。有没有办法加快对数组切片的调用 例如在

分析一段numpy代码表明,我大部分时间都在这两个函数中

numpy/matrixlib/defmatrix.py.__getitem__:301
numpy/matrixlib/defmatrix.py.__array_finalize__:279
以下是Numpy的来源:

问题1:

\uuuu getitem\uuuu
似乎每次我使用类似于
my\u array[arg]
的东西时都会被调用,如果
arg
不是一个整数而是一个片,那么它的代价会越来越高。有没有办法加快对数组切片的调用

例如在

for i in range(idx): res[i] = my_array[i:i+10].mean()
问题2:

确切地说,
\uuuuuu array\u finalize\uuuu
什么时候被调用?如何通过减少对该函数的调用次数来加快速度


谢谢

不能像使用矩阵那样多,只能使用2d numpy数组。我通常只在很短的时间内使用矩阵来利用乘法的语法(但通过在数组上添加.dot方法,我发现这样做的次数也越来越少)

但是,对于你的问题:

1) 到
\uu getitem\uuuuuuuuu
真的没有捷径,除非defmatrix超越了
\uuuuu getslice\uuuuuuuuu
,它可以做到但还没有做到。有.item和.itemset方法,它们针对整数获取和设置进行了优化(并返回Python对象,而不是NumPy的数组标量)

2) 每当创建数组对象(或子类)时,都会调用
\uuuuuuu数组\uu finalize\uuuu
。它是从C函数调用的,每个数组创建都会通过它


对于纯用Python定义的子类,它从C调用Python解释器,这会产生开销。如果matrix类是内置类型(例如,基于Cython的cdef类),那么调用可以避免Python解释器开销。

问题1:

由于数组片有时可能需要底层数据结构的副本(将指向内存中数据的指针保存在内存中),因此它们可能非常昂贵。如果你在上面的例子中真的被这个限制住了,你可以通过迭代i到i+10元素并手动创建平均值来执行平均值操作。对于某些操作,这不会带来任何性能改进,但避免创建新的数据结构通常会加快该过程

另一个注意事项是,如果在numpy中不使用本机类型,那么在操作numpy数组时会受到很大的性能损失。假设您的数组具有dtype=float64,并且您的本机计算机浮点大小为float32——这将为numpy消耗大量额外的计算能力,并且总体性能将下降。有时候,这很好,您只需承担维护数据类型的风险。其他时候,float或int在内部存储为什么类型是任意的。在这些情况下,请尝试使用dtype=float而不是dtype=float64。Numpy应默认为本机类型。通过这一改变,我在numpy密集型算法上获得了3倍以上的加速

问题2:


每当系统从obj内部分配新数组时,将调用
\uuu数组\u finalize\uuu
,其中obj是“根据”的(大)数据数组的子类(子类型)。因此,这是第一个问题中描述的结果。切片并制作新阵列时,必须通过制作结构副本或包装原始结构来完成该阵列。这个操作需要时间。避免切片将在此操作中保存,但对于多维数据,可能无法完全避免调用
\uuuu array\u finalize\uuuu

很高兴看到您,欢迎!那么,这是否意味着numpy用户列表上的一些问题将转发给So?非常感谢您的回答,特拉维斯!切换到2D数组真的很容易,而且是摆脱那些不必要调用的好方法。谢谢你,Pyrce,坚持使用固定类型(float32完全可以)也是个好主意!