Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Fftw誰得ガイド

4,089 views

Published on

http://ocaml.jp/um2010 で発表したスライドです

  • Be the first to comment

Fftw誰得ガイド

  1. 1. 桜庭 俊 @ 京大<br />誰得<br />Twitter: @chunjp<br />FFTW/genfftハッキングガイドThe hitchhacker’s guide to FFTW/genfft<br />
  2. 2. FFTWて何<br />MIT で開発されたFFT(高速フーリエ変換)のライブラリ<br />開発: MatteoFrigo & Steven G. Johnson<br />その名も……<br />The Fastest Fourier Transform in the West<br />(西洋最速のフーリエ変換)<br />
  3. 3. ここが凄い<br />Pen4, 2.8GHz<br />Alpha, 833MHz<br />全てのCPUでベンダー提供のライブラリと拮抗(時に凌駕)するパフォーマンスを提供<br />From Proc. IEEE 93 (2), 216–231 (2005)<br />
  4. 4. 支えているのはOCaml!<br />FFT専用コンパイラ “genfft”<br />let reccooley_tukey sign n1 n2 input =<br />let tmp1 = <br /> array n2 (fun i2 -> <br />dft sign n1 (fun i1 -> input (i1 * n2 + i2))) in<br />let tmp2 = <br /> array n1 (fun i1 -><br /> array n2 (fun i2 -><br /> exp n (sign * i1 * i2) @* tmp1 i2 i1)) in<br />let tmp3 = array n1 (fun i1 -> dft sign n2 (tmp2 i1)) in<br /> (funi -> tmp3 (imod n1) (i / n1))<br />固定サイズの問題に対し<br />機械生成されたCコードを出力<br />
  5. 5. 生成コードの例<br />static void n1_5(const R *ri, const R *ii, R *ro, R *io, stride is, stride os, INT v, INT ivs, INT ovs)<br />{<br />…<br /> {<br /> E T2, T3, T5, T6;<br /> T2 = ri[WS(is, 1)];<br /> T3 = ri[WS(is, 4)];<br /> T5 = ri[WS(is, 2)];<br /> T6 = ri[WS(is, 3)];<br /> {<br /> E Tc, T4, T7, Td, Tf, Tg;<br />Tc = ii[WS(is, 1)];<br /> Ts = T2 - T3;<br /> T4 = T2 + T3;<br />Tt = T5 - T6;<br /> T7 = T5 + T6;<br /> Td = ii[WS(is, 4)];<br />Tf = ii[WS(is, 2)];<br />
  6. 6. 今日のお題:genfftで遊ぶ<br />なぜ遊ぶのか?<br />そこにコンパイラがあるからだ!<br />こんな時におすすめ!<br />金曜の夜に上司から「人生、宇宙すべての答えを月曜までに計算しておいて」と命令されたとき<br />卒論のアブストで広げてしまった風呂敷をたたむために高速な数値計算カーネルが必要なとき<br />TopCoder Marathonや現実逃避のお供に<br />
  7. 7. genfft構造<br />and dft sign n input =<br /> let reccooley_tukey sign n1 n2 input =<br /> let tmp1 = <br /> array n2 (fun i2 -> <br />dft sign n1 (fun i1 -> input (i1 * n2 + i2))) in<br /> let tmp2 = .. <br />0.0 * a + b<br />b<br />a+b<br />2a+2b<br />2a+2b<br />a<br />a<br />b<br />b<br />1<br />2<br />V T4, T5, Te, Tf, T7, T8;<br />T4 = LD(&(xi[WS(is, 2)]), ivs, &(xi[0]));<br />T5 = LD(&(xi[WS(is, 7)]), ivs, &(xi[WS(is, 1)]));<br />Te = LD(&(xi[WS(is, 6)]), ivs, &(xi[0]));<br />
  8. 8. 命令セット(抜粋)<br />type expr =<br /> | Num of Number.number<br /> | Plus of expr list<br /> | Times of expr * expr<br /> | Uminus of expr<br /> | Load of Variable.variable<br /> | Store of Variable.variable * expr<br />Ifもloopも無い!<br />実際にはこれを直接書くことは少なく、もっぱらmodule Complexのval(@*) : expr -> expr -> expr<br />val (@+) : expr -> expr -> expr<br />val (@-) : expr -> expr -> exprなどを使う<br />
  9. 9. fibを作る<br />q0, q1, q0+q1, q1+(q0+q1), (q0+q1)+(q1+(q0+q1)), …<br /> let q = load_array_c 2 input in<br />let rec output =<br /> function<br /> 0 -> q 0<br /> | 1 -> q 1<br /> | i -> output (i-1) @+ output (i-2)<br /> in<br /> (* 中略 *)<br /> let odag = store_array_r n oloc output in<br /> let annot = standard_optimizerodag in<br /> let tree = Fcn (* 中略 *) ([Asch annot]))) in<br />print_string (unparse tree ^ " ")<br />LoopはOcaml側で書く<br />Complex.(@+)を利用<br />自動で最適化をしてくれる魔法の言葉<br />実態は最適化関数群を@@で繋いだもの<br />C.unparse : C言語出力!<br />
  10. 10. 出力<br />/*<br /> * This function contains 8 FP additions, 13 FP multiplications,<br /> * (or, 1 additions, 6 multiplications, 7 fused multiply/add),<br /> * 9 stack variables, 7 constants, and 12 memory accesses<br /> */<br />void fib(const R * I, R * O)<br />{<br />DK(KP3_00000, +3.0000);<br />DK(KP8_00000, +8.0000);<br />DK(KP5_00000, +5.0000);<br />DK(KP13_00000, +13.0000);<br />DK(KP2_00000, +2.0000);<br />DK(KP34_00000, +34.0000);<br />DK(KP21_00000, +21.0000);<br />{<br />E T1;<br />E T2;<br />T1 = I[0];<br />T2 = I[1];<br />O[0] = T1;<br />O[1] = T2;<br />O[2] = T1 + T2;<br />O[9] = FMA(KP21_00000, T1, KP34_00000 * T2);<br />O[3] = FMA(KP2_00000, T2, T1);<br />O[8] = FMA(KP13_00000, T1, KP21_00000 * T2);<br />O[6] = FMA(KP5_00000, T1, KP8_00000 * T2);<br />O[4] = FMA(KP2_00000, T1, KP3_00000 * T2);<br />O[7] = FMA(KP8_00000, T1, KP13_00000 * T2);<br />O[5] = FMA(KP3_00000, T1, KP5_00000 * T2);<br />}<br />}<br />FMA=Fused Multiply-Add: ax+b型計算<br />
  11. 11. まとめ<br />FFTWのgenfftはソースの公開された数値計算用のミニコンパイラ<br />ソースサイズが小さく、追跡が容易<br />いろいろな部分が差し替え可能<br />興味を持ったら触ってみてね!<br />
  12. 12.
  13. 13. 以下、予備スライド<br />
  14. 14. MinCamlやLLVMとの違い<br />FFTWはFFTに特化<br />いくつかの特殊で危険な式簡略化を実装<br />oracle.mlなど<br />丸め誤差程度しか違わない数字はマージしてしまう<br />アグレッシブに符号反転した定数を処理<br />
  15. 15. 遊び方提案<br />c.mlを参考にllvm.ml, java.ml, cuda.mlを作成<br />DWTなどを実装<br />あなたのタスクに最適なSchedulerを設計<br />微妙に作りかけで放置されているConvolution kernelを作る<br />その他あなたの好きな計算を<br />
  16. 16. みどころ<br />(* I will regret this hack : *)<br />(* NEWS: I did *)<br />
  17. 17. ソースを読む上での注意点<br />Spotter又は-annotate / -dtypes必須<br />常に汝の横にPLDI’99を置け<br />arrayはUtil.arrayで作成されint -> expr型<br />exprの表す数値は全てcomplex<br />

×