Przerzucanie odpowiedzi impulsowej podczas splotu

26

Dlaczego podczas splotu na sygnale musimy odwracać odpowiedź impulsową podczas procesu?

Winuall
źródło
5
Druga połowa tej odpowiedzi może pomóc Ci zrozumieć.
Dilip Sarwate
3
Oprócz przeczytania świetnej odpowiedzi @ DilipSarwate dobrym ćwiczeniem jest wzięcie kartki papieru i obliczenie graficznej wydajności systemu LTI poprzez dodanie przesuniętej w czasie i skalowanej wersji odpowiedzi impulsowej.
Deve
1
Zauważ, że możesz przerzucić dowolny argument - wynik jest taki sam.
wakjah

Odpowiedzi:

29

Na podstawie odpowiedzi na inne pytanie (jak wspomniano w komentarzu) w nadziei, że to pytanie nie będzie wielokrotnie zadawane przez Wiki Wiki jako jedno z najważniejszych pytań ...

Nie ma „odwracania” odpowiedzi impulsowej przez układ liniowy (niezmienny w czasie). Dane wyjściowe liniowego systemu niezmiennego w czasie to suma skalowanych i opóźnionych w czasie wersji odpowiedzi impulsowej, a nie „impulsowej” odpowiedzi impulsowej.

Rozkładamy sygnał wejściowy na sumę skalowanych sygnałów impulsu jednostkowego. Odpowiedź systemu na jednostkowy sygnał impulsowy to odpowiedź impulsowa lub odpowiedź impulsowa i tak według właściwości skalowania pojedyncza wartość wejściowa lub, jeśli wolisz tworzy odpowiedź , 0 , 0 , 1 , 0 , 0 , h [ 0 ] , h [ 1 ] , , h [ n ] , x [ 0 ] x [ 0 ] ( , 0 , 0 , 1 , 0 , 0 , ) = 0 , 0 ,x, 0, 0, 1, 0, 0,

h[0], h[1],, h[n],
x[0]
x[0](, 0, 0, 1, 0, 0,)= 0, 0, x[0], 0, 0,
x[0]h[0],  x[0]h[1],,  x[0]h[n],

Podobnie, pojedyncza wartość wejściowa lub tworzy tworzy odpowiedź Zauważ opóźnienie w odpowiedzi na . Możemy kontynuować w tym duchu, ale najlepiej jest przejść do bardziej tabelarycznej formy i pokazać różne wyniki odpowiednio dopasowane w czasie. Mamy x[1]

x[1](, 0, 0, 0, 1, 0,)= 0, 0, 0, x[1], 0,
0,x[1]h[0],  x[1]h[1],,  x[1]h[n1],x[1]h[n]
x[1]
time012nn+1x[0]x[0]h[0]x[0]h[1]x[0]h[2]x[0]h[n]x[0]h[n+1]x[1]0x[1]h[0]x[1]h[1]x[1]h[n1]x[1]h[n]x[2]00x[2]h[0]x[2]h[n2]x[2]h[n1]x[m]000x[m]h[nm]x[m]h[nm+1]
\ ddots \ end {array} Wiersze w powyższej tablicy są dokładnie skalowanymi i opóźnionymi wersjami odpowiedzi impulsowej, które sumują się do odpowiedzi na sygnał wejściowy . yx Ale jeśli zadasz bardziej szczegółowe pytanie, takie jak

Jaka jest wydajność w czasie ?n

możesz uzyskać odpowiedź, sumując kolumnę, aby uzyskać ukochaną formułę splotu, która wprawia w osłupienie pokolenia studentów, ponieważ reakcja impulsowa wydaje się być „odwrócona” lub cofnięta w czasie. Ale ludzie wydają się zapominać o tym, że zamiast tego moglibyśmy napisać więc to wejście wydaje się „przewrócone” lub biegnie wstecz w czasie! Innymi słowy, są to ludzien

