Como posso vetorizar os cálculos para um filtro recursivo de primeira ordem?

9

Eu tenho um filtro simples de passa-baixo simples (para suavização de parâmetros) que pode ser explicado pela seguinte fórmula:

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

A arquitetura que estou usando tem acesso a instruções de instrução única e dados múltiplos (SIMD) que podem executar vários cálculos vetorizados em paralelo. Gostaria de aproveitar esse recurso, mas não tenho certeza de como fazer isso para um filtro recursivo como esse. O problema é que todo cálculo precisa de um resultado anterior.

user1132968
fonte
Alguém poderia esclarecer por que isso foi fechado como "fora de tópico"?
Paul R
A pergunta se sobrepõe aqui e Stack Overflow. A pergunta original perguntou especificamente como implementá-lo usando extensões ARM NEON. A questão ficará nos dois sites; foi editado aqui para torná-lo mais uma discussão teórica sobre a estruturação do problema para tirar vantagem do paralelismo.
Jason R
@PaulR Solicitei que fosse migrado para cá ontem, mas o phonon sentiu fortemente que pertencia ao SO, e não aqui. Admito que não conheço o ARM NEON em particular, e ele provavelmente está certo e eu respeito o seu julgamento. Veja esta meta questão . A minha resposta excluída basicamente disse que estou de acordo com Jason R e que os usuários devem flag tais questões para a migração
Lorem Ipsum
11
Obrigado pelo esclarecimento - tenho feito o possível para migrar aqui as questões relacionadas ao DSP para melhorar nosso perfil. Por isso, fiquei preocupado em saber se isso era a coisa certa a ser feita quando a pergunta foi encerrada - feliz em vê-lo aberto novamente agora de uma forma mais geral.
Paul R

Respostas:

7

Supondo que você execute operações vetoriais elementos de cada vez, é possível desenrolar a equação da diferença por um fator bastante facilidade para o filtro simples de um pólo. Suponha que você já calculou todas as saídas até . Em seguida, você pode calcular os seguintes: M y [ n ] 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]

Em geral, você pode escrever como:y[n+k]

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

Para cada índice de amostra , isso se parece com um filtro FIR com toques: um toque multiplica a última saída de filtro e os outros toques multiplicam as entradas de filtro . O bom é que os coeficientes utilizados para todas estas torneiras pode ser pré-calculada, o que lhe permite desenrolar o filtro recursivo em -Toque paralelo filtros não recursivos (estes filtros calcular as amostras de saída ), atualizando o termo de feedback a cada amostras de saída. Então, dada uma condição inicialn+kk+1y[n]kx[n+1],,x[n+k]M M+1y[n+1],,y[n+M]My[n](que é considerado a última saída calculada na iteração vetorial anterior), é possível calcular as próximas saídas em paralelo.M

Existem algumas ressalvas nessa abordagem:

  • Se se tornar grande, você acaba multiplicando vários números para obter os coeficientes FIR efetivos para os filtros desenrolados. Dependendo do seu formato numérico e do valor de , isso pode ter implicações numéricas de precisão.Ma

  • Além disso, você não obtém uma aceleração fold com essa abordagem: acaba calculando com o que equivale a um filtro FIR tap. Embora você esteja calculando saídas em paralelo, o fato de você ter que executar operações multiply-acumulate (MAC) em vez da implementação recursiva simples de primeira ordem diminui alguns dos benefícios da vetorização. A abordagem não vetorizada usa 2 MACs por saída, portanto, você precisa de operações de para calcular saídas. O esquema vetorizado calcula as saídas uma só vez, exigindo MACs no processo. Portanto, a redução nas operações pode ser expressa em função daMy[n+k]kMk2MMMM+1M

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

    MM=4M=8y[n]y[n1]. Esse efeito é obviamente muito dependente da plataforma.

Jason R
fonte
3

Em geral, você só pode vetorizar conjuntos de cálculos completamente independentes. Mas no seu passe baixo IIR, toda saída depende de outra (exceto a 1ª), portanto, a vetorização não é possível.

Se sua variável "a" for grande o suficiente para que (1-a) ^ n decaia rapidamente abaixo do nível de ruído desejado ou erro permitido, você poderá substituir uma aproximação curta do filtro FIR pelo seu IIR e, em vez disso, vetorizar essa convolução. Mas não é provável que seja mais rápido.

hotpaw2
fonte
2

Você realmente pode vetorizar isso efetivamente se tiver mais de um sinal ao qual deseja aplicar o mesmo filtro, por exemplo, se for um sinal de áudio estéreo, poderá processar os canais esquerdo e direito em paralelo. Quatro ou oito canais em paralelo obviamente seriam ainda melhores.

Paul R
fonte
0

Que tal expandir equações para 4 etapas e usar a multiplicação de matrizes? a é constante, então uma matriz pode ser pré-calculada


fonte
0

É mais eficiente vetorizar a filtragem de vários fluxos independentes em paralelo.

Se você tiver apenas um único fluxo longo, poderá dividi-lo em várias seções sobrepostas e filtrá-las como se fossem fluxos independentes.

Você deseja uma sobreposição porque as primeiras amostras de cada fluxo estarão incorretas. A quantidade de amostras que você precisa descartar dependerá do valor de a e da precisão desejada. Você desejará descartar cerca de n amostras em que (1 / a) (1-a) ** n <eps para que o resultado seja preciso para eps * max (| x [i] |).

Por exemplo, se a = 0,1, em 128 amostras o erro causado por (1 / a) (1-a) ^ n seria menor que o LSB em um número inteiro de 16 bits, enquanto que para a = 0,9 você precisaria apenas descartar cerca de 6 amostras.

Peter de Rivaz
fonte