¿Cómo puedo vectorizar los cálculos para un filtro recursivo de primer orden?

9

Tengo un filtro simple de paso bajo de un polo (para suavizado de parámetros) que puede explicarse mediante la siguiente fórmula:

y[n]=(1a)y[n1]+ax[n]

La arquitectura que estoy usando tiene acceso a instrucciones de una sola instrucción y múltiples datos (SIMD) que pueden realizar múltiples cálculos vectorizados en paralelo. Me gustaría aprovechar esta capacidad, pero no estoy seguro de cómo hacerlo para un filtro recursivo como este. El problema es que cada cálculo necesita un resultado previo.

usuario1132968
fuente
¿Podría alguien aclarar por qué esto se cerró como "fuera de tema"?
Paul R
La pregunta se superpone entre aquí y Stack Overflow. La pregunta original preguntaba específicamente cómo implementarla usando las extensiones ARM NEON. La pregunta vivirá en ambos sitios; se ha editado aquí para que sea más una discusión teórica sobre la estructuración del problema para aprovechar el paralelismo.
Jason R
@PaulR Solicité que se migrara aquí ayer, pero phonon sintió firmemente que pertenecía a SO, y no aquí. Lo admito, no sé sobre ARM NEON en particular, y probablemente tenga razón y respeto su juicio. Ver esta meta pregunta . Mi respuesta eliminada básicamente decía que estoy de acuerdo con Jason R y que los usuarios deberían marcar esas preguntas para la migración
Lorem Ipsum
1
Gracias a ambos por la aclaración: he estado haciendo todo lo posible en SO para migrar las preguntas relacionadas con DSP aquí para elevar nuestro perfil, por lo que me preocupaba si esto era lo correcto cuando esta pregunta se cerró. Me alegra ver que está abierto nuevamente ahora en una forma más general.
Paul R

Respuestas:

7

Suponiendo que realiza operaciones de vector de elementos a la vez, puede desenrollar la ecuación de diferencia por un factor de M con bastante facilidad para el filtro de un solo polo simple. Suponga que ya ha calculado todas las salidas hasta y [ n ] . Luego, puede calcular los siguientes de la siguiente manera: y [ n + 1 ]MMy[n]

y[n+1]=(1a)y[n]+ax[n+1]y[n+2]=(1a)y[n+1]+ax[n+2]=(1a)((1a)y[n]+ax[n+1])+ax[n+2]=(1a)2y[n]+a(1a)x[n+1]+ax[n+2]

En general, puede escribir como:y[n+k]

y[n+k]=(1a)ky[n]+i=1ka(1a)kix[n+i]

Para cada índice de muestra , esto se parece a un filtro FIR con k + 1 toques: un toque multiplica la última salida del filtro y [ n ] , y los otros k taps multiplican las entradas del filtro x [ n + 1 ] , ... , x [ n + k ] . Lo bueno es que los coeficientes utilizados para todos estos grifos se pueden calcular previamente, lo que le permite desenrollar el filtro recursivo en M M + 1n+kk+1y[n]kx[n+1],,x[n+k]M M+1-tap filtros paralelos no recursivos (estos filtros calculan las muestras de salida ), actualizando el término de retroalimentación cada M muestras de salida. Entonces, dada una condición inicial y [ n ] (que se supone que es la última salida calculada en la iteración vectorizada anterior), puede calcular las siguientes M salidas en paralelo.y[n+1],,y[n+M]My[n]M

Hay algunas advertencias a este enfoque:

  • Si hace grande, entonces terminas multiplicando un grupo de números para obtener los coeficientes FIR efectivos para los filtros desenrollados. Dependiendo de su formato de número y el valor de a , esto podría tener implicaciones de precisión numérica.Ma

  • My[n+k]kMk2MMMM+1M

    R=M+12M=12(1+1M)

    MM=4M=8y[n]y[n1]. Este efecto es obviamente muy dependiente de la plataforma.

Jason R
fuente
3

En general, solo puede vectorizar conjuntos de cálculos completamente independientes. Pero en su paso bajo IIR, cada salida depende de otra (excepto la primera), por lo que no es posible la vectorización.

Si su variable "a" es lo suficientemente grande como para que (1-a) ^ n decaiga rápidamente por debajo de su nivel de ruido deseado o error permitido, puede sustituir una aproximación corta del filtro FIR para su IIR, y en su lugar vectorizar esa convolución. Pero eso no es probable que sea más rápido.

hotpaw2
fuente
2

Realmente solo puede vectorizar esto de manera efectiva si tiene más de una señal a la que desea aplicar el mismo filtro, por ejemplo, si es una señal de audio estéreo, puede procesar los canales izquierdo y derecho en paralelo. Obviamente, cuatro u ocho canales en paralelo serían aún mejores.

Paul R
fuente
0

¿Qué tal expandir las ecuaciones a 4 pasos y usar la multiplicación de matrices? a es constante, por lo que una matriz puede calcularse previamente


fuente
0

Es más eficiente vectorizar el filtrado de varias corrientes independientes en paralelo.

Si solo tiene una secuencia larga, también puede dividir la secuencia en varias secciones superpuestas y filtrarlas como si fueran secuencias independientes.

Desea una superposición porque las primeras muestras de cada transmisión serán incorrectas. La cantidad de muestras que necesita descartar dependerá del valor de ay la precisión deseada. Deberá descartar aproximadamente n muestras donde (1 / a) (1-a) ** n <eps para que el resultado sea exacto a eps * max (| x [i] |).

Por ejemplo, si a = 0.1, entonces en 128 muestras el error causado por (1 / a) (1-a) ^ n sería menor que el LSB en un entero de 16 bits, mientras que para a = 0.9 solo necesitaría descartar Cerca de 6 muestras.

Peter de Rivaz
fuente