Where possible, using numpy functions and operators that operate on the whole arrays, and do the necessary broadcasting
for you:
In [24]: A = np.array([1.0,2.0]); t = np.linspace(0.0, 1.0, 10)
In [25]: x = t[:,None] * A[None,:]
In [26]: x.shape
Out[26]: (10, 2)
In [27]: x[:3,:]
Out[27]:
array([[0. , 0. ],
[0.11111111, 0.22222222],
[0.22222222, 0.44444444]])
In [28]: np.sin(t)
Out[28]:
array([0. , 0.11088263, 0.22039774, 0.3271947 , 0.42995636,
0.52741539, 0.6183698 , 0.70169788, 0.77637192, 0.84147098])
If you have a function that only works with scalar inputs, you can use np.vectorize
to feed it those values - from broadcasted arrays:
In [30]: def foo(A,t):
...: return t*A
...:
In [31]: f = np.vectorize(foo, otypes=[float])
In [32]: f(A[None,:], t[:,None])
Out[32]:
array([[0. , 0. ],
[0.11111111, 0.22222222],
[0.22222222, 0.44444444],
....
[1. , 2. ]])
vectorize
is a convenience function; it does not promise speed. Compare its time with In[25]
:
In [33]: timeit f(A[None,:], t[:,None])
41.3 µs ± 48.5 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [34]: timeit x = t[:,None] * A[None,:]
5.41 µs ± 8.2 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
8x slower.
Or with the scalar math.sin
function:
In [35]: import math
In [36]: g = np.vectorize(math.sin)
...
In [39]: timeit g(t)
39 µs ± 72.4 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
In [40]: timeit np.sin(t)
1.4 µs ± 2.72 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Called iteratively math.sin
is faster than np.sin
, but np.sin
is much faster when given a whole array.
The basic difference is that vectorize
, like explicit loops is iterating in interpreted Python, and calling your function once for each output element. np.sin
and array *
is iterating, but in compiled code.
There are various ways of iterating in Python and numpy, but rarely do they give you more than a 2x speedup.
There are tools for moving calculations to compiled code, such as cython
and numba
. Search on those tags to get ideas on how to use them.