y[n]=x[0]h[n]+x[1]h[n1]+x[2]h[n2]++x[m]h[nm]+=m=0x[m]h[nm],
y[n]=x[n]h[0]+x[n1]h[1]+x[n2]h[2]++x[0]h[n]+=m=0x[nm]h[m],
którzy odwracają odpowiedź impulsową (lub dane wejściowe) podczas obliczania odpowiedzi w czasie przy użyciu wzoru splotu, ale sam system nic takiego nie robi.n
Dilip Sarwate
źródło
4

Oto przykład C / C ++, który pokazuje, że splot można wykonać bez użycia odpowiedzi impulsowej w odwrotnej kolejności. Jeśli sprawdzisz convolve_scatter()funkcję, żadna zmienna nie zostanie nigdzie zanegowana. Jest to splot rozpraszający, w którym każda próbka wejściowa jest rozproszona (zsumowana) do wielu próbek wyjściowych w pamięci, przy użyciu wag podanych w odpowiedzi impulsowej. Jest to marnotrawstwo, ponieważ próbki wyjściowe będą musiały zostać kilkakrotnie odczytane i zapisane.

Zwykle splot odbywa się jako gromadzenie splotu, jak w convolve_gather(). W tej metodzie każda próbka wyjściowa jest tworzona osobno, poprzez zebranie (zsumowanie) próbek wejściowych, z odwróconą odpowiedzią impulsową jako odważnikami. Próbka wyjściowa znajduje się w rejestrze procesora używanym jako akumulator podczas tego procesu. Jest to zwykle metoda z wyboru, ponieważ na każdą filtrowaną próbkę przypada tylko jeden zapis pamięci. Teraz jest więcej odczytów pamięci na wejściu, ale tylko tyle, ile było odczytów pamięci na wyjściu w metodzie rozpraszania.

#include <stdio.h>

const int Nx = 5; 
const int x[Nx] = {1, 0, 0, 0, 2};
const int Ny = 3; 
const int y[Ny] = {1, 2, 3};
const int Nz = Nx+Ny-1;
int z[Nz];

void convolve_scatter() { // z = x conv y
  for (int k = 0; k < Nz; k++) {
    z[k] = 0;
  }
  for (int n = 0; n < Nx; n++) {
    for (int m = 0; m < Ny; m++) {
      z[n+m] += x[n]*y[m]; // No IR reversal
    }
  }
}

void convolve_gather() { // z = x conv y
  for (int k = 0; k < Nz; k++) {
    int accu = 0;
    for (int m = 0; m < Ny; m++) {
      int n = k+m - Ny + 1;
      if (n >= 0 && n < Nx) {
        accu += x[n]*y[Ny-m-1]; // IR reversed here
      }
    }
    z[k] = accu;
  }
}

void print() {
  for (int k = 0; k < Nz; k++) {
    printf("%d ", z[k]);
  }
  printf("\n");
}

int main() {
  convolve_scatter();
  print();
  convolve_gather();
  print();
}

Splot sekwencji:

1 0 0 0 2
1 2 3

i używając obu metod splotu wyjścia:

1 2 3 0 2 4 6

Nie mogę sobie wyobrazić nikogo używającego metody rozpraszania, chyba że filtr zmienia się w czasie, w którym to przypadku dwie metody przyniosą różne wyniki, a jedna może być bardziej odpowiednia.

