Nice to know simple optimizations for python

This to-be-updated blog-post will contain some simple optimisations for Python.

Numpy - define an array of values, best strategy

If you want to construct an array in which all values are equal there are multiple approaches. Lets time two approaches and check what is faster:

Array length 4, filled with 50:

>>> timeit.timeit(stmt='a=np.ones((1,4))*5', setup='import numpy as np', number=1000000)
2.780178565000824
>>> timeit.timeit(stmt='a=np.zeros((1,4))+5', setup='import numpy as np', number=1000000)
1.2084406799986027
>>> timeit.timeit(stmt='a=np.full((1,4),5)', setup='import numpy as np', number=1000000)
1.5506706800006214
>>> timeit.timeit(stmt='a=np.empty((1,4,));a[:]=50', setup='import numpy as np', number=10000000)
7.5454642989989225
>>> timeit.timeit(stmt='a=np.empty((1,4,));a.fill(50)', setup='import numpy as np', number=10000000)
5.603505196999322

Array length 40, filled with 50:

>>> timeit.timeit(stmt='a=np.ones((1,40))*50', setup='import numpy as np', number=10000000)
28.332619561000683
>>> timeit.timeit(stmt='a=np.zeros((1,40))+50', setup='import numpy as np', number=10000000)
12.163550770999791
>>> timeit.timeit(stmt='a=np.full((1,40),50)', setup='import numpy as np', number=10000000)
15.727678253000704
>>> timeit.timeit(stmt='a=np.empty((1,40,));a[:]=50', setup='import numpy as np', number=10000000)
7.71038524100004
>>> timeit.timeit(stmt='a=np.empty((1,40,));a.fill(50)', setup='import numpy as np', number=10000000)
5.823411160999967

Array length 400, filled with 50:

>>> timeit.timeit(stmt='a=np.ones((1,400))*50', setup='import numpy as np', number=10000000)
33.2022760079999
>>> timeit.timeit(stmt='a=np.zeros((1,400))+50', setup='import numpy as np', number=10000000)
17.502198547999797
>>> timeit.timeit(stmt='a=np.full((1,400),50)', setup='import numpy as np', number=10000000)
18.580837157000133
>>> timeit.timeit(stmt='a=np.empty((1,400,));a[:]=50', setup='import numpy as np', number=10000000)
9.875230586998441
>>> timeit.timeit(stmt='a=np.empty((1,400,));a.fill(50)', setup='import numpy as np', number=10000000)
8.185147824000524

Array length 4000, filled with 50:

>>> timeit.timeit(stmt='a=np.ones((1,4000))*50', setup='import numpy as np', number=10000000)
68.02982943499956
>>> timeit.timeit(stmt='a=np.zeros((1,4000))+50', setup='import numpy as np', number=10000000)
40.300352407999526
>>> timeit.timeit(stmt='a=np.full((1,4000),50)', setup='import numpy as np', number=10000000)
38.26363668100021
>>> timeit.timeit(stmt='a=np.empty((1,4000,));a[:]=50', setup='import numpy as np', number=10000000)
24.46817981500135
>>> timeit.timeit(stmt='a=np.empty((1,4000,));a.fill(50)', setup='import numpy as np', number=10000000)
22.387818323999454

Which shows clearly (when using longer arrays) allocation before initialisation is the fastest method.

Matplotlib; and the slowness of drawing

Drawing with Matplotlib can be tediously slow. This can be easily solved by using a different backend. And while we are at it, we can define quite some other parameters as well using the matplotlib config file (or the matplotlibrc file). Here I refer to: http://matplotlib.org/users/customizing.html

The slow drawing can be improved by using a different backend. Use the example matplotlibrc file and search for the keyword: backend. I chose the TkAgg backend and looked no further (it was good enough). Test for yourself to see what suits you. Also see: http://matplotlib.org/faq/usage_faq.html#what-is-a-backend.

Conclusion

I would say… these are good to know!

~ Patrick