Профилирование некоторой вычислительной работы, которую я выполняю, показало, что одним узким местом в моей программе была функция, которая в основном выполняла это (np
- numpy
, sp
- scipy
):
def mix1(signal1, signal2):
spec1 = np.fft.fft(signal1, axis=1)
spec2 = np.fft.fft(signal2, axis=1)
return np.fft.ifft(spec1*spec2, axis=1)
Оба сигнала имеют форму (C, N)
, где C
- это количество наборов данных (обычно менее 20), а N
- это количество выборок в каждом наборе (около 5000). Вычисления для каждого набора (строки) полностью независимы от любого другого набора.
Я подумал, что это просто простая свертка, поэтому я попытался заменить его на:
def mix2(signal1, signal2):
outputs = np.empty_like(signal1)
for idx, row in enumerate(outputs):
outputs[idx] = sp.signal.convolve(signal1[idx], signal2[idx], mode='same')
return outputs
... просто чтобы увидеть, получил ли я такие же результаты. Но я не сделал, и мои вопросы:
- Почему бы и нет?
- Есть ли лучший способ вычислить эквивалент
mix1()
?
(я понимаю, что mix2
, вероятно, не был бы быстрее как есть, но это могло бы быть хорошей отправной точкой для распараллеливания.)
Вот полный сценарий, который я использовал, чтобы быстро проверить это:
import numpy as np
import scipy as sp
import scipy.signal
N = 4680
C = 6
def mix1(signal1, signal2):
spec1 = np.fft.fft(signal1, axis=1)
spec2 = np.fft.fft(signal2, axis=1)
return np.fft.ifft(spec1*spec2, axis=1)
def mix2(signal1, signal2):
outputs = np.empty_like(signal1)
for idx, row in enumerate(outputs):
outputs[idx] = sp.signal.convolve(signal1[idx], signal2[idx], mode='same')
return outputs
def test(num, chans):
sig1 = np.random.randn(chans, num)
sig2 = np.random.randn(chans, num)
res1 = mix1(sig1, sig2)
res2 = mix2(sig1, sig2)
np.testing.assert_almost_equal(res1, res2)
if __name__ == "__main__":
np.random.seed(0x1234ABCD)
test(N, C)