numru/fftw3とnumo/fftwをGithub actionsで使う
頭の体操を兼ねて、FFT(Fast Fourier Transform)の代表的なアルゴリズムであるCooley-Tukey(素因数分解して高速化)とBluestein(2のべき乗になるようゼロ埋め)をRubyのgemであるgps_pvtのFFT.hとして実装してみました。正しく実装が行われているか比較するためにFFTライブラリとして著名なFFTWとの比較をしようと思い、Rubyのnumru/fftw3(パッケージ名はruby-fftw3)、およびその近代化版であるnumo/fftw(同numo-fftw)と比較をしてみることにしました。Rspec上にてfft_spec.rbでFFT結果の比較をしてみています。
対応するGithub Actions用のCIスクリプトも作りました。テストをパスさせるうえでいくつか嵌った点があるので、ここに書き残しておこうと思います。
まずGithub Actions上でnumru/fftw3とnumo/fftwを標準的なRubyインストールアクションであるruby/setup-ruby@v1にてbundle installさせるために、少々ビルドを外から助けてあげる必要がありました。CIスクリプト上でBUNDLE_BUILD_XXXという環境変数を設定することで、共有ライブラリのパスやファイル名(-l:narray.soとすると標準(=libnarray.so)でないファイル名のライブラリにリンクできる、ldのmanの-lオプションに記載)、コンパイルオプション(narrayは古いのでgcc-15以降でもビルドするには-std=c17が必要)を教えてあげるようにしています。この環境変数はbundle config setでのビルド設定と同様の効果をもたらします。またこの環境変数の命名規則ですが、_(アンダースコア)が2個で.(ドット)に、_が3個で-(ハイフン)になるという仕様があり、ドキュメントに書いてある(Credentials For Gem Sourcesの最後のほう)ものの、気が付くのに時間がかかりました。
次の嵌りポイントはWindows環境におけるFFTWライブラリの調達です。pacmanを使っても良いのですが、最新版を追えてなさそうなのでvcpkgでセルフビルドするようにしました。ビルドを毎回しなくてよいよう、TAServers/vcpkg-cache@v3にてキャッシュも効かせてあります。
最後にWindowsでの嵌りポイントです。numru/fftw3はnarrayパッケージのnarray.soを、numo/fftwはnumo/narrayのnarray.soを参照します。同時に使おうとすると、共有ライブラリ(.so)の内部が違うにもかかわらず、同じ名前(Windowsではパス全体ではなくファイル名しか見てくれない)によりシンボル解決ができず、死にます。gdbで動きをおってみた(こちらのリンクにあるsls(Show Loader Snaps)のビットを立てると十分なログが取れる)ところ、下記のようなエラーがでていました。
warning: 144f4:b6b8 @ -1382925156 - LdrpReportError - ERROR: Locating export "na_data_type" for DLL "C:\Tools\Ruby\Ruby34-x64\lib\ruby\gems\3.4.0\bundler\gems\numo-fftw-d89821146b5c\lib\numo\fftw.so" failed with status: 0xc0000139.
仕方がないので、ライブラリごとにプロセスを分けて比較をします。といってもWindows環境にはforkがないので、別プロセスをopen3(内部的にはspawn)で立ち上げて、drbで通信をしてFFTの結果だけ取り出すことにしました。
技術的に色々細かいこと(特にWindowsの共有ライブラリまわり)を知れたのが良かったです。
コメント
コメントする
- 匿名でのコメントは受け付けておりません。
- お名前(ハンドル名可)とメールアドレスは必ず入力してください。
- メールアドレスを表示されたくないときはURLも必ず記入してください。
- コメント欄でHTMLタグは使用できません。
- コメント本文に日本語(全角文字)がある程度多く含まれている必要があります。
- コメント欄内のURLと思われる文字列は自動的にリンクに変換されます。
- 投稿ボタンを押してエラーがでなければ、投稿は成功しています。反映されるまでには少し時間がかかります。