Numpy快速检查完全数组相等,就像Matlabs isequal

ger*_*rit 8 python arrays numpy

在Matlab中,内置isequal函数检查两个数组是否相等.如果它们不相等,这可能会非常快,因为一旦存在差异,实施可能会停止检查:

>> A = zeros(1e9, 1, 'single');    
>> B = A(:);                     
>> B(1) = 1;
>> tic; isequal(A, B); toc;
Elapsed time is 0.000043 seconds.
Run Code Online (Sandbox Code Playgroud)

Python/numpy中是否有任何等价? all(A==B)或者all(equal(A, B))速度慢得多,因为它比较了所有元素,即使最初的元素不同:

In [13]: A = zeros(1e9, dtype='float32')                                                                                                                                                           

In [14]: B = A.copy()

In [15]: B[0] = 1

In [16]: %timeit all(A==B)
1 loops, best of 3: 612 ms per loop
Run Code Online (Sandbox Code Playgroud)

是否有任何numpy等价物?这应该是很容易用C实现,但在Python实现,因为这是我们做的情况下缓慢并不想进行广播,所以它需要一个明确的循环.

编辑:

它看起来array_equal像我想要的.但是,它并不比它快all(A==B),因为它不是内置的,而只是一个简短的Python函数A==B.所以它不符合我快速检查的需要.

In [12]: %timeit array_equal(A, B)
1 loops, best of 3: 623 ms per loop
Run Code Online (Sandbox Code Playgroud)

tom*_*m10 7

首先,应该注意的是,在OP的示例中,数组具有相同的元素,因为B=A[:]它只是数组的视图,因此:

>>>  print A[0], B[0]
1.0, 1.0
Run Code Online (Sandbox Code Playgroud)

但是,虽然测试不合适,但基本的抱怨是正确的:Numpy没有短路等效性检查.

人们可以很容易地看到从,所有的allclose,array_equal以及array_equiv是在刚刚变化all(A==B),以满足他们各自的细节,并没有显着的速度更快.

numpy的一个优点是切片只是视图,因此非常快,所以人们可以相当容易地编写自己的短路比较(我不是说这是理想的,但确实有效):

from numpy import *

A = zeros(1e8, dtype='float32')                                                                                                                                                         
B = A[:]
B[0] = 1
C = array(B)
C[0] = 2
D = array(A)
D[-1] = 2

def short_circuit_check(a, b, n):
    L = len(a)/n
    for i in range(n):
        j = i*L
        if not all(a[j:j+L]==b[j:j+L]):
                return False
    return True


In [26]: %timeit short_circuit_check(A, C, 100)   # 100x faster
1000 loops, best of 3: 1.49 ms per loop

In [27]: %timeit all(A==C)
1 loops, best of 3: 158 ms per loop

In [28]: %timeit short_circuit_check(A, D, 100)
10 loops, best of 3: 144 ms per loop

In [29]: %timeit all(A==D)
10 loops, best of 3: 160 ms per loop
Run Code Online (Sandbox Code Playgroud)