Olli Niemitalo
źródło
Ciekawy! Jaki jest więc końcowy wniosek, który chciałbym zobaczyć
Failed Scientist
Twoja troska o architekturę jest interesująca. Biorąc pod uwagę dostępne pamięci podręczne, instrukcje SIMD (SSE, AVX) i architektury wielordzeniowe, metoda rozproszona wydaje się bardziej odpowiednia do obliczeń równoległych? Ale nie przeprowadziłem szczegółowej analizy ...
Fat32
@ Fat32 mnie też! Masz na myśli akumulację w gromadzeniu splotu, która może stać się wąskim gardłem z wieloma rdzeniami pracującymi na multiplikacjach? Można to złagodzić, dając każdemu rdzeniu własny akumulator i sumując je na końcu. Myślę, że ten narzut nie byłby wiele w porównaniu z dodatkowymi zapisami pamięci w rozproszonym splocie.
Olli Niemitalo
Właściwie bardziej martwiłem się wydajnością formy rozproszonej niż wąskim gardłem formularzy zbierających. Moje obecne kody filtrujące C znajdują się (najprawdopodobniej) w formularzu zbierającym, ale jeśli chodzi o kody ASM, zwykle piszę je w rozszerzeniach SIMD SSE, które są bardziej nadaje się do postaci rozproszonej. Muszę jednak zaktualizować moje tets :-))) Pamięć IO jest zdecydowanie problemem w porównaniu do akumulacji rejestrów. I prawdopodobnie brakuje mi kary powtarzającego się IO ...
Fat32
Czy ktoś zna lepsze słowa niż rozpraszanie i gromadzenie? Nie jestem pewien, czy są one zarezerwowane dla rzadkich jąder splotu.
Olli Niemitalo
3

Jest tylko „odwracany” do obliczeń punktowych.

@Dipip wyjaśnia, co reprezentuje całka / sumowanie splotowe, ale aby wyjaśnić, dlaczego jedna z dwóch funkcji wejściowych (często h(t)) jest odwracana do celów obliczeniowych, rozważ system dyskretny z x[n]reakcją wejściową i impulsową h[n]:

  • Możesz wziąć swoją funkcję wejściową x[n]i dla każdej niezerowej * próbki x[n]obliczyć skalowaną odpowiedź impulsową z próbki ni dalej, dopóki przesunięcie czasowe nie h[n]spadnie do zera (zakładając przyczynę h[n]). Oznaczałoby to brak „odwracania” (a ściślej „odwrócenia czasu”) jednego x[n]lub drugiego h[n]. Jednak na końcu musiałbyś dodać / nałożyć wszystkie te przeskalowane + przesunięte „echa” odpowiedzi impulsowej dla każdego niezerowego x[n].

  • Lub , dla wygody, możesz odwrócić w czasie jedną z funkcji dotyczących początku czasu (zwykle 0), dzięki czemu Twoje obliczenia {pomnóż, dodaj, pomnóż, dodaj, ...} zamiast {pomnóż, pomnóż, ..., dodaj , Dodaj, ...}. Daje to ten sam sygnał wyjściowy, ponieważ wykona dokładnie taką samą operację mnożenia i dodawania. Na przykład pomyśl o wkładzie wyjściowym niezerowego sygnału wejściowego w czasie 0 x[0]. Gdy k= 0 dla równania odpowiedź impulsowa zostanie odwrócona w czasie, ale nie przesunięta, dając nam pierwszą próbkę odpowiedzi, dla której jest . Następnie zwiększenie o jeden spowoduje przesunięcie w prawo o jeden krok czasowy, tak że czas zostanie odwrócony

    k=x[k]h[nk]
    h[n]x[n]x[0]h[0]kh[n]h[n]Drugi wpis ( h[1]) będzie teraz leżał na wierzchu x[0]i czeka na pomnożenie. To da pożądany wkład x[0]h[1]w czasie n=1, tak jak zrobiłby to poprzedni sposób.

* Mówię niezerowe, x[n]ponieważ odpowiedź impulsowa jest skalowana do zera, nie przyczyniając się w ten sposób do ostatecznego wyniku .

x[n]=0
h[n]y[n]
ABC
źródło
„Możesz wziąć swoją funkcję wejściową x [n] i dla każdej niezerowej * próbki x [n] obliczyć skalowaną odpowiedź impulsową z próbki n i dalej, aż przesunięta w czasie h [n] spadnie do zera (zakładając, że przyczynowy h [n]) "Czy pięć występujących w tym zdaniu ma taką samą liczbę, czy różnią się? n
Dilip Sarwate
@Dilip. Wszystkie n są takie same, z wyjątkiem „przesuniętego w czasie h [n]”, co oznacza „h [nk]”, gdzie „k” jest stałą używaną do przesunięcia odpowiedzi impulsowej do pożądanego punktu sygnału x [n ]. tj .: h [n-2] do obliczenia odpowiedzi na sygnał przy x [2].
abc
3

