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

Popular posts from this blog

python - pip install -U PySide error -

arrays - C++ error: a brace-enclosed initializer is not allowed here before ‘{’ token -

cytoscape.js - How to add nodes to Dagre layout with Cytoscape -