在python中加速循环

时间:2013-06-25 09:26:20

标签: python numpy

我遇到了一些性能问题,我很高兴看到这个。

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

我现在这样做的方式是:

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是一个带有sflist索引的NxM数组。

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

5 个答案:

答案 0 :(得分: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倍(取决于核心数量)。不过,如果这还不够好,你需要弄清楚如何用矢量/矩阵运算来做到这一点。

答案 1 :(得分: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的实际尺寸。你得到的是一个3D numpy数组,而不是数组列表的列表,虽然它们在大多数设置中是可互换的,当然:

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

答案 2 :(得分:0)

您可以使用Python-psyco库

http://psyco.sourceforge.net/
http://en.wikipedia.org/wiki/Psyco

或任何其他类似的图书馆

它可能会加快您的计划。

答案 3 :(得分: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列表快得多。请注意,a从一开始就是一个NumPy数组,我使用的索引的格式为a[list_of_rows, list_of_columns]

答案 4 :(得分:0)

首先,您可以使用以下方式创建time_axis_ns数组:

time_axis_ns = np.arange(number_of_points_for_fft)*delta_time_ns

然后,而不是迭代sfcube中的索引:

sflist[sfcube]

应该给出相同的结果。然后根据此结果进行np.exp(t_range*