Cálculos de convolución en Numpy / Scipy

Perfilar algo de trabajo computacional que estoy haciendo me mostró que un cuello de botella en mi programa era una función que básicamente hacía esto np esnumpy, sp esscipy):

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)

mbas señales tienen forma(C, N) dóndeC es el número de conjuntos de datos (generalmente menos de 20) yN es el número de muestras en cada conjunto (alrededor de 5000). El cálculo para cada conjunto (fila) es completamente independiente de cualquier otro conjunto.

Pensé que esto era solo una convolución simple, así que traté de reemplazarlo con:

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

... solo para ver si obtuve los mismos resultados. Pero no lo hice, y mis preguntas son:

¿Por qué noHay una mejor manera de calcular el equivalente demix1()?

(Me doy cuenta de quemix2 probablemente no hubiera sido más rápido tal cual, pero podría haber sido un buen punto de partida para la paralelización).

Aquí está el script completo que utilicé para verificar esto rápidamente:

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)