通过Scipy低通滤波器传递CuPy阵列

问题描述

我想通过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)。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...