CPU実験でTravis CIを使ってみた
この記事はCPU実験 Advent Calendar 2015の15日目の記事です。
CPU実験において、僕の班は(主に僕の独断で)Travis CIを導入しました。
もう一度CPU実験の概要について説明します。
CPU実験では主に
の4つの係があり、
という流れになります。FPUはコアに組み込みます。また、シミュレータの浮動小数点演算もx86組み込みのfadd命令ではなく、自班のFPUの動作を模倣するシミュレータを書きます(コア/シミュレータの差分を比較するため)。
ここで重要になってくるのは、いかにしてまずシミュレータをバグなく完成させるかということです。
コアやコンパイラは一般にバグなく書き上げるのは難しいので、シミュレータを正しく動作させるのが先決です。
また、コンパイラ→シミュレータのパスを正確につくり上げることでコア係のデバッグに役立ちます。
というか、コンパイラ→シミュレータのパスに信頼性がないと、コアのバグがコアの原因なのかコンパイラやシミュレータの原因なのかわからず、何からデバッグすればいいか手をつけにくいです。
(CPU実験においてはこういう状況は精神衛生によくない)
そのため、コンパイラ→シミュレータのパスの信頼性を担保するのは重要であり、ここにTravis CIを用いることを考えました。
テストの流れ
1. 必要パッケージのインストール
2. min-camlのビルド
3. シミュレータのビルド
4. テストケースの実行
この流れはMakefileに書きました(make testで実行できるようにした)。実際には.travis.ymlのscript属性にmake testと記述してあります。
【参考】.travis.yml
依存パッケージのインストール
テストケースの実行にはPythonのnoseというユニットテストモジュールを用いているので、pipで必要パッケージをインストールします。
pip install -r .install.txt
また、min-camlはOCamlで記述されているためOCamlが必要です。僕はBytesというモジュールを使っているのですが、これはOCaml 4.0.2から導入されたモジュールです。
しかし、travisで標準で用いられているOCamlはもっと古いので、新しいバージョンをインストールする必要があります。
これはTravis CIでOCamlを使うまでの道のり - Handwritingで紹介したので、参考にしてみてください。
min-caml、シミュレータのビルド
これは普通にビルドするスクリプトを書いただけです。
テストケースの実行
テストケースの実行には、上述の通りPythonのnoseというモジュールを用いました。
これはリポジトリ内にある、「test」と名前についているファイル中に含まれる「test」を冠するテストメソッドを実行します。
説明するより見るほうが早いので、僕が書いたテストスクリプトを置いておきます。
これが実際に走るとこのログのようになります。
各々のテストメソッドで行っているのはシミュレータの答えと期待される答えが一致しているかどうかのアサーションで、等しければOK、違っていればそこでテストが落ちます。
Slackへの通知
TravisはSlackへの通知をサポートしています。pushする度にテストが走り、Slackにテスト結果が通知されます。
所感
Travisを使うのは初めてでしたが、pushする度に100行超のログが流れてテストに通るのはなかなか快感でした(自己満足)。
ただ、実際CPU実験の役にたったのかどうかというのは少し疑問です。
というのも、どちらかというとTravisのテストに通すために非本質的なfixを強制されることがありました。
例えば、
などなど。まあ恐らくコンパイラやアセンブラ、シミュレータのデグレーションは防げていたのだろうけど、逆にデグレーションしなかったからあまりありがたみが感じられなかったのかもしれません。「失って初めて気づく幸せ」というやつですね。
あと、浮動小数点演算のテストを作るのはちょっと面倒です。結局僕は面倒だったのでサボりました。
FPUのレギュレーションはx87完全一致ではなく、数ulpの誤差が許されています。
逆にそのせいで浮動小数点演算の答えがx87と一致しないので、テストを書くのが難しいです。
例えば、僕は次のようなロジスティック写像を15回ほど回すlogisticというテストケースを作りました。
ところが、元々1回の浮動小数点演算(ここではfmul)がx87と一致しないので、15回回すと結構大きな誤差になりました。確か1万ulp程度はずれていたと記憶しています。これでも一応レギュレーションは満たしているのですが。
そのため、本当に厳密にテストを書くのならば、ちゃんと不等式で幅を持たせて期待される答えの範囲を記述する必要が出てくるので、非常に面倒くさいです。