EÖTVÖS LORÁND TUDOMÁNYEGYETEM TERMÉSZETTUDOMÁNYI KAR Lengyel Richárd FFT algoritmus Szakdolgozat Matematika BSc Alkalmazott Matematikus Szakirány Témavezet : Schipp Ferenc Numerikus Analízis Tanszék Budapest, 2015
Köszönetnyilvánítás Köszönettel tartozom Schipp Ferenc professzornak, aki elvállalta a konzulensi feladatkört és az utolsó pillanatig is segítette munkámat. 1
Tartalomjegyzék 1. A Fourier-transzformáció 4 1.1. Fourier-sor.................................... 4 1.2. Fourier-transzformáció............................ 6 2. FFT 9 2.1. Jelölések, deníciók............................... 9 2.2. Az általános algoritmus............................ 13 2.3. Speciális esetek................................. 16 2.3.1. A Cooley Tukey algoritmus...................... 16 2.3.2. A Walsh-rendszerek........................... 20 3. Alkalmazások 22 3.1. Párhuzamosítás tesztelése........................... 22 3.2. Sz rés...................................... 24 3.3. Polinomok szorzása............................... 26 3.4. NIST....................................... 28 3.4.1. Az algoritmus.............................. 28 4. Forráskód 31 2
Bevezetés FFT (Fast Fourier Transform), azaz a gyors Fourier-transzformáció az egyik ismert legjelent sebb és legfontosabb algoritmus. Ezt az is alátámasztja, hogy 2000-ben az IEEE: Guest Editors Introduction to the top 10 algorithms publikációban megválasztották a 20. század egyik legnagyobb hatással rendelkez algoritmusának, olyan algoritmusok között mint a szimplex módszer vagy a quicksort algoritmus. Legalapvet bb felhasználása a digitális jelfeldolgozásban van (frekvencia spketrum analízis), hiszen egy jelet az id tartományból a frekvencia tartományba transzformál, azaz komplex sinusoidok kombinációjává alakít. Jelfeldogozásban sz rhetünk, konvolálhatunk vele. Ugyanakkor a legkülönfélébb helyeken is el fordul, egészen az orvostechnikai alkalmazásoktól, a közgazdasági területeken át a kriptográáig. Polinomokat szorozhatunk segítéségével, dierenciálegyenleteket oldhatunk meg vagy akár prímtesztet is végezhetünk. Ha pedig tekintjük az algoritmus egy általánosítását, még szélesebb körben válik alkalmazhatóvá mind az alkalmazott mind az elméleti matematikában. A dolgozatban ezt az általános algoritmust fogjuk különböz rendszereken vizsgálni. Konkrétan a trigonometrikus rendszeren és a Walsh rendszereken. Megnézzük még az algoritmus párhuzamosítását és ki is próbáljuk egy R7 m szériás grakus kártyán, az ATI-SDK implementációját használva. A Walsh rendszereken python implementációt fogunk tekinteni. A dolgozat harmadik fejezetében különböz alkalmazásokra nézünk példákat, azaz egy képfeldolgozást, véletlenszámgenerátorok tesztelését és polinomok szorzását. 3
1. fejezet A Fourier-transzformáció Mint a legtöbb matematikai fogalmat a Fourier-transzformációt is sokféleképp lehet bevezetni, el ször bemutatom a Fourier-sorokat majd ennek általánosításaként a Fouriertranszformációt. Végül pedig azt még általánosabban különböz terekre, rendszerekre is deniáljuk. Így ki fog derülni, hogy nemcsak a Fourier-sor, de a Fourier-együttható is, egy speciális esete a Fourier-transzformációnak. 1.1. Fourier-sor A Fourier-sor hasonlóan a Fourier-transzformációhoz az alkalmazott matematika egyik legfontosabb eszköze. Segítségével egy periódikus függvényt egyszer bb függvényekre (ortogonális sinus, cosinusok) rendszerére bonthatjuk és állíthatjuk azt vissza, így a függvény vizsgálatát jelent sen egyszser bbé téve. A deníciókban H egy tetsz leges Hiblert-teret, a.,. pedig annak egy skalárszorzatát jelöli. 1.1.1. Deníció (Ortonormált rendszer). Egy (e n ) H, (n N) vektorsorozatot ortonormáltnak hívünk ha e i, e j = δ ij Ahol δ ij a Kronecker-delta szimbólum, azaz: δ ij = 1 ha (i = j) és 0 egyébként. 1.1.2. Deníció (Teljes rendszer). Egy (e n ) H, (n N) vektorsorozat teljes rendszer, ha: x H: x, e n = 0 ( n N), akkor x = 0. 1.1.3. Deníció (Teljes ortonormált rendszer (TONR)). Egy (e n ) H, (n N) vektorsorozat teljes ortonormált rendszer, ha teljes és ortonormált. 4
1.1.4. Deníció (Fourier-sor, Fourier-együttható). Az x = x, e i e i szummát Fouriersornak, az (x H, (e n ) nevezzük. n N ) A x, e i skalárszorzatokat pedig Fourier-együtthatóknak Jogosan merülhet fel a kérdés hogy mikor is létezik ilyen el állítása egy függvények. A következ tétel erre ad választ. 1.1.1. Tétel (Fourier-sorok f tétele). H Hilbert-tér, (e n ) egy teljes ortonormált rendszer, ekkor: x = x, e i e i ( x H) i=1 1.1.1. Megjegyzés (speciális esetek). Az alkalmazásokban az egyik leggyakrabban használt rendszer a komplex sinus, cosinus rendszer, azaz: Legyen H = L 2 (0, 2π), a teljes ortonormált rendszer pedig: e n (x) = 1 2π e inx. Ekkor a Fourier-sorok f tétele szerint: Ugyanis: f(x) = 1 2π f(x) = Ahol c n a Fourier-együttható, azaz c n = f, e n = n=1 i=1 2π e inx f(t)e int dt n=1 2π 0 0 c n 1 2π e inx ( f H) fe n = 2π 0 1 f(t) e int dt 2π 1.1.2. Megjegyzés (nem periódikus a függvény). El z esetben 2π szerint periódikus függvényeket néztünk, persze ez tetsz leges periódussal is megtehet. Ha pedig nem periódikus az intervallum, azaz L 2 (R), akkor y R : e y (x) = 1 2π e iyx nem különböztethet k meg, ellenben az el z esettel. Ekkor lesz szükség a Fourier-transzformációra, azaz az n szerint futó szummát egy y szerinti integrál vált fel. Azaz: 1.1.5. Deníció (Fourier-transzformáció). 1 f(x) := f(y) e ixy dy, 2π R (x R, f L 1 (R) 5
1.2. Fourier-transzformáció A következ szakaszban még tovább terjesztjük ki a deníciót, ezzel megmutatva a kapcsolatot a Fourier-sor, Fourier-együttható és Fourier-transzformáció között mind diszkrét mind folytonos esetben. Így a transzformáció nem csak L 1 (R)-en, de sok más téren is használható lesz. Ehhez az alábbi fogalmak szükségesek. 1.2.1. Deníció (normált csoport). Legyen G egy kommutatív csoport. Normált csoportnak hívjuk, ha értelmezve van rajta egy norma. Azaz: G [0, ), x x i) x = 0 x = 0 ii) x = x ( x G) iii) x + y x + y ( x, y G) 1.2.2. Deníció (topologikus vagy folytonos csoport). Ha x n, y n G (n N) sorozatra lim n ρ(x n, x) = 0 és lim n ρ(y n, y) = 0 esetén teljesül: lim ρ(x n + y n, x + y) = 0, lim ρ( x n, x) = 0 n n 1.2.3. Deníció (lokálisan kompakt). Egy (G, ρ) metrikus teret lokálisan kompaktnak nevezünk, ha: Azaz a zárt gömbjei kompakt halmazok. {x G : x r, r > 0} 1.2.4. Deníció (Diszkrét csoport). Egy G csoportot diszkrétnek nevezünk, ha: inf{ x : x 0} > 0 1.2.5. Deníció (Borel-halmaz). (G, +) egy normált Abel-csoport, ρ a norma által indukált metrika. Ekkor a (G, ρ) metrikus tér nyílt részhalmazai által generált B σ-algebra elemei a Borel-halmazok. 6
1.2.6. Deníció (Transzláció invariáns halmaz és mérték). A B Borel halmazok osztálya transzláció invariáns, azaz m mérték transzláció invariáns, ha H B-re teljesül : x + H := {x + y : y H} B x G, H B Borel-halmazra m(x + H) = m(h) 1.2.1. Tétel (Haar Alfréd). Minden lokálisan kompakt topológikus csoporton van nem triviális transzláció invariáns Borel-mérték. 1.2.7. Deníció. Az el z (1.2.1) tételben szerepl mértéket Haar-mértéknek nevezzük. A Haar-mérték konstans faktor erejéig egyértelm en meghatározott. 1.2.8. Deníció (M, M m és T). M := [0, 1) intervallum a mod 1 összeadással. (Ez izomorf a R/Z faktorcsoporttal) { } k M m := : k = 0, 1,..., m 1 az M egy m-edrend ciklikus részcsoportja. m T := {z C : z = 1} a szorzással az egydimenziós tórusz nev csoportot alkotja 1.2.1. Megjegyzés. A komplex trigonometrikus függvény egy izomorzmust ad meg M és T között. Vagyis ɛ : M T, ɛ(t) := e i2πt (t R) egy bijekció, amelyre: ɛ(x+y) = ɛ(x)ɛ(y), ahol a bal oldalon M-beli összeadás, a jobb oldalon pedig T-beli szorzás szerepel. 1.2.9. Deníció (Karakter). A γ : G T leképezés a (G, +) csoport karaktere, ha γ folytonos és: γ(x + y) = γ(x)γ(y) ( x, y G) Azaz γ egy homomorzmus G és T között. Látható, hogy ez az el z megjegyzésben szerepl komplex trigonometrikus függvény tulajdonságai alapján lett deniálva. Az eddig deniált fogalmak segítségével mostmár bevezethetjük a Fourier-transzformáció fogalmát általánosabban is. 1.2.10. Deníció (Fourier-transzformált). f L 1 m(g) és γ karaktere a G normált, lokálisan kompakt csoportnak. Az m pedig a G csoport Haar-mértéke. (Ff)(γ) := f(γ) := f(t)γ(t)dm(t) 7 G
Láthatjuk hogy ez valóban általánosítása az eddig bevezetett Fourier-sornak, Fourieregyütthatónak és Fourier-transzformációnak is mivel: (Ff) speciális esetekben: T F T : f(x) = T F E : f(n) = R M f(t) exp( 2πixt)dt f(t) exp( 2πint)dt T F S : f(x) = ( f(n) exp( 2πinx) = x n e 2πinξ, n Z ( DF T : f(n) = 1 f(t) exp( 2πint) = m t M m TFT: trigonometrikus Fourier-transzformáció, TFE: trigonometrikus Fourier-együttható, TFS: trigonometrikus Fourier-sor, DFT: diszkrét Fourier-transzformáció, n=1 1 m N 1 n=0 x n e 2πink/N, f L 1 (R), x R f L 1 (R), n Z f l 1 (Z), x M f : M m C, n Z m (A zárójelben a mérnöki matematikában elterjedt jelölést használva) x n := f(n) ) k Z Ahol az exp( 2πixt) függvény az adott tér karakterének konjugáltja. A G {R, M} esetben m mérték a Lebesgue-mértéket, a G {Z, M m } esetben a diszkrét mértéket jelenti. 1.2.2. Megjegyzés (Inverzió). A dolgozatban csak a DFT-nek fontos az inverze, de a fent említett 4 transzformációt egyszerre kezelhetjük a következ tétellel: ) f, f L 1 (R) (G = R) vagy f L 1 (M), f l 1 (Z) ezen feltételek mellett ha: f L 1 m(g) 1 és Ff Lm(Ĝ), ahol Ĝ a G csoport karaktereinek halmazát jelenti, akkor: F (Ff) = f, ahol (F f)(x) := ( F f)( x), (x Ĝ és F, F a G illetve Ĝ Fourier-transzformáltja) Példa a legfontosabb esetre: DF T : f(x) := n Z m f(n) exp(2πinx), (f L 1 (M m )) 8
2. fejezet FFT Ebben a fejezetben ortogonális rendszerek egy fontos osztályával fogunk foglalkozni. Ez az osztály magába foglalja a harmonikus analízis legfontosabb rendszereit, mind folytonos és diszkrét esetben, s t egy- és többváltozós esetben is. Ezen a rendszeren mutatunk egy általános gyors algoritmust, amely az összes ide tartozó rendszeren a Fourier-analízist és Fourier-szintézist is gyorsan el állítja. Ahhoz hogy ezt az algoritmust megismerjük, bevezetünk néhány fogalmat, jelölést. 2.1. Jelölések, deníciók 2.1.1. Jelölés (J n ). J n := {A I : A = 2 n }, ahol I := [0, 1) Tehát J n a [0, 1) intervallum kett ad részekre osztott szakaszai. 2.1.2. Jelölés (L). L n := {f : I C, f az J n -beli intervallumokon konstans} (Tehát L n egy 2 n dimenziós lineáris tér, és L 0 pedig a konstans függvények osztálya ) L := L n, és L 1 := L 1 (I) n=0 Ekkor nyilvánvaló hogy: L 0 L 1... L n L L 1 2.1.1. Deníció (E n -feltételes várható érték). Ahol f L 1, x I és I n J n. (E n f)(x) := 1 I n (x) 9 I n(x) f(t)dt
2.1.1. Megjegyzés. E n f(x) az f függvény x pontot tartalmozó I n intervallumra vett átlaga. Mivel a fenti denícióban I n eleme az J -nek, ezért I n (x) = 1. Az operátor f-et 2n L n -be képezi. F bb tulajdonságai: 0) E 0 f = 1 0 f(t)dt (f L) i) E n : L 1 L n, lineáris operátor ii) (E I nf)(t)dt = f(t)dt, (f I L1, I J n ) iii) E n (λf) = λe n f, (λ L n, f L 1 ) (azaz az operátor L n -homogén) iv) E n (E m f) = E m (E n f) = E m f, (f L 1, m n, m, n N) Ezen tulajdonságok a denícióból könnyen igazolhatóak. A 0) tulajdonságot kihasználva minden fogalom, amelyben integrál szerepel kiterjeszthet az E n operátorral, hiszen E 0 esetben a szokásos integrál funkcionált kapjuk. 2.1.2. Deníció (E n -ortonormált). Két ϕ i L 2 (I) függvény E n -ortonormált,ha: E n (ϕ k ϕ l ) = δ k,l 2.1.2. Megjegyzés. Ha két függvény E n értelemben ortonormált akkor, a szokásos értelemben is ortonormált. Mivel a 0) és iv) tulajdonságokat kihasználva: 1 0 ϕ k (t)ϕ l (t)dt = E 0 (E n (ϕ k ϕ l )) = E 0 (δ k,l ) 2.1.3. Deníció (E n -Fourier-együttható). ϕ k L 2 (I) ekkor: E n (fϕ k ) 2.1.3. Megjegyzés. Látható, hogy ezek a deníciók E 0 esetben valóban a 1.1.1 és 1.1.4 deníciókat adják vissza. Algoritmikusan diadikus martingál dierenciákból E n -ortonormált rendszerek közönséges ortonormált rendszerek képezhet k. 2.1.4. Deníció (UDMD). ψ = (ϕ n ) n N, ϕ L sorozat egy diadikus martingál dierencia (DMD), ha: ϕ n L n+1 és E n (ϕ n ) = 0 (n N) Ha még a ϕ n (x) = 1 (x I, n N) is teljesül, akkor UDMD az angol Unitary Dyadic Matringale Dierence szavakból. 10
2.1.5. Deníció (Rademacher függvény). 1, 0 x < 1 2 r(x) := 1 1, x < 1 2 A periódusa pedig 1, azaz : r(x) = r(x + 1) (x R) Legyen r n (x) := r(2 n x) (x I, n N) vagyis: 2.1.4. Megjegyzés (Rademacher-rendszer). Az (r n ) n N rendszert Rademechar-rendszernek hívjuk. Ez a legegyszer bb UDMD-rendszer, ami a denícióból azonnal adódik. Az alábbi ábrán egy Rademacher-függvény látható. 2.1.6. Deníció (Bináris felírás). Az x = m n 2 n, n=0 Az r n (x) függvény grafikonja n=0 x n 2 n+1, (x I, x n B := {0, 1}) és m = (m N, m n B) szummák az x és m számok bináris/diadikus el állításai, x n és m n bitek pedig az n. bináris jegyek. 2.1.5. Megjegyzés. Az r n (x) függvények értékei kifejezhet ek az x szám bináris jegyeivel. Ha x = k 2 m, (k {0, 1..., 2m 1 }, m N), akkor válasszuk a végtelensok 0-ra végz d el állítást. Ekkor a Rademacher-függvények a következ alakban állíthatóak el : r n (x) = ( 1) xn Azaz a függvény csak az x szám bináris jegyét l függ. 11
2.1.6. Megjegyzés. Minden UDMD-rendszer el áll mint: ϕ n (x) = ( 1) xn ϕ n(x), (x I, n N, ϕ n L n ) és ϕ n(x) = 1, mivel ϕ n minden 1 intervallumon konstans és minden 2n 1 1 hosszúságú diadikus intervallumra vett átlaga 0. 2n 2.1.7. Deníció (Szorzatrendszer). Vegyük a (ϕ n ) n N függvényrendszer összes lehetséges véges szorzatait. Ezt könnyen megtehetjük a bináris felírást használva. Φ m := k:m n=1 ϕ n = n=0 ϕ mn k, (m N) Látni fogjuk, hogy igensok rendszer el állítható mint UDMD rendszer szorzatrendszere. Ez többek között a következ tétel miatt is hasznos. 2.1.1. Tétel. Minden UDMD-rendszer szorzatrendszere, TONR. (Ebb l rögtön következik, hogy az UDMD rendszerek nem lehetnek teljesek, hiszen a szorzatrendszerben benne van az eredeti UDMD rendszer is.) 2.1.7. Megjegyzés. A komplex trigonometrikus rendszer ɛ m (x) := e 2πimx el áll az (ɛ 2 k) k N rendszer szorzatrendszereként. Ugyanis m-et bináris jegyeivel felírva: ɛ m (x) := e 2πi( k=0 m k2 k )x = e 2πim k2 kx = k=0 k=0 ɛ m k 2k (x) A Walsh rendszer egy átrendezése pedig a Rademacher rendszer szorzatrendszereként áll el, amelyet Walsh-Paley rendszernek szokás nevezni. W := ( w n )n N ( w n := n=0 ) rn mn, (m N) Az eredeti Walsh rendszer pedig az : rendszer szorzatrendszere. φ 0 (x) = ( 1) x 0 φ n (x) = ( 1) xn+x n 1, (n = 1, 2, 3...) 12
2.1.8. Deníció (Bitfordító transzformációk). π N (x) := x N 1 2 + x N 2 2 2 +... + x 0 2 N + n=n x n 2 n+1 (x I) π N (m) := m N 1 + m N 2 2 +... + m 0 2 N 1 +... + m n 2 n (m N) Ahol m n és x N az x és m szám bináris jegyei. 2.1.8. Megjegyzés. Legyen n=n v n := ( 1) xn exp(2πi( x n 1 +... + x 0 2 2 2 n+1 )) Ekkor a (v n ) n N rendszer UDMD rendszer, és az általa generált szorzatrendszer (V m ) m NN bitfordító transzformációkkal kifejezhet a diszkrét trigonometrikus rendszerrel: ɛ m (π N (x)) = V πn (m)(x) 2.2. Az általános algoritmus Végig valamely UDMD rendszer által generált Ψ szorzatrendszer részrendszerével dolgozunk. A 2.1.1. tétel miatt ekkor Ψ TONR így a Ψ N := ( ψ m )m N N részrendszer teljes a L N -re nézve (ahol N N := {0, 1, 2..., 2 N 1}), tehát a Fourier-sorok f tétele alkalmazható és így a függvényeket jellemezhetjük a Fourier-együtthatóival. A most leírt algoritmus mind a függvény Fourier-együtthatóiból vett el állításást (Fourier-szintézis), mind a Fourier-együtthatók kiszámítását (Fourier-analízis) a denícióval vett számolásnál sokkal gyorsabban adja meg. 2.2.1. Jelölés. Jelöljük f(m)-el az m. Fourier-együtthatót (f L N ). Azaz: f(m) := f, ψ m = 1 ( ) ( ) k k f ψ 2 N 2 N m, (m N 2 N N ) k N N Ekkor deníció szerint: ( ) n f = 2 N k N N f( k ) ψk ( n 2 N ), (n N N ) Az L N beli függvényekhez összesen 2 N darab Fourier-együtthatót kell kiszámolni. Ehhez összesen 2 N 2 N darab szorzás és 2 N (2 N 1) darab összeadás kellene. A Fourier-szintézishez 13
is ugyanennyi m velet lenne szükséges. Denícióval való számolás helyett használjuk ki hogy Ψ egy UDMD-rendszer szorzatrendszere. Tudjuk hogy f(m) = E 0 (fψ m ). Az algoritmus során E 0 (fψ m )-on kívül kiszámítjuk az alábbi E N (fψ m )-Fourier-együtthatókat is: E 0 (fψ m ), E 1 (fψ m ), E 2 (fψ m ), E 3 (fψ m ), (m [0, 2 N ), 1 m) (m [0, 2 N 1 ), 2 m) (m [0, 2 N 2 ), 4 m) (m [0, 2 N 3 ), 8 m)... E n (fψ m ), (m [0, 2 N n ), 2 n m) Azaz kompaktabb jelöléssel: E n (fψ m ), (m = 2 n l, 0 l < 2 N n ) Az algoritmus lényege az alábbi tulajdonságon múlik: 2.2.1. Megjegyzés. A Ψ UDMD (2.1.4) rendszer 1. tulajdonságát és az E n operátor (2.1.1) iii) (L n -homogenitás) és iv) tulajdonságát kihasználva: E n (fψ m ) = E n ( ϕn l 0 E n+1 (fψ l2 n+1) ) (m = 2 n l, l = 2l + l 0, 0 l < 2 N n 1, l 0 B) 2.2.2. Megjegyzés. E n operátor deníciója miatt pedig minden f L n+1 -re: (E n (f))(x) = (E ( ) n+1(f))(x) + (E n+1 (f))(x ), k N n, n = 0, 1..N 1 2 Ahol x és x a következ k: x := k 2 n, x := x + 1 2 n+1 Így az általános gyors algoritmus rekurziója a következ : ( En (fψ 2 n (2l+l 0 )) ) (x) = = ϕ n l 0 (x) ( E n+1 (fψ 2 n+1 l) ) (x) + ϕ n l 0 (x ) ( E n+1 (fψ 2 n+1 l) ) (x ) 2 (l N N n 1, n = 0, 1..N 1) 14
Ezt kompaktabb módon is felírhatjuk, ha bevezetjük a következ jelöléseket: 2.2.3. Megjegyzés. ( k ϕ n 2 + 1 ) ( ) k = ϕ n 2 n+1 n 2 n, ahol ϕ n a (2.1.6) megjegyzés szerinti függvény. 2.2.2. Jelölés. α n,k := 1 2 ϕ n ( k 2 n ) ( ) k N N, n = 0, 1,..., N 1 ( f (n) ( ) )( ) ( ) k k,l := E n fψ2 n l k N 2 n n, l N N n, n = 0, 1, 2,..., N Ekkor f (N) k,0 = f( ) k (k N 2 N N ) és f (0) ( ) 0,l = E 0 fψl (l N N ) (Azaz az eredeti függvényt és a Fourier-együtthatót kapjuk vissza.) A 2.2.2 megjegyzésben szerepl tulajdonságot és a rekurziós formulát felhasználva, azt a következ vé egyszer - síthetjük: ( ) f (n) k,2l+l 0 = α n,k f (n+1) 2k,l + ( 1) l 0 f (n+1) 2k+1,l k N n, l N N n 1, l 0 B, n = N N 1 Ezt a rekurziót használva, a kezdeti függvényértékekb l kiindulva, azaz f (N) k,0 -ekb l elkészítjük a f (n) k,l (k N N n, l N n ) értékeket. Ehhez minden lépésben 2 N n 2 n = 2 N darab szorzást és összeadást végzünk. Így tehát f(j) = f (0) 0,j (k N N ) Fourier-együtthatók kiszámításához összesen: N2 N darab szorzás és ugyanennyi összeadás kellett. Tehát az algoritmus INPUT ja az f L N függvényértékek. Az OUTPUT pedig a Ψ N rendszer szerinti f(j) (j N N ) Fourier-együtthatók. Ezeket az E n -Fourier-együtthatók kiszámításának segítségével kapjuk meg, f (n) k,l (n = N 1, N 2,..., 1, 0) sorrendben. Az algoritmus elkészíthet úgynevezett helybenjáró inplace algoritmusként is. Ekkor az algoritmus tárigénye O(1). Tároljuk A tömbben az inputot, mégpedig a következ képpen: ( ) k A(k) := f = f (N) 2 N k,0 (k N N ) 15
Az E n+1 -Fourier-együtthatókat pedig az alábbi módon tároljuk: A(2 N n 1 k + j) := f (n+1) k,j (k N n+1, j N N n 1 ) Ekkor a rekurzió szerint az A(2k2 N n 1 +l), A((2k +1)2 N n 1 +l) értékekkel kiszámoljuk a következ fk,2l n, f (n) k,2l+1 értékeket és 2k2 N n 1 + l = k2 N n + l és (2k + 1)2 N n 1 + l = k2 N n + 2 N n 1 + l alapján az éppen felhasznált két adat helyen tároljuk. Ekkor az N. lépésben el állnak a Fourier-együtthatók a bitfordítótranszformációnak megfelel en: A( π N (l)) = f(l) (l N N ) 2.3. Speciális esetek 2.3.1. A Cooley Tukey algoritmus A diszkrét trigonometrikus rendszeren fogunk dolgozni,most legyen f C N. f(m) az f m. koordinátáját jelöli. Ekkor deníció szerinti analízis és szintézis: = N 1 n=0 Ahol ɛ N (m) az alábbit jelenti: f(m) := F (m) = 2.3.1. Deníció. W N := ɛ N := WN m = W N(m) = ɛ N (m) = N 1 n=0 f(n)e i2πnm/n = f(n)ɛ(m) n 1/N = f, ɛ N(m), (m = 0, 1,..N 1) ɛ 0 1/N ɛ 1 1/N... ɛ (N 1) 1/N W 0m N W 1m N... W (N 1)m N Ahol pedig WN n -nek a twiddle factorok: = W 0 N W 1 N... W (N 1) N ɛ 0 1/N ( m) = ɛ 1 1/N ( m)... ɛ (N 1) 1/N ( m) 16, így tehát: = ɛ 0m 1/N ɛ 1m 1/N... ɛ (N 1)m 1/N
2.3.2. Deníció (Twiddle factor). W n N := exp(2πin/n) Látható, hogy így N-1 darab összeadást és N darab szorzást végzünk. Mivel f és a karakter is komplex, így egy ilyen szorzás 4 szorzást és 2 összeadást igényel. ( ) (a + ib)(c + id) = (ac bd) + i(bc + ad) Így összesen 4N 2 szorzás, és 4N 2 2N összeadás történt. Mivel már léteznek olyan CPU, GPU-k amelyek 1 m veletként végzik el a szorzást és összeadást (a kett t egyszerre SIMD,FMA), így a m velet igény tekinthet 4N 2 -nek. Ezzel a jelöléssel: Az általános algoritmusból látható: F (m) := ( N 1 n:n=2k F (m) := N 1 n=0 f(n)w nm N ) ( N 1 ) f(n)w nm N + W m N f(n)w (n 1)m N n:n=2k+1 (k = 0, 1,..N 1) És tudjuk hogy ekkor a 2 szumma, éppen egy N/2 pontú FFT. Viszont egy K pontú DFT periódikus K szerint, és W Kk K = 1, azaz kihasználjuk hogy: 2.3.1. Jelölés. Jelölje F 01..2 N 1 a 2 N pontú DFT-jét az: (f(0), (1),..., f(2 N 1 )) sorozatnak. f, W 2 N (m) = F 012..2 N 1(m) = F 024..2 N 2(m) + W m 2 N (F 135..2 N 1(m)) Periódikus: F 01..2 N 1(m + 2 N ) = F (m) A komplex trigonometrikus függvény miatt: W (m+2n ) = W m 2 N 2 N Ezzel így megkapva a rekurziót. 2.3.1. Megjegyzés (N = 8). Mivel W 4 8 = exp( 2πi4/8) = exp( πi) = 1 és F 01234567 = F 0246 + W m 8 (F 1357 (m)) és F 0246 [m + 4] = F 0246 (m) : F (0) = F 0246 (0) + W 0 8 F 1357 (0) = F 0246 (0) + F 1357 (0) F (4) = F 0246 (0) + W 4 8 F 1357 (0) = F 0246 (0) F 1367 (0) 17
F (1) = F 0246 (1) + W 1 8 F 1357 (1) F (5) = F 0246 (1) + W 5 8 F 1357 (1) = F 0246 (1) W 1 8 F 1357 (1) F (2) = F 0246 (2) + W 2 8 F 1357 (2) F (6) = F 0246 (2) + W 6 8 F 1357 (2) = F 0246 (2) W 2 8 F 1357 (2) F (3) = F 0246 (3) + W 3 8 F 1357 (3) F (7) = F 0246 (3) + W 7 8 F 1357 (3) = F 0246 (3) W 3 8 F 1357 (3) Majd ugyanezt a rekurzió szerint megismételjük a 4 pontú DFT-kre is: F 0246 (m) = F 04 (m) + W m 4 F 26 (m) F 1357 (m) = F 15 (m) + W m 4 F 37 (m) F 0246 (0) = F 04 (0) + F 26 (0) F 0246 (2) = F 04 (0) F 26 (0) F 0246 (1) = F 04 (1) + W 1 4 F 26 (1) F 0246 (3) = F 04 (1) W 1 4 F 26 (1) Hasonlóan F 1357 (m) is, a két pontú DFT pedig: F 26 (0) = f(2)w 0 2 + f(6)w 0 2 = f(2) + f(6) F 26 (1) = f(2)w 0 2 + f(6)w 2 1 = f(2) f(6) Hasonlóan a maradék 4 darab is. F 04 (0) = f(0) + f(4) F 04 (1) = f(0) f(4) 18
A teljes rekurzió lépéseit az úgynevezett pillangó diagramon szokás ábrázolni. A diagramon az szimbólum a W i,j N faktorral való szorzást jelenti, j pedig a szorzás el jelét. A pirossal jelölt részen látható, hogy a pillangó diagram elnevezés honnan ered. A m velet igény is könnyen leolvasható: hiszen log 2 (N) darab szint lesz, és minden szinten N darab twiddle factor m veletet végzünk. Így az algoritmus sebessége: N log 2 (N) Látható, hogy a vektorok komponensei más sorrendben érkeznek meg a m velet végén. Ahhoz, hogy a helyes sorrendet visszaállítsuk egy egyszer bitreverziót kell végezni. Egy 16 pontú FFT pillangó diagramja 19
2.3.2. A Walsh-rendszerek Megnézzük az FFT algoritmust a Walsh-rendszereken is. Ehhez az egyszer ség kedvéért egy saját python implementációt tekintünk. Az algoritmus nagyon hasonló, szinte megegyezik a diszkrét trigonometrikus rendszer esetével. A lényegi különbség az, hogy az L n -homogenitás miatt, a kiemelend faktor most elt nik, így a +1, 1 marad csak meg. Ez az implementáción jól látható: fwht implementáció A diszkrét trigonometrikus rendszernél, a +1, 1-nél még ott lenne a W m N szorzó is. Ez a függvény ebben a formában a Walsh-Paley rendszer szerint adja meg az együtthatókat. Ahhoz hogy a Hadamard szerinti sorrendben kapjuk meg az eredményt, a bitfordító transzformációt kell használnunk. Bitfordító transzformáció A rev függvény, a bin függvénnyel és úgynevezett string-slice m veletekkel bináris stringgé alakítjuk a számot, feltöltjük 0-kal, és azt megfordítjuk, majd egész 10-es számrendszer beli számot készítünk bel le. A reverse order függvény elkészíti a permutációs 20
vektort és ez alapján átrendezi az inputját. Egy példa a futására: fwht futása Az els esetben a Wash-Paley rendszer szerinti sorrendben, másodikban a Hadamard szerinti sorrendben kaptuk meg az eredményt. 21
3. fejezet Alkalmazások Ebben a fejezetben különböz alkalmazásokra nézünk példákat. El ször a párhuzamosítás tesztelését, majd az egyik legelterjedtebb alkalmazást mutatom be, a sz rést. Ezt különböz képeken fogom végre hajtani mégpedig a párhuzamosított Cooley-Tookey helybenjáró algoritmust használva. A párhuzamosítás implementációját Fixstars általt 2012-ben publikált The OpenCL Programming Book cím könyv segítségével tettem meg. A párhuzamosítás hatékonyságának tesztelésére az AMD-SDK 3.0 FFT példaprogamját használtam. 3.1. Párhuzamosítás tesztelése Az FFT algoritmus legtriviálisabb, párhuzamosítása a következ képpen néz ki. Az algoritmus minden lépése során, az adott f (n) k,l együtthatók kiszámítása, csak az el z lépésben létrejött együtthatóktól függ, egymástól nem. Tehát minden lépés során az f (n) k,l együtthatók egymástól függetlenül kiszámolhatók, így ezeket párhuzamosan végezhetjük. Ezt a pillangó-diagramon jól láthatjuk. A párhuzamosítás egy R7 260m, 2GB memóriával rendelkez videókártyán, OpenCL 1.2 keretrendszerrel történt. A GPGPU (General-Purpose computing on Praphics Processing Units) programozásnak hátránya, hogy az adatok írás,olvásasa a kártya memóriája és a host között lassú folyamat. Ez sokszor annyira lelassítja a folyamatot, hogy meg sem érné CPU helyett GPU-val számolni. A számításkor a komplex vektorban f loat típusú változókat deklaráltam, azaz single precision-nel számoltam, mivel a GPU double típussal dolgozva, több mint 20-szor lassabb. Sajnos ez a videókártya nem elég nagy teljesítmény ahhoz, hogy az FFT algoritmus- 22
nál látványos eredményt érjen el. Viszont egy ennél körülbelül kétszer er sebb GPU-val rendelkez kártya, kétszer gyorsabb eredményt is produkál. (Gyorsabb alatt nagyobb órajellel, vagy több workitemmel, azaz nagyobb párhuzamosíthatósággal rendelkez kártyát értünk.) Látható, hogy a vektor méretének növelésével, lassan a GPU kezdi utolérni a CPU (i7 4510U) idejét, bár még 25 bites számnál is csak pár milisecundummal gyorsabb. Teljesítmény diagram Éppen az említett írás-olvasás lassúsága hátráltatja a GPU-t, amit nagyobb vektoroknál kezd behozni. (Hiszen a CPU ezeknél lassul, de a párhuzamosított algoritmus gyorsabb.) 23
3.2. Sz rés Ebben a szakaszban pár képen fogunk éldetektálást végre hajtani. A kép felfogható egy n n-es dimenziós mátrixként. Eddig 1 dimenziós adatszerkezeteken használtuk az t algoritmusokat. Ahhoz, hogy egy képen ezt megtehessük, futtatni kell az t algoritmust a kép minden során, majd minden oszlopán. Ezt úgy szokás megtenni, hogy amikor az oszlopokon futtatnánk, akkor transzponáljuk a képet és azon futtatjuk. Így a számítógép memóriáját jobban kihasználjuk, s t a párhuzamosítás miatt még inkább, mivel a transzponálás m veletét nagyon hatékonyan lehet párhuzamosítani. (A matlab t2 függvénye is transzponálással van megvalósítva). A képeken a párhuzamosított implementációt hajtuk végre (aminek a sebessége a matlab t2 függvényével 256 256 méret pgm képeken körülbelül azonos). Az t algoritmus a képek jelét, frekvencia tartományba transzformálja, itt sz rünk a magas frekvenciájú jelekre (így a képen a hirtelen változásért felel s alacsony frekvenciájú jeleket (azaz az éleket) nem engedjük át). Ennek eredménye képpen az élek fehéren fognak kiemelkedni. El ször a standart Léna képet fogjuk vizsgálni, majd egy sajátot. Eredeti és sz rt kép 24
nye. A képre szándékosan éleket rajzoltam, így még jobban látható az algoritmus eredmé- Eredeti és sz rt kép Az alábbi képeken egy túl szigorú és egy túl enyhe sz rés látható. Szigorú és enyhe sz rés Az implementációban történt változások a Forráskód fejezetben megtekinthet k. 25
3.3. Polinomok szorzása Tekintsük az alábbi két polinomot: p(x) := a 0 + a 1 x +... + a N 1 x N 1 q(x) := b 0 + b 1 x +... + b N 1 x N 1 A két polinom szorzata: p(x)q(x) = c 0 + c 1 x +... + c 2N 2 x 2N 2 Ekkor minden a i együtthatót meg kell szorozni b j együtthatóval ( i, j 0 i, j N 1). Tehát legrosszabb esetben N 2 darab szorzást kell végezni, (jobb eset ha vannak 0 együtthatók). Tehát a polinomszorzás m veleteigénye: O(N 2 ). Ezt az FFT algoritmussal O(N log(n)) -re csökkenthetjük. Az implementálást ismét pythonban végeztem. Polinomok szorzása Az INPUT a p és q polinomok az együttható vektoruk szerint. A szorzást miatt a 4. és 5. sorban kiszámoljuk mekkorára n het a két polinom szorzata. A 9. sorban megnézzük, hogy a nagyobbik hossz kett hatvány-e. Ehhez kettes számrendszerbe váltjuk a számot és megnézzük, hogy tényleg csak az els helyiértékén szerepel-e 1-es. Ha nem így van, megkeressük a legközelebbi kett hatványt és eltároljuk a power változóban. 26
Végül feltöltjtük nullákkal a legközelebbi kett hatványig, így az t algoritmus gyorsan futhat le. Transzformáljuk p-t és q-t is, majd pontonként összeszorozzuk ket, és végül visszatranszformáljuk. Ez így 3 db t algoritmust és N darab szorzást igényelt, tehát valóban O(N log(n)) lépésszámban kiszámoltuk a szorzatot. Példa a program futására: p(x) = x 3 + 4x 4 + 10x 6 q(x) = 5 + 12x 3x 2 + x 3 + x 7 p(x)q(x) = 5x 3 + 32x 4 + 45x 5 + 39x 6 + 124x 7 30x 8 + 10x 9 + x 10 + 4x 11 + 10x 13 Program p,q input polinomokkal A program által adott polinom pedig valóban ez, hiszen a 10 14 nagyság rend számok 0-nak tekinthet k. 27
3.4. NIST NIST (National Institute of Standards and Technology) Statistical Test Suite egy statisztikai programcsomag, amely 2001-ben azzal a céllal jött létre, hogy a véletlenszám generátorokat validáljanak. Ez 16 darab tesztet jelent, amelyet akár szoftveres, akár hardware-es bináris sorozatgenerátorra alkalmazhatunk. A tesztek a véltelenszer séget próbálják mérni. A tesztek között találhatunk egészen egyszer t és egész szosztikáltat is. NIST Statistical Test Suite A 6. test a DFT Teszt, másnéven a Spektrális Teszt. Itt a sorozatban szerepl kiugró értékeket, csúcsokat vizsgáljuk. Ezzel azt próbáljuk mérni, mennyire jelennek meg olyan minták a sorozatban amelyek közel vannak egymáshoz. 3.4.1. Az algoritmus Az INPUT egy a bináris számsorozat. Ezt el ször átalakítjük 1, 1 érték vé. x i := 2a i 1 Alkalmazzuk DFT-t x-en: X = x = DF T (x) Mivel valósból transzformálunk komplexbe, a transzformált vektornak csak az els n/2 darab elemét vizsgáljuk a szimmetria miatt. Megszámoljuk, hogy hány komponens abszolút értéke kisebb mint h, legyen ez a szám N 1, ahol: h := 2.995732274n, és n az a input hossza. 28
Számoljuk ki N 0 -át, ami az elméleti várható értéke (valódi véletlent feltételezve) azon csúcsok számának, amik kisebbek mint h. Számoljuk ki d-t, ami: d = N 0 := 0.95n 2 N 1 N 0 n(0.95)(0.5)/2 Számoljuk ki a P -értéket: ( ) d P := erfc 2 Ahol erfc(x) := 2 π x e u2 du Ha a kiszámolt P -érték kisebb mint 0.01, akkor a sorozatot nem tekintjük véletlennek. Egyébként átmegy a teszten és annak tekintjük. NIST Spectral Test 29
Az implementáció egy stringet vár inputjának, használata az alábbi módon: Ezen az ábrán a random.org webservice-t használva kértünk 100 darab valódi véletlen számot. Ami át is megy a teszten. S t a kódot ciklusba helyezve, (pár másodperces szünetet tartva a szerver érdekében) 50-b l 50-szer átment 1000 hosszú stringgel is. A honlap szerint majdnem mindig átmegy ezen a teszten. Ellenben az alábbi nyilvánvalóban nem véletlen sorozattal, s t ismeretes hogy mi magunk nehezen tudunk jó véletlen számot generálni. Ezt alá támasztja az is, hogy néhány billenty leütésem nem megy át a teszten. A valóságban persze ajánlott legalább 1000 hosszú stringet, és sok vizsgálat átlagát venni, a megbízhatóbb eredmény érdekében. 30
4. fejezet Forráskód Az itt leírt kódrészletben csak az implementációtól eltért módosításaimat írtam le. Ezek lényegében csak a kártyáról és a környezetr l adnak némi információt, így biztosak lehetünk benne, hogy jó eszközön futtatjuk a számításokat. A maradék változtatás csak azért kellett, hogy Visual Studio 2013 compilerrel futtatható legyen a kód. Az kernel.cl és pgm.h leok lényegében majdnem változatlanok, de minden kód teljes méretében megtekinthet a https://github.com/lengyelr/fft-algoritmus címen. /... / #ifdef APPLE #include <OpenCL/ opencl. h> #else #define CL_USE_DEPRECATED_OPENCL_2_0_APIS #include <CL/ c l. h> #endif /... / int main ( ) { /... / FILE fp ; errno_t e r r ; 31
const char filename [ ] = " k e r n e l. c l " ; size_t s ource_size ; char source_str ; cl_int i, j ; cl_int n ; cl_int m; size_t gws [ 2 ] ; size_t lws [ 2 ] ; // ( d e v i c e ) char vendor ; //CL_DEVICE_VENDOR char device_name ; //CL_DEVICE_NAME char open_cl_c_version ; //CL_DEVICE_OPENCL_C_VERSION char open_cl_version ; // CL_DEVICE_VERSION s i z e_ t max_workgroup ; // CL_DEVICE_MAX_WORK_GROUP_SIZE // ( p l a t f o r m ) char p r o f i l e = NULL; char platform_version = NULL; / Kernel o l v a s a s a / e r r = fopen_s(&fp, filename, " r " ) ; i f ( e r r ) { p r i n t f ( "HIBA: Failed to load k e r n e l. \ n" ) ; e x i t ( 1 ) ; } source_str = ( char ) malloc (MAX_SOURCE_SIZE) ; source_size = f r e a d ( source_str, 1, MAX_SOURCE_SIZE, fp ) ; f c l o s e ( fp ) ; /... / / Device es Platform b e a l l i t a s a / cl_int s t a t u s ; 32
cl_uint numplatforms ; cl_uint numdevices ; size_t s i z e ; cl_platform_id platforms ; cl_device_id d e v i c e s ; clgetplatformids (0, NULL, &numplatforms ) ; p r i n t f ( "Number o f Platforms : %d\n\n", numplatforms ) ; platforms = ( cl_platform_id ) malloc ( numplatforms sizeof ( cl_platform_id ) ) ; clgetplatformids ( numplatforms, platforms, NULL) ; clgetdeviceids ( platforms [ 1 ], CL_DEVICE_TYPE_ALL, 0, NULL, &numdevices ) ; d e v i c e s = ( cl_device_id ) malloc ( numdevices sizeof ( cl_device_id ) ) ; clgetdeviceids ( platforms [ 1 ], CL_DEVICE_TYPE_ALL, numdevices, devices, NULL) ; context = clcreatecontext (NULL, numdevices, devices, NULL, NULL, &s t a t u s ) ; cmdqueue = clcreatecommandqueue ( context, d e v i c e s [ 1 ], 0, &s t a t u s ) ; / Platform i n f o / clgetplatforminfo ( platforms [ 0 ], CL_PLATFORM_PROFILE, NULL, p r o f i l e, &s i z e ) ; 33
p r o f i l e = ( char ) malloc ( s i z e ) ; clgetplatforminfo ( platforms [ 0 ], CL_PLATFORM_PROFILE, s i z e, p r o f i l e, NULL) ; clgetplatforminfo ( platforms [ 0 ], CL_PLATFORM_VERSION, NULL, platform_version, &s i z e ) ; platform_version = ( char ) malloc ( s i z e ) ; clgetplatforminfo ( platforms [ 0 ], CL_PLATFORM_VERSION, s i z e, platform_version, NULL) ; p r i n t f ( " Platform Informations : \ n" ) ; p r i n t f ( " ( Status now : %d)\n", s t a t u s ) ; p r i n t f ( " P r o f l e : %s \n", p r o f i l e ) ; p r i n t f ( " Platform Version : %s \n", platform_version ) ; / Device i n f o / clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_VENDOR, NULL, NULL, &s i z e ) ; vendor = ( char ) malloc ( sizeof ( char ) s i z e ) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_VENDOR, s i z e, vendor, NULL) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_NAME, NULL, NULL, &s i z e ) ; device_name = ( char ) malloc ( sizeof ( char ) s i z e ) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_NAME, s i z e, device_name, NULL) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_OPENCL_C_VERSION, NULL, NULL, &s i z e ) ; open_cl_c_version = ( char ) malloc ( sizeof ( char ) s i z e ) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_OPENCL_C_VERSION, 34
s i z e, open_cl_c_version, NULL) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_VERSION, NULL, NULL, &s i z e ) ; open_cl_version = ( char ) malloc ( sizeof ( char ) s i z e ) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_VERSION, s i z e, open_cl_version, NULL) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_MAX_WORK_GROUP_SIZE, NULL, NULL, &s i z e ) ; max_workgroup = ( size_t ) malloc ( sizeof ( size_t ) s i z e ) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_MAX_WORK_GROUP_SIZE, s i z e, &max_workgroup, NULL) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_MAX_COMPUTE_UNITS, NULL, NULL, &s i z e ) ; max_cu = ( cl_uint ) malloc ( sizeof ( cl_uint ) s i z e ) ; clgetdeviceinfo ( d e v i c e s [ 0 ], CL_DEVICE_MAX_COMPUTE_UNITS, s i z e, &max_cu, NULL) ; p r i n t f ( "\n\ ndevice Informations : \ n" ) ; p r i n t f ( "Vendor : %s \n", vendor ) ; p r i n t f ( " Device : %s \n", device_name ) ; p r i n t f ( "opencl C: %s \n", open_cl_c_version ) ; p r i n t f ( "opencl : %s \n", open_cl_version ) ; p r i n t f ( "Max WorkGroup : %d\n", max_workgroup ) ; p r i n t f ( "Max ComputeUnits : : %d\n\n", max_cu ) ; /... / return 0 ; } 35
Irodalomjegyzék [1] Schipp Ferenc, Fourier Analízis [2] Schipp Ferenc, Párhuzamos FFT Algoritmusok, (vázlat) [3] Ryoji Tsuchiyama, Takashi Nakamura, Takuro Iizuka, Akihiro Asahara, Jeongdo Son, Satoshi Miki, The OpenCL Programming Book [4] Eric W. Hansen, Fourier Transforms, Principles and Applications [5] Andrew Rukhin, Juan Soto, James Nechvatal, Miles Smid, Elaine Barker, Stefan Leigh, Mark Levenson, Mark Vangel, David Banks, Alan Heckert, James Dray, San Vo A Statistical Test Suite for Random Number Generators for Cryptographic Applications [6] Yan-Bin Jia, Polynomial Multiplication and Fast Fourier Transform [7] http://developer.amd.com/tools-and-sdks/opencl-zone/ amd-accelerated-parallel-processing-app-sdk 36