HOME

FFTをやってみた

<2008/11/29記>
 キャッシュのOnOffが出来たし、XYメモリーも使えるようになったし、特権DSPモードにも入れるようになったし、固定小数点も使えたんで、これでどうやらFFTを使う準備が出来たみたいじゃん。
 で、早速やってみたけど、FFTポイント数を増やすと初期化関数がエラーを返してくる。
 分からん・・分からん・・調べる・・調べる・・出た〜〜
 なんとヒープをバカ食いするのだ。
DSP取説 P97
 なんでこんな大事なことがQ&Aなんかに書いてあるんだよ。ちゃんとFftInit関数の項に書いておけっての!・・ったくも〜。
 しかもヒープの増やし方も書いてないし。ヒープは「sbrk.h」で指定してね。
 「必要なことは全部書いてある。ちゃんと目を通さないお前が悪い」って書き方だもんや。
 先が思いやられるな〜

図11 FFT ライブラリ関数 - 最大サンプリング数、使用ヒープサイズ


DSPライブラリが分からん

 実数FFTと複素数FFTってのがある。
 どっちがどっちか良く分からんけど、まんず取り敢えず実数FFTを使うだ。
← その後、複素数FFTのライブラリ関数 FftInComplex をXYメモリーのみで使ってみたけど、実数FFTの方が速かった。実数FFTが約1.2mSで複素数FFTが1.8mSだった。

 ところが使い方がちっとも分からん。
 ネットで色々検索しても、何故か全然出てこないんだよ。
 んで、○ネサスに「もう少し資料かソースを下さい」とメールしたら「
DSP取説が全てです。他にはなんもありません。分からないなら市販の本を読んで勉強すべし」だと。
 なにこの態度。
 本を読んで勉強するのが面倒臭いから資料をくれと言ってるんじゃん。
 仕方ないから自分で考えた・・くそっ・・(^^;

 一週間ほどあちこち調べたり考えたりして、やっと結論が出た。資料をくれりゃなんも考えずに済んだものを手間取らせおって。
 ケチなルネサ○にイジワルされたらここを見においで。
 DSPを全然知らなくて、でもSHのDSPライブラリを使うハメになった気の毒なサラリーマン技術者の味方じゃ(^^;
 って、なにか間違いを見つけたら教えてくだしゃい・・見逃げするんじゃないよ(笑)

 このDSPライブラリはSH-DSPの内蔵メモリーを使ってFFTをするために徹底的に最適化されてる・・・と言うよりも、DSPってこうやって二種類のメモリーを同時にアクセスしたりして高速化するのが常套手段らしいのだ。
 つまり
XYメモリーにデータをセットして演算するのを基本とするって事ね。
 それと
なるべく自分でコードを書かない。なるべくライブラリ関数を利用するんだ。CPU命令でコードを書くと、なんだかんだ言っても遅くなるからさ。
 このことが見えてきてからどんどん進んだなり。

 で、実数FFTで使うのは次の関数どもだ。

InitFFT :初期化関数。

FreeFFT :終了関数。

GenHamming :窓関数用のテーブルを作る(他にもあるよ)。

VectorMulti :窓関数をA/Dデータに掛けるときに使う関数。

CopyToX :A/DデータをXメモリーにコピーする関数。

Limit :FFT時にOverFlowを起こさないようにする関数。

FftReal :FFT関数。

 これらの関数を使うようにして、自分でループとか作らないようにするのがコツなのだ。
 最初はそれを知らないもんだから・・だってどこにも書いてないんだよ〜・・窓関数のテーブルとA/Dデータを自分で掛け算してみたり、A/DデータをXメモリーにコピーするにもループしてたりした。
 こう言うことは一切しちゃぁあきまへん。
 例えば、A/Dデータに-1(0x8000)が含まれてると、FFT演算時にオーバーフローするんで、ループの中で-1をはじいてたんだけど、Limitなんて関数がある。これを使うと0x8000を0x8001に変更してくれる。それもかなり高速。
 ちゅうわけで、要するに「ライブラリ関数を使え。自分でループするな」って事ね。
 で、これが分かってみると、このDSPライブラリはとても良く考えられてるねん。
 高速な内蔵XYメモリーとDSPと内部バスの組み合わせを前提にして作られたライブラリなワケね。逆かな?こういう風に使うべくSH−DSPを設計しておいたって事だろうな。

DSPライブラリ関数の詳細

 関数名の右側の数値は実行時間だけど、PALMICEで計測した時間なんで、まとめて一挙に実行すると、もう少し速くなるはずなのだ。
 なおキャッシュONしてるよ。
 ここで使ってるCPUは、SH7710(SH3-DSP)の200MHzなのだ。

  1. InitFFT 23mS
     なんでも良いからFFTを使う前に一度だけ実行するのだ。
     多分、sinとかcosのテーブルを作ったりしてるのかも?
     注意点はヒープを20キロバイト程度確保しておくこと。
     これをしてないと実行時にエラーが返るのだ。
     ヒープの量はsbrk.hで指定する。
     ヒープの正確な使用量は
    DSP取説 P97のQ&Aに出てる。上の図11と同じ物。
     
  2. FreeFFT 56uS
     使い終わったらこれを実行する。
     ワークメモリーの解放だと思うけど、今時はメモリーはいくらでも載せてるから特に使い道無いよな。
     
  3. GenHamming 14mS
     ハミング窓のテーブルを作る。
     FFT演算の前に実行してテーブルを作っておく。
     色んな種類の窓関数テーブルを作れるから関数一覧を見てくれや。
    DSP取説 P29
     テーブルは必ずXYメモリー上に作ること(ここではYメモリーを使用)。これで次のVectorMultiによる掛け算がメチャクチャ高速になるのだ。ちゅうか、VectorMultiを使いたいからXYメモリー上にテーブルを作るって事な。こう言うことがどこにも書いてないんだよ。
     
  4. VectorMulti 136uS
      3で作った窓関数テーブルとA/Dデータの掛け算をする。
     掛け算した結果は普通のメモリーに書かれる。2048点のFFTをしてるんで、XYメモリーだけじゃ足りないのだ。
     自分で掛け算しちゃダメだよ。CPUでループすると遅くなるからさ。
     CPUでループしたのよりも30倍は速くなるよ・・メチャクチャ早いです。これってもしかしてベクトル演算?
     
  5. CopyToX  110uS
     A/DデータをXメモリーにコピーするのに使う。
     Yメモリーにコピーするのもあるけど、ここではXメモリーを使ってる。
     これも自分でコピーしたらアカン。
     最初はmemcpyでコピーしてたんだけど、やっぱりかなりの速度差有り。
     
  6. Limit 80uS
     こいつを実行すると、データの0x8000を0x8001に変更する。
     つまり0x8000=-1.0を0x8001=-0.999..に変更するって事だ。
     FFT演算でデータに-1.0が含まれてると、オーバーフローするんだそうだ。
     それを防ぐためにデータ内容から-1.0を取り除いておこうって魂胆。
     念のために窓関数テーブルを作った後で、そのテーブルもLimitしてみた。
     しつこく言うけど、自分でループして調べないこと。エエな。
     
  7. FftReal 1.05mS
     実数形式のデータをFFTする(複素数データをFFTするのも有る)。
     前準備が全部終わったところで、やっとFFT演算のお出ましなのだ。
     VectorMultiで書き出したデータを入れてやると、結果がXYメモリーに出てくる。
     ここではXメモリーに実数部、Yメモリーに虚数部が出力される。
     実数だの虚数だのって何?知らないけど結果が出たから良いです(笑)
     
  8. パワースペクトルの計算 136uS
     パワースペクトルは「実数部×実数部 + 虚数部×虚数部」で計算する。
     普通にプログラミングしてると、ついつい「pow(実数部,2)+pow(虚数部,2)」としちゃうでしょ?こんなことしたら千倍は遅くなっちまうで。
     powを使うとコンパイラはまともに浮動小数点を使ったコードを吐き出すんで、今までの苦労がまったく無駄になってしまうのだ。

 FftRealの引数のスケーリング定数の抜粋。DSP取説 P9
 「FFT 計算の各段階において、計算は積和の形式で実行されるためオーバフローが起きやすくなっています。オーバフローが起きるとすべて最大値または最小値となるため計算結果を正しく評価することができません。
 スケーリングはそのオーバフローを防ぐためにFFT 計算の各段階において、どの程度2で割る(右シフトを行う)かを表す目安です。
 スケーリングの性能に及ぼす影響は大きくありません。したがって、スケーリングを決定する場合は性能ではなく、データの特性から決定してください。」
 だとさ。


 ちゅうわけなり。
 ソースはここからDLしたってや。
 こんな事ぐらい教えたって良いじゃんかよな〜
 こんなことでも調べてたら一週間もかかっちまった。
 Googleのオープンな姿勢と、マイクロソフトのクローズな姿勢と似てるよね・・・こんな簡単なことを知らないお前がバカなんだよってか・・くっそ〜(^^;
 質問があったら vics66@ジーメール.com からどうぞ。




FFTリンク



 

[キーワード]
SuperH RISC engine DSP活用 SH-DSP SH2-DSP SH3-DSP SH4AL-DSP SH=MOBILE DSP ライブラリ ライブラリ関数 固定小数点 __fixed __sat 高速フーリエ変換 not-in-place in-place 実数FFT スケーリング FftComplex FftReal VectorMulti CopyToX  CopyToY Limit GenHamming GenBlackman  ヒープメモリ X/Y メモリ XYメモリ __X __Y 

HOME