Przy indeksie c [n] splot a [n] ib [n] jest taki, że:

„c [n] jest sumą wszystkich produktów (a [k] b [m]) takich, że m + k = n,” więc m = n - k lub k = n - m, co oznacza, że ​​jedna z sekwencji musi zostać odwrócony.

Dlaczego więc przede wszystkim tak zachowuje się splot? Ze względu na jego związek z mnożeniem wielomianów.

Pomnożenie dwóch wielomianów powoduje powstanie nowego wielomianu ze współczynnikami efektywności. Współczynniki wielomianu produktu określają działanie splotu. Teraz, w przetwarzaniu sygnałów, funkcje przesyłania - transformaty Laplace'a lub transformaty Z są wielomianami, przy czym każdy współczynnik wydajności odpowiada innemu opóźnieniu czasowemu. Dopasowanie współczynników produktu i mnożników powoduje, że „zwielokrotnienie w jednej reprezentacji odpowiada splotowi w transformowanej reprezentacji”.

wprowadź opis zdjęcia tutaj

Mahesh Shastry
źródło
0

Podczas splotu wcale nie musi wystąpić żadne „odwrócenie” odpowiedzi impulsowej ...

Jeśli jednak chcesz zapobiec jakiejkolwiek zmianie fazy, możesz zwołać sygnał z odpowiedzią impulsową, a następnie odwrócić odpowiedź impulsową i ponownie zwoić, aby anulować efekty fazowe.

W przetwarzaniu offline równie łatwo można odwrócić sygnał po pierwszym spięciu, aby dojść do tego samego wniosku (jak sugerują komentarze).

learnvst
źródło
3
Odnosi się on do „odwrócenia czasu” odpowiedzi impulsowej w całce splotowej: . Jak ktoś już zauważył, nie musisz odwracać odpowiedzi impulsowej ; możesz przerzucić dowolny termin (tj. ). Myślę, że próbuje dowiedzieć się, jaka jest jakościowa interpretacja tej akcji typu „flip-and-slide”. y(t)=x(τ)h(tτ)dτh(t)x(t)h(t)=h(t)x(t)
Jason R
@JasonR Ah, ups! Czasami trudno zrozumieć, o co chodzi w pytaniu. Izhak, kiedy zrozumiesz odpowiedź, której szukałeś, zrozumiesz, dokąd idę. Zignoruj ​​mnie na razie!
learnvst
0

Po prostu napisz całkę konwolucji zamiast falowania ręcznego mianowicie całkowanie iloczynu i we wszystkich parach argumentów sumujących się do .

f(τ)g(tτ)dτ
t1+t2=tf(t1)g(t2)dt1dt2
fgt

Teraz forma falowania dłoni wyraźnie pokazuje symetrię tutaj zaangażowaną i że nie ma tu miejsca żadne „odwracanie”. Przekształcenie go w odpowiednią całkę jednowymiarową wymaga jednak uczynienia jednego z dwóch argumentów rzeczywistą zmienną całkującą. Jest to albo znalezienie sztywnej symetrycznej formy, która nie wymaga falowania ręcznego. Ten ostatni jest trudniejszy. Zasadniczo musisz odzyskać normalizację, tworząc coś (przy użyciu funkcji / dystrybucji delty Diraca), na przykład Jeśli następnie zmienisz układ w jeden sposób, otrzymasz oraz z właściwości przesiewania operatora Dirac t 1 f ( t 1 )

t1,t2f(t1)g(t2)δ(tt1t2)dt1dt2
t 1 f ( t 1 )
t1f(t1)dt1t2g(t2)δ(tt1t2)dt2
t1f(t1)dt1g(tt1)
który jest oryginalną całką z odrobiną zmiany nazwy.

źródło