Come posso vettorializzare i calcoli per un filtro ricorsivo di primo ordine?


9

Ho un semplice filtro passa basso unipolare (per il livellamento dei parametri) che può essere spiegato con la seguente formula:

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

L'architettura che sto usando ha accesso a istruzioni a singola istruzione, dati multipli (SIMD) che possono eseguire calcoli vettoriali multipli in parallelo. Vorrei sfruttare questa funzionalità, ma non sono sicuro di come farlo per un filtro ricorsivo come questo. Il problema è che ogni calcolo ha bisogno di un risultato precedente.


Qualcuno potrebbe chiarire perché questo è stato chiuso come "off topic"?
Paul R,

La domanda si sovrappone tra qui e StackTranslate.it. La domanda originale chiedeva specificamente come implementarla usando le estensioni ARM NEON. La domanda vivrà su entrambi i siti; è stato modificato qui per rendere più di una discussione teorica sulla strutturazione del problema per trarre vantaggio dal parallelismo.
Jason R,

@PaulR Ho chiesto che fosse migrato qui ieri, ma Phonon sentiva fortemente che apparteneva a SO, e non qui. Devo ammettere che non conosco ARM NEON in particolare, e probabilmente ha ragione e rispetto il suo giudizio. Vedi questa meta domanda . La mia risposta eliminata in sostanza diceva che sono d'accordo con Jason R e che gli utenti dovrebbero contrassegnare tali domande per la migrazione
Lorem Ipsum,

1
Grazie sia per il chiarimento - Ho fatto del mio meglio su SO per far migrare qui le domande relative al DSP al fine di aumentare il nostro profilo, quindi ero preoccupato se questa fosse la cosa giusta da fare quando questa domanda veniva chiusa - felice di vedere che ora è di nuovo aperto in una forma più generale.
Paul R,

Risposte:


7

Supponendo che si eseguano operazioni vettoriali M elementi alla volta, puoi srotolare l'equazione della differenza di un fattore di Mabbastanza facilmente per il semplice filtro unipolare. Supponiamo di aver già calcolato tutti gli output fino ay[n]. Quindi, è possibile calcolare quelli successivi come segue:

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]

In generale, puoi scrivere y[n+k] come:

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

Per ogni indice di esempio n+k, questo sembra un filtro FIR con k+1 tocchi: un tocco moltiplica l'ultimo output del filtro y[n], e l'altro k i tocchi moltiplicano gli ingressi del filtro x[n+1],,x[n+k]. La cosa bella è che i coefficienti utilizzati per tutti questi tocchi possono essere precalcolati, permettendoti di srotolare il filtro ricorsivo inM M+1-tap filtri paralleli non ricorsivi (questi filtri calcolano i campioni di output y[n+1],,y[n+M]), aggiornando il termine di feedback ogni Mcampioni di output. Quindi, data una condizione inizialey[n] (che si presume sia l'ultimo output calcolato sulla precedente iterazione vettoriale), è possibile calcolare il successivo M uscite in parallelo.

Ci sono alcuni avvertimenti su questo approccio:

  • Se Mdiventa grande, quindi si moltiplica un gruppo di numeri per ottenere i coefficienti FIR effettivi per i filtri non srotolati. A seconda del formato del numero e del valore dia, questo potrebbe avere implicazioni di precisione numerica.

  • Inoltre, non ottieni M-upold speedup con questo approccio: finisci per calcolare y[n+k] con ciò che equivale a k-tap filtro FIR. Anche se stai calcolandoM uscite in parallelo, il fatto che devi fare kle operazioni di moltiplicazione (MAC) anziché la semplice implementazione ricorsiva del primo ordine diminuiscono alcuni dei vantaggi della vettorializzazione. L'approccio non vettoriale utilizza 2 MAC per output, quindi è necessario2M operazioni da calcolare Muscite. Lo schema vettorializzato calcola il fileM output in una sola volta, richiedendo M+1MAC nel processo. Pertanto, la riduzione delle operazioni può essere espressa in funzione diM come:

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

    Quindi, anche con Mmolto grande, puoi ottenere una riduzione massima del 50% nella quantità di calcoli usando questo metodo. Per i valori comuni diM=4 e M=8, la riduzione è rispettivamente del 37,5% e del 43,75%. Tuttavia, oltre alla pura riduzione del numero di operazioni, è possibile ottenere ulteriori vantaggi in termini di prestazioni a causa del diverso modello di accesso alla memoria impiegato dall'approccio non srotolato; per un'implementazione più semplice, è possibile che si verifichino ritardi dovuti alla dipendenza di ciascun campione di outputy[n] sul campione precedente y[n1]. Questo effetto è ovviamente molto dipendente dalla piattaforma.


3

In generale, è possibile vettorializzare solo set di calcoli completamente indipendenti. Ma nel tuo passa basso IIR, ogni uscita dipende da un'altra (tranne la prima), quindi la vettorializzazione non è possibile.

Se la tua variabile "a" è abbastanza grande da far sì che (1-a) ^ n decada rapidamente al di sotto del rumore di fondo desiderato o dell'errore consentito, puoi sostituire una breve approssimazione del filtro FIR per il tuo IIR e vettorializzare invece quella convoluzione. Ma non è probabile che sia più veloce.


2

Puoi realmente vettorizzare questo in modo efficace solo se hai più di un segnale a cui desideri applicare lo stesso filtro, ad esempio se si tratta di un segnale audio stereo, puoi elaborare il canale sinistro e destro in parallelo. Quattro o otto canali in parallelo sarebbero ovviamente ancora migliori.


0

Che ne dici di espandere le equazioni a 4 passaggi e utilizzare la moltiplicazione della matrice? a è costante, quindi una matrice può essere precalcolata


0

È più efficiente vettorializzare in parallelo il filtro di più flussi indipendenti.

Se hai solo un singolo flusso lungo, puoi anche dividere il flusso in diverse sezioni sovrapposte e filtrarle come se fossero flussi indipendenti.

Si desidera una sovrapposizione perché i primi pochi campioni di ciascun flusso non saranno corretti. La quantità di campioni che è necessario scartare dipenderà dal valore di a e dalla precisione desiderata. Dovrai scartare circa n campioni in cui (1 / a) (1-a) ** n <eps in modo che il risultato sia accurato su eps * max (| x [i] |).

Ad esempio, se a = 0,1, quindi in 128 campioni l'errore causato da (1 / a) (1-a) ^ n sarebbe inferiore all'LSB in un numero intero a 16 bit, mentre per a = 0.9 dovrai solo scartare circa 6 campioni.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.