python - Why list comprehension is much faster than numpy for multiplying arrays? -
recently answered this question wanted multiplication of 2 lists,some user suggested following way using numpy, alongside mine think proper way :
(a.t*b).t
also found aray.resize()
has same performance that. way answer suggested solution using list comprehension :
[[m*n n in second] m, second in zip(b,a)]
but after benchmark saw list comprehension performs faster numpy :
from timeit import timeit s1=""" a=[[2,3,5],[3,6,2],[1,3,2]] b=[4,2,1] [[m*n n in second] m, second in zip(b,a)] """ s2=""" a=np.array([[2,3,5],[3,6,2],[1,3,2]]) b=np.array([4,2,1]) (a.t*b).t """ print ' first: ' ,timeit(stmt=s1, number=1000000) print 'second : ',timeit(stmt=s2, number=1000000,setup="import numpy np")
result :
first: 1.49778485298 second : 7.43547797203
as can see numpy approximately 5 time faster. surprising thing faster without using transpose, , following code :
a=np.array([[2,3,5],[3,6,2],[1,3,2]]) b=np.array([[4],[2],[1]]) a*b
the list comprehension still 5 time faster.so besides of point list comprehensions performs in c here used 2 nested loop , zip
function can reason? because of operation *
in numpy?
also note there no problem timeit
here putted import
part in setup
.
i tried larger arras, difference gets lower still doesn't make sense :
s1=""" a=[[2,3,5],[3,6,2],[1,3,2]]*10000 b=[4,2,1]*10000 [[m*n n in second] m, second in zip(b,a)] """ s2=""" a=np.array([[2,3,5],[3,6,2],[1,3,2]]*10000) b=np.array([4,2,1]*10000) (a.t*b).t """ print ' first: ' ,timeit(stmt=s1, number=1000) print 'second : ',timeit(stmt=s2, number=1000,setup="import numpy np")
result :
first: 10.7480301857 second : 13.1278889179
creation of numpy arrays slower creation of lists:
in [153]: %timeit = [[2,3,5],[3,6,2],[1,3,2]] 1000000 loops, best of 3: 308 ns per loop in [154]: %timeit = np.array([[2,3,5],[3,6,2],[1,3,2]]) 100000 loops, best of 3: 2.27 µs per loop
there can fixed costs incurred numpy function calls before meat of calculation can performed fast underlying c/fortran function. can include ensuring inputs numpy arrays,
these setup/fixed costs keep in mind before assuming numpy solutions inherently faster pure-python solutions. numpy shines when set large arrays once , perform many fast numpy operations on arrays. may fail outperform pure python if arrays small because setup cost can outweigh benefit of offloading calculations compiled c/fortran functions. small arrays there may not enough calculations make worth it.
if increase size of arrays bit, , move creation of arrays setup, numpy can faster pure python:
import numpy np timeit import timeit n, m = 300, 300 = np.random.randint(100, size=(n,m)) b = np.random.randint(100, size=(n,)) a2 = a.tolist() b2 = b.tolist() s1=""" [[m*n n in second] m, second in zip(b2,a2)] """ s2 = """ (a.t*b).t """ s3 = """ a*b[:,none] """ assert np.allclose([[m*n n in second] m, second in zip(b2,a2)], (a.t*b).t) assert np.allclose([[m*n n in second] m, second in zip(b2,a2)], a*b[:,none]) print 's1: {:.4f}'.format( timeit(stmt=s1, number=10**3, setup='from __main__ import a2,b2')) print 's2: {:.4f}'.format( timeit(stmt=s2, number=10**3, setup='from __main__ import a,b')) print 's3: {:.4f}'.format( timeit(stmt=s3, number=10**3, setup='from __main__ import a,b'))
yields
s1: 4.6990 s2: 0.1224 s3: 0.1234
Comments
Post a Comment