2013-06-25 48 views
2

我遇到了一些性能问题,我希望快速浏览一下。在python中加速循环

我正在阅读频域数据,我需要制作一个数据立方体来补偿时域的起始频率。

我现在做到这一点的方法是:

compdata = [[np.exp(t_range*sflist[y]) for y in x] for x in sfcube] 

其中

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是N×M的阵列与sflist索引。

计算compdata是我现在程序中最慢的部分,任何有关优化的想法?

+0

您已经标记了的问题为'bumpy',但似乎就像你在最慢的部分使用普通的Python列表理解一样。 'sfcube'和'sflist' numpy数组?如果是这样,你可以做一些聪明的索引来向量化指数。 – mbatchkarov

+0

是的,sfcube和sflist都是numpy数组 – HenrikW

+0

'compdata = np.exp([[(t_range * sflist [y])for y in x] for s in sfcube])'这应该会更快。如果您一次使用整个numpy列表或numpy数组的函数,它将在C中迭代,并且会比python迭代快得多。 – Froyo

回答

0

如果你有索引的数组,你可以用它来矢量化计算:

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]) 

这通常比使用Python列表快得多。注意,是从一开始就与NumPy阵列,和我用的是指数形式a[list_of_rows, list_of_columns]

1

快速取胜将您所有的CPU内核并行化的利用多重模块(+ HT如果可用)。

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] 

当然,这将使您获得4倍至16倍的速度提升(取决于内核数量)。不过,如果这还不够好,你需要弄清楚如何用矢量/矩阵运算来实现。然后

time_axis_ns = np.arange(number_of_points_for_fft)*delta_time_ns 

,而不是你遍历指数在sfcube:

0

首先,你可以通过创建time_axis_ns阵列

sflist[sfcube] 

应该给予同样的结果。然后做你的np.exp(t_range*这个结果。

+0

虽然有效,但速度大致相同。 – HenrikW

1

这是你的计算和选择,更numpythonic对其采取:

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) 

有了这个样本数据集基于你的问题:

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.]) 

我得到这些时间:

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 

这是一个20倍的加速,虽然你的结果会改变,这取决于实际尺寸sflistsfcube。而你得到的是一个三维numpy的阵列,而不是一个数组列表的列表中,虽然它们在大多数的设置可以互换,当然:

In [5]: np.allclose(compdata, compdata2) 
Out[5]: True