Fin*_*ood 26 python signal-processing numpy scipy
在同一个numpy数组中,计算np.cos需要3.2秒,而在Linux Mint上np.sin运行548秒(9分钟).
有关完整代码,请参阅此repo.
我有一个脉冲信号(见下图)我需要调制到HF载波上,模拟激光多普勒振动计.因此,需要对信号及其时间基础进行重新采样,以匹配载波的较高采样率.

在随后的解调过程中,需要同相载波cos(omega * t)和相移载波sin(omega * t).奇怪的是,评估这些功能的时间在很大程度上取决于计算时间向量的方式.
t1使用np.linspace直接计算时间向量,t2使用实现scipy.signal.resample的方法.
pulse = np.load('data/pulse.npy') # 768 samples
pulse_samples = len(pulse)
pulse_samplerate = 960 # 960 Hz
pulse_duration = pulse_samples / pulse_samplerate # here: 0.8 s
pulse_time = np.linspace(0, pulse_duration, pulse_samples,
endpoint=False)
carrier_freq = 40e6 # 40 MHz
carrier_samplerate = 100e6 # 100 MHz
carrier_samples = pulse_duration * carrier_samplerate # 80 million
t1 = np.linspace(0, pulse_duration, carrier_samples)
# method used in scipy.signal.resample
# https://github.com/scipy/scipy/blob/v0.17.0/scipy/signal/signaltools.py#L1754
t2 = np.arange(0, carrier_samples) * (pulse_time[1] - pulse_time[0]) \
* pulse_samples / float(carrier_samples) + pulse_time[0]
Run Code Online (Sandbox Code Playgroud)
从下图中可以看出,时间向量并不相同.差距t1 - t2达到8000万个样本1e-8.
Run Code Online (Sandbox Code Playgroud)
我可以在我的32位笔记本电脑和我的64位塔上重现这个错误,两者都运行Linux Mint 17.然而,在我的平板伴侣的MacBook上,"慢速正弦"花费的时间与其他三个计算时间相同.
我在64位AMD处理器上运行Linux Mint 17.03,在32位Intel处理器上运行Linux Mint 17.2.
DSM*_*DSM 18
我不认为numpy与此有任何关系:我认为你正在绊倒系统中C数学库中的性能错误,这会影响接近pi的大倍数的sin.(我在这里广泛使用"bug" - 据我所知,由于大浮点数的正弦定义不明确,"bug"实际上是库正确处理极端情况的行为!)
在linux上,我得到:
>>> %timeit -n 10000 math.sin(6e7*math.pi)
10000 loops, best of 3: 191 µs per loop
>>> %timeit -n 10000 math.sin(6e7*math.pi+0.12)
10000 loops, best of 3: 428 ns per loop
Run Code Online (Sandbox Code Playgroud)
以及Python聊天室报告中使用的其他Linux类型
10000 loops, best of 3: 49.4 µs per loop
10000 loops, best of 3: 206 ns per loop
Run Code Online (Sandbox Code Playgroud)
和
In [3]: %timeit -n 10000 math.sin(6e7*math.pi)
10000 loops, best of 3: 116 µs per loop
In [4]: %timeit -n 10000 math.sin(6e7*math.pi+0.12)
10000 loops, best of 3: 428 ns per loop
Run Code Online (Sandbox Code Playgroud)
但Mac用户报道
In [3]: timeit -n 10000 math.sin(6e7*math.pi)
10000 loops, best of 3: 300 ns per loop
In [4]: %timeit -n 10000 math.sin(6e7*math.pi+0.12)
10000 loops, best of 3: 361 ns per loop
Run Code Online (Sandbox Code Playgroud)
没有数量级的差异.作为一种解决方法,您可以先尝试使用mod 2 pi:
>>> new = np.sin(omega_t2[-1000:] % (2*np.pi))
>>> old = np.sin(omega_t2[-1000:])
>>> abs(new - old).max()
7.83773902468434e-09
Run Code Online (Sandbox Code Playgroud)
哪个有更好的表现:
>>> %timeit -n 1000 new = np.sin(omega_t2[-1000:] % (2*np.pi))
1000 loops, best of 3: 63.8 µs per loop
>>> %timeit -n 1000 old = np.sin(omega_t2[-1000:])
1000 loops, best of 3: 6.82 ms per loop
Run Code Online (Sandbox Code Playgroud)
请注意,正如预期的那样,cos发生了类似的效果,只是移位:
>>> %timeit -n 1000 np.cos(6e7*np.pi + np.pi/2)
1000 loops, best of 3: 37.6 µs per loop
>>> %timeit -n 1000 np.cos(6e7*np.pi + np.pi/2 + 0.12)
1000 loops, best of 3: 2.46 µs per loop
Run Code Online (Sandbox Code Playgroud)