Tôi nghĩ rằng bạn đã tìm thấy source code của hàm fftconvolve
. Thông thường, đối với đầu vào thực, nó sử dụng các hàm numpy.fft.rfftn
và .irfftn
, tính toán các phép biến đổi N-chiều. Vì mục đích là để làm biến đổi nhiều 1-D, về cơ bản bạn có thể viết lại fftconvolve
như thế này (giản thể):
from scipy.signal.signaltools import _next_regular
def fftconvolve_1d(in1, in2):
outlen = in1.shape[-1] + in2.shape[-1] - 1
n = _next_regular(outlen)
tr1 = np.fft.rfft(in1, n)
tr2 = np.fft.rfft(in2, n)
out = np.fft.irfft(tr1 * tr2, n)
return out[..., :outlen].copy()
Và tính toán kết quả mong muốn:
result = fftconvolve_1d(data, Gauss)
này hoạt động vì numpy.fft.rfft
và .irfft
(chú ý việc thiếu n
trong tên) biến đổi trên một trục của mảng đầu vào (trục cuối cùng theo mặc định). Đây là khoảng 40% nhanh hơn so với mã OP trên hệ thống của tôi.
Tăng tốc thêm có thể đạt được bằng cách sử dụng một back-end FFT khác.
Đối với một, các chức năng trong scipy.fftpack
có vẻ hơi nhanh hơn tương đương Numpy của chúng. Tuy nhiên, định dạng đầu ra của các biến thể Scipy là khá khó xử (xem docs) và điều này làm cho nó khó khăn để làm phép nhân.
Một chương trình phụ trợ khác có thể là FFTW thông qua trình bao bọc pyFFTW. Nhược điểm là biến đổi được bắt đầu bằng một "giai đoạn lập kế hoạch" chậm và các đầu vào phải được căn chỉnh 16 byte để đạt được hiệu suất tốt nhất. Điều này được giải thích khá rõ trong pyFFTW tutorial. Mã kết quả có thể là ví dụ:
from scipy.signal.signaltools import _next_regular
import pyfftw
pyfftw.interfaces.cache.enable() # Cache for the "planning"
pyfftw.interfaces.cache.set_keepalive_time(1.0)
def fftwconvolve_1d(in1, in2):
outlen = in1.shape[-1] + in2.shape[-1] - 1
n = _next_regular(outlen)
tr1 = pyfftw.interfaces.numpy_fft.rfft(in1, n)
tr2 = pyfftw.interfaces.numpy_fft.rfft(in2, n)
sh = np.broadcast(tr1, tr2).shape
dt = np.common_type(tr1, tr2)
pr = pyfftw.n_byte_align_empty(sh, 16, dt)
np.multiply(tr1, tr2, out=pr)
out = pyfftw.interfaces.numpy_fft.irfft(pr, n)
return out[..., :outlen].copy()
Với đầu vào liên kết và "lập kế hoạch" được lưu trong bộ nhớ cache, tôi thấy tốc độ gần gấp 3 lần so với mã trong OP.Liên kết bộ nhớ can be easily checked bằng cách xem địa chỉ bộ nhớ trong thuộc tính ctypes.data
của mảng Numpy.
'Gauss' là gì? Một số loại hạt nhân 1-D gaussian? Nếu vậy, kích thước nào tương ứng với 'z_depth'? –
Nhân tạo Gaussian được tạo ra một lần, trước vòng lặp. Dữ liệu là vector 1d (z_depth) thường dài khoảng 1535 phần tử, với hạt nhân 1D gaussian có chiều dài thường là 79. Tôi đã dọn sạch một lượng chi phí trong fftconvolve, về cơ bản chỉ cần chuyển trực tiếp đến irfftn (rfftn (in1, fshape) * rfftn (in2, fshape), fshape) [fslice] .copy() – user4547612