Reputation: 57
I running into some performance problems and I would appreciate a quick look at this.
I'm reading frequency domain data and I need to make a data cube for compensating the start frequencies in time domain.
The way I do this now is:
compdata = [[np.exp(t_range*sflist[y]) for y in x] for x in sfcube]
where
t_range = 1j*2*np.pi*time_axis_ns
time_axis_ns = np.array([x*delta_time_ns for x in xrange(number_of_points_for_fft)])
sflist = array([ 29500000., 30500000.])
sfcube is a NxM array with indexes for sflist.
Calculating compdata is by far the slowest part of my program now, any ideas for optimization?
Upvotes: 2
Views: 204
Reputation: 67427
Here's your calculation and an alternative, more numpythonic take on it:
compdata = [[np.exp(t_range*sflist[y]) for y in x] for x in sfcube]
compdata2 = np.take(np.exp(sflist[:, None] * t_range), sfcube, axis=0)
With this sample data set based on your question:
sfcube = np.random.randint(2, size=(100, 100))
delta_time_ns = 100
number_of_points_for_fft = 1024
time_axis_ns = np.array([x*delta_time_ns for x in xrange(number_of_points_for_fft)])
t_range = 1j*2*np.pi*time_axis_ns
sflist = np.array([ 29500000., 30500000.])
I get these timings:
In [3]: %timeit compdata = [[np.exp(t_range*sflist[y]) for y in x] for x in sfcube]
1 loops, best of 3: 1.76 s per loop
In [4]: %timeit compdata2 = np.take(np.exp(sflist[:, None] * t_range), sfcube, axis=0)
10 loops, best of 3: 72.2 ms per loop
That's a 20x speed-up, although your result will change, depending on the actual sizes of sflist
and sfcube
. And what you get is a 3D numpy array, not a list of lists of arrays, although they are interchangeable in most settings, and of course:
In [5]: np.allclose(compdata, compdata2)
Out[5]: True
Upvotes: 1
Reputation: 10721
Firstly, you can create your time_axis_ns
array using:
time_axis_ns = np.arange(number_of_points_for_fft)*delta_time_ns
Then rather than you iterating over indices in sfcube:
sflist[sfcube]
Should give the same result. Then do your np.exp(t_range*
on the result of this.
Upvotes: 0
Reputation: 134601
Quick win would be to parallelize it across all your CPU cores (+HT if available) using multiprocessing module.
from multiprocessing import Pool
pool = Pool(16) ## use total number of cores, x2 if HT is supported.
def f(y):
return np.exp(t_range*sflist[y])
compdata = [pool.map(f, x) for x in sfcube]
Of course this will get you 4-fold to 16-fold speed improvement (depending on number of cores). Still, if that's not good enough, you need to figure out how to do that with vector/matrix operations.
Upvotes: 1
Reputation: 16049
If you have an array of indices, you can use it to vectorize the calculation:
In [1]: a = numpy.random.random((4,4))
In [2]: a
Out[2]:
array([[ 0.08746418, 0.57716752, 0.85863208, 0.42931856],
[ 0.90259153, 0.19590983, 0.73075288, 0.88976529],
[ 0.71843135, 0.0169308 , 0.98336314, 0.22227009],
[ 0.93776916, 0.58943769, 0.55040806, 0.92192396]])
In [3]: a[0]
Out[3]: array([ 0.08746418, 0.57716752, 0.85863208, 0.42931856])
In [7]: index=[(0,1), (0,1)]
In [8]: a[index]
Out[8]: array([ 0.08746418, 0.19590983])
In [9]: a[index] = 100*a[index]
In [10]: a[index]
Out[10]: array([ 8.74641837, 19.59098276])
This is usually much faster than using Python lists. Note that a is a NumPy array from the start, and the the indices I use are in the form a[list_of_rows, list_of_columns]
Upvotes: 0
Reputation: 157
You can use Python-psyco library
http://psyco.sourceforge.net/
http://en.wikipedia.org/wiki/Psyco
or any other similar library
It may speed up your program.
Upvotes: 0