2

我遇到了一些性能问题,希望能快速了解一下。

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

我现在这样做的方式是:

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是我程序中最慢的部分,有什么优化的想法吗?

4

5 回答 5

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 倍(取决于内核数量)。不过,如果这还不够好,您需要弄清楚如何使用向量/矩阵运算来做到这一点。

于 2013-06-25T10:11:13.127 回答
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 倍的加速,尽管您的结果会根据 和 的实际大小sflist而改变sfcube。你得到的是一个 3D numpy 数组,而不是数组列表的列表,尽管它们在大多数设置中是可以互换的,当然:

In [5]: np.allclose(compdata, compdata2)
Out[5]: True
于 2013-06-25T15:43:18.807 回答
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]

于 2013-06-25T10:09:07.040 回答
0

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

time_axis_ns = np.arange(number_of_points_for_fft)*delta_time_ns

然后,您不必遍历 sfcube 中的索引:

sflist[sfcube]

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

于 2013-06-25T10:12:18.913 回答
0

您可以使用 Python-psyco 库

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

或任何其他类似的图书馆

它可能会加快你的程序。

于 2013-06-25T09:54:27.703 回答