Numpy快速检查完整的数组相等,就像Matlab isequal

时间:2014-10-08 15:34:28

标签: 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.

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

是否有任何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

1 个答案:

答案 0 :(得分:6)

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

>>>  print A[0], B[0]
1.0, 1.0

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

可以从the source轻松看到allclosearray_equalarray_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