2015-01-21 24 views
5

Rozważ następujące dwie funkcje, które zasadniczo mnożą każdą liczbę w małej sekwencji z każdą liczbą w większej sekwencji, aby zbudować tablicę 2D, a następnie podwajają wszystkie wartości w tablica. noloop() używa bezpośredniego mnożenia tablic 2D numpy i zwraca wynik, podczas gdy loop() używa pętli for do iteracji ponad arr1 i stopniowo buduje tablicę wyjściową.Dlaczego pętle są szybsze niż numpy dla mnożenia macierzy dwuwymiarowych

import numpy as np 

arr1 = np.random.rand(100, 1) 
arr2 = np.random.rand(1, 100000) 

def noloop(): 
    return (arr1*arr2)*2 

def loop(): 
    out = np.empty((arr1.size, arr2.size)) 
    for i in range(arr1.size): 
     tmp = (arr1[i]*arr2)*2 
     out[i] = tmp.reshape(tmp.size) 
    return out 

Spodziewałem noloop się znacznie szybciej, nawet dla niewielkiej liczby iteracji, ale tablica o rozmiarach powyżej loop jest rzeczywiście szybciej:

>>> %timeit noloop() 
10 loops, best of 3: 64.7 ms per loop 
>>> %timeit loop() 
10 loops, best of 3: 41.6 ms per loop 

I co ciekawe, jeśli usunąć *2 zarówno tam

>>> %timeit noloop() 
10 loops, best of 3: 29.4 ms per loop 
>>> %timeit loop() 
10 loops, best of 3: 34.4 ms per loop 

jest dobrym wytłumaczeniem th: funkcje, noloop jest szybsza, ale tylko nieznacznie ese wyniki i czy istnieje znacznie szybszy sposób na wykonanie tego samego zadania?

+2

uzyskać 'noloop()' jest szybszy (o ~ 15%) niż 'pętli()' niezależnie ... –

+0

ja również uzyskać na odwrotnej zarówno python2, jak i python3. –

+1

"Pętla" jest szybsza, jak sugeruje OP (o 28% w moim komputerze). Python 3.4.1 | Anaconda 2.1.0, IPython 2.2.0 – Roberto

Odpowiedz

0

Nie udało mi się odtworzyć wyników, ale zauważyłem, że mogę uzyskać znaczną prędkość (współczynnik 2) przy użyciu numpy.multiply. Za pomocą argumentu out można skorzystać z faktu, że pamięć jest już przydzielona i wyeliminować kopiowanie z tmp do out.

def out_loop(): 
    out = np.empty((arr1.size, arr2.size)) 
    for i in range(arr1.size): 
     np.multiply(arr1[i], arr2, out=out[i].reshape((1, arr2.size))) 
     out[i] *= 2 
    return out 

Wyniki na moim komputerze:

In [32]: %timeit out_loop() 
100 loops, best of 3: 17.7 ms per loop 

In [33]: %timeit loop() 
10 loops, best of 3: 28.3 ms per loop 
Powiązane problemy