Tags: , , , | Categories: ソフトウェア開発, ベンチマーク Posted by usagi on 2010/06/26 2:19 | コメント (0)

MISTライブラリのFFT、遅いと感じたわけではないのだけれどFFTWと比べてみようかと思った。

C++, using GeSHi 1.0.8.8
  1. #include <iostream>
  2. #include <wrp/diagnostics.hxx>
  3. #include <ppl.h>
  4.  
  5. #include <mist/mist.h>
  6. #include <mist/fft/fft.h>
  7.  
  8. int main()
  9. {
  10. const auto N = 16777216;
  11. typedef double TValue;
  12. typedef std::complex<TValue> TComplex;
  13. typedef mist::array1<TComplex> TArray;
  14.  
  15. auto data = TArray(N);
  16.  
  17. Concurrency::parallel_for(0, N, [&](size_t n){
  18. const auto c = M_PI / N;
  19. data[n].real(sin(c * n));
  20. });
  21.  
  22. auto src = data;
  23. decltype(src) dst;
  24.  
  25. auto sw = wrp::diagnostics::StopWatch();
  26.  
  27. sw([&]{ mist::fft(src, dst); });
  28. std::cout<<sw.GetResultInSec()<<std::endl;
  29.  
  30. sw([&]{ mist::ifft(dst, src); });
  31. std::cout<<sw.GetResultInSec()<<std::endl;
  32. }
Parsed in 0.024 seconds at 26.57 KB/s

StopWatchはQueryPerformanceCounterで時間間隔測るクラス(crono対応とかHPET無い環境とかLinuxとか未対応)。operator()で受け取った関数オブジェクトの所要時間を測ったり、GetResultInSec()で計測した時間間隔を秒単位で返します。

parallel_forの中で元データとして1半周期分の正弦波を作っています。データはN件、mist::array1<std::complex<double>>型で作っています。MISTライブラリのFFTはcomplex<double>でもdoubleでも扱える。

FFTは27行目のmist::fft、30行目のmist::ifftとシンプル。このコードの結果は以下の通り。

2.1442 [sec] (FFT)
2.02586 [sec] (iFFT)

※Phenom II 940、Windows 7、VS2010、x64

FFTWも出来合いのDLLなり、ソースコードとVS2010のソリューションファイルを拾ってビルドするだけなので導入の手間はそれほどかからない。でも、FFTWはC言語向けにつくられている事もあり、C++に慣れているとちょっと使い勝手は悪い気がする。FFTW++というのもあるようだけど今回はスルー。

C++, using GeSHi 1.0.8.8
  1. auto src = static_cast<fftw_complex*>(fftw_malloc(sizeof(fftw_complex) * N));
  2. auto dst = static_cast<fftw_complex*>(fftw_malloc(sizeof(fftw_complex) * N));
  3.  
  4. auto pf = fftw_plan_dft_1d(N, src, dst, FFTW_FORWARD, FFTW_ESTIMATE);
  5. auto pb = fftw_plan_dft_1d(N, dst, src, FFTW_BACKWARD, FFTW_ESTIMATE);
  6.  
  7. fftw_execute(pf);
  8. fftw_execute(pb);
  9.  
  10. fftw_destroy_plan(pf);
  11. fftw_destroy_plan(pb);
  12. fftw_free(src);
  13. fftw_free(dst);
  14.  
Parsed in 0.017 seconds at 25.57 KB/s

メモリ確保、FFT、iFFT、メモリ解放の部分だけ抜粋。fftw_plan_dft_1dてのがMISTでいうfftにarray1dを突っ込みますよに相当、プランのFFTW_FORWARDとFFTW_BACKWARDがFFTとiFFTに対応。正規化してくれないので変換結果がデカくなるのもMISTより不便。それはそうと、同様に変換速度を測ってみた。

3.59038 [sec] (FFT)
3.56843 [sec] (iFFT)

(´・ω・`)

FFTW使ったらMIST付属のFFTより速いかもとか思ってたのでしょぼーん…とも一概に言えなくい。MISTの方が使いやすいし、まあいっかー…と。

 

<追記>

MIST内蔵のFFTエンジンはこの界隈ではお馴染み Ooura's Mathematical Software Packages のアルゴリズムが実装されています。

コメント可能な期間を過ぎました