问题描述
我想通过scipy内置的低通滤波器发送一些数据。我正在用下面的一些数据数组进行测试。使用numpy时,它可以正常工作并输出过滤后的值。然后,我想看看是否可以使用GPU并加快速度,并听说有关CuPy的工作原理类似于numpy。但是,当我用cupy数组替换numpy数组时,出现以下错误ValueError: could not convert b,a,and x to a common type
from scipy.signal import butter,lfilter,freqz
import cupy as cp
import time
import numpy as np
def butter_lowpass(cutoff,fs,order=5):
nyq = 0.5 * fs
normal_cutoff = cutoff / nyq
b,a = butter(order,normal_cutoff,btype='low',analog=False)
return b,a
def butter_lowpass_filter(data,cutoff,order=5):
b,a = butter_lowpass(cutoff,order=order)
y = lfilter(b,data)
return y
order = 1
fs = 30.0
cutoff = 0.3
new_frame_np = np.ones(100)*3
new_frame_cp = cp.ones(100)*3
y = butter_lowpass_filter(new_frame_np,order) #WORKS
y = butter_lowpass_filter(new_frame_cp,order) #DOES NOT WORK
如何在上面的示例中使cupy数组正常工作?
Scipy似乎可以处理CPU任务,因此也许不能与GPU杯状阵列一起工作。我找不到能够为杯状阵列提供低通或带通滤波器的库。
解决方法
我是cuSignal的创建者。过去,我们花了一些时间尝试GPU加速SciPy的lfilter
,但是对于ARMA过滤器,lfilter使用DF-II形式,该形式具有数据依赖性,这使得并行化变得困难。有很多解决方法(例如,通过同时过滤的信号数量进行并行化),但最终我们将此称为“阻塞”。
也就是说,我们确实通过FFT方法具有FIR滤波器支持。这与fftconvolve
基本相同,但是在我们的夜间conda版本中(或者如果您使用branch-0.16从源代码构建),它被包裹为cusignal.firfilter
。
您可以执行以下操作:
>>> from scipy import signal
>>> import cupy as cp
>>> import cusignal
>>> [b,a] = signal.butter(3,0.5)
>>> b = cp.asarray(b)
>>> x = cp.random.randn(2**8)
>>> y = cusignal.firfilter(b,x)
请注意,我们目前不支持Butterworth滤波器设计,并且依赖scipy来生成系数,然后再将其移动到GPU mem(使用cupy.asarray
)。