Fastest way to populate a matrix with a function on pairs of elements in two numpy vectors?

前端 未结 3 1965
无人及你
无人及你 2021-01-14 14:52

I have two 1 dimensional numpy vectors va and vb which are being used to populate a matrix by passing all pair combinations to a function.

3条回答
  •  时光取名叫无心
    2021-01-14 15:09

    Like @shx2 said, it all depends on what is foo. If you can express it in terms of numpy ufuncs, then use outer method:

    In [11]: N = 400
    
    In [12]: B = np.empty((N, N))
    
    In [13]: x = np.random.random(N)
    
    In [14]: y = np.random.random(N)
    
    In [15]: %%timeit
    for i in range(N):
       for j in range(N):
         B[i, j] = x[i] - y[j]
       ....: 
    10 loops, best of 3: 87.2 ms per loop
    
    In [16]: %timeit A = np.subtract.outer(x, y)   # <--- np.subtract is a ufunc
    1000 loops, best of 3: 294 µs per loop
    

    Otherwise you can push the looping down to cython level. Continuing a trivial example above:

    In [45]: %%cython
    cimport cython
    @cython.boundscheck(False)
    @cython.wraparound(False)
    def foo(double[::1] x, double[::1] y, double[:, ::1] out):
        cdef int i, j
        for i in xrange(x.shape[0]):
            for j in xrange(y.shape[0]):
                out[i, j] = x[i] - y[j]
       ....: 
    
    In [46]: foo(x, y, B)
    
    In [47]: np.allclose(B, np.subtract.outer(x, y))
    Out[47]: True
    
    In [48]: %timeit foo(x, y, B)
    10000 loops, best of 3: 149 µs per loop
    

    The cython example is deliberately made overly simplistic: in reality you might want to add some shape/stride checks, allocate the memory within your function etc.

提交回复
热议问题