Previous ToC Next

4. 楽なやり方は一つではない、ということ。(2009/6/12)

デバッグ、というのは何を作っている時にも必要な作業だが、どういうやり方 がよいか、というのは時と場合によって違う、というのは必ずしも理解されて いるとは限らないような気もする。

例えば、ちょっとしたスクリプトなら、まず書いてみて、実行し、結果が期待 と違っていたらそれから考える、というのでさほど問題はない。が、極端な例 としてカスタム LSI を作る、という話だと、どこか間違っていたら修正に数ヶ 月と、莫大なお金が必要になる。 GRAPE なんかだとそもそもそんな、チップ がバグっていた時に作り直すための予算自体がないので、致命的な(こちらの せいの)ミスがあったところでプロジェクトが崩壊する。

こういう場合には、実チップができる前にあらゆるテストをすることになる。

お金がからまなくても、問題の箇所を特定するための実行や修正、修正後のコ ンパイルといった作業に非常に長い時間がかかる場合には、修正してから数秒 で結果がわかる場合と同じやり方をしていてはいけない。例えば、ハードウェ ア開発をしていて FPGA の中身を変更しないといけない、しかし FPGA の中身 のコンパイラは一度のコンパイルに2時間かかる、あるいは並列プログラムを開 発していて最大コア数の時にだけでるバグがあるが、最大コア数では一日に一 度しかジョブが流れない、といった場合である。

私は経験したことはないが、大昔に計算を使う時には普通のジョブでも一日に 一度しかジョブが流れないものだったようで、昔からある(言い換えると、昔か らあまり改善されていない)状況がある、という話である。

昔の人がどうしたかというと、結局、

    良く考えた
ということである。計算機というものが他にないので、使えるものは自分の頭 と、1970年代になれば電卓くらいは使える、ということになる。よく考える、 というのはもちろん重要なことだが、FPGA の中身の開発、となると全く違うア プローチもある。それは、 FPGA の中身を書き換えなくても色々な変更ができ るようにする、ということである。手軽に中身を変更できるのが FPGA ではな かったか?と思うとこれはなんだか変な気もするが、「手軽」が2時間ならもっ と違う方法が必要である。

とはいえ、一日に一度しかし実行できない昔の計算機と、コンパイル等に数時 間かかるとはいえシミュレーションや実行は何度でもできる FPGA ではデバッ グのしかたは根本的に違う。

例えば、通信路のハードウェアエラーをチェックする回路を作ったとしよう。 これが正しく動作しているかどうかを調べるためには、人為的にハードウェア エラーを起こして、それが検出されるかどうかを調べる必要がある。

このチェックをするのに、以下のようなことをしているのをみたことがある。

  1. 常にエラーを出すようにハードウェアを書き換える。

  2. コンパイル、起動、実行してエラー検出ができることをチェックする。

  3. エラーをださない回路に戻す。

コンパイルに数時間かかるのは良いとして、このやり方の問題は、チェックし たエラーパターンが1通りしかないということであったことが後で判明した。 もちろん、最初からエラー検出が正しく動いたわけではないので、エラーを出 す回路、エラーを出さない回路のどちらも何度もコンパイル、ハードウェアに 転送、実行のサイクルを繰り返す必要があり、一日ではおわっていなかった、 ということはさておき、これで作者が正しく作ったつもりになっていた回路が 実は全く間違っていた。

間違っていた理由は簡単で、上のやり方では可能なエラーパターンのうち1つ だけしかみていなかったが、実際の回路では15箇所くらいから出るエラーを 2ビットに縮約したエラー状態をチェックするようになっていた、ということ である。この15箇所が全てエラーを出した場合のみのチェックをしていた。

このようなやり方になったのは、ハードウェアを変更してエラーを出す、とい うやり方では、本来チェックするべき多様なエラーパターンをチェックするの にはあまりに長い時間がかかる、と意識的になり無意識になり思ったからであ ろう、と想像される。

どのような回路にするべきであったか、というと、外部からのレジスタへの書 き込み等で、ハードウェアを変更しなくても任意のエラーパターンを出すこと ができるような回路にして、それらが正しく検出できるかどうかをテストする、 というのが最低限するべきことである。問題の回路はパリティ生成回路なので、 単純にパリティビット毎に even か odd かを指定するフラグをつける、とい うか、回路的にはレジスタと xor 1つをつけるだけである。

このように、チェックをつける回路をいれても規模・速度的に問題にならない なら、いれておくのが正しいやり方である。あるパターンのエラーを発生させる ためだけのために FPGA の回路を変更する、という方法では、エラーパターン を網羅することが不可能なだけでなく、後でテストしたくなったらまたコンパ イルからやり直しになるからである。

なお、このように後からまたテストするためには、テスト自体が自動化されて いることが必須である。つまり、基本的にスクリプトをパラメータなしで 走らせて、スクリプト自体が出力結果があっているか間違っているか判定でき ないといけない。

この辺の考え方、開発手法をもうちょっと体系化したのが「テスト駆動開発」 である。これは沢山書物もあるが、基本的なところは、例えば 「テスト駆動開発」はプログラマのストレスを軽減するか? を読めばわかると思う。基本的には、

というような話である。

と、こんなわけで、何か変更するのに数時間かかる、というような場合なら、 テストやデバッグのためのコードや回路をあらかじめ作りこんでおいて、なる べく少ない変更回数で間違いを修正する、目的の機能を実現する、というのが 楽をする方法になる。これに対して、例えば数行のスクリプトで実行したら瞬 時に結果がでるなら、大がかりなテスト用コードを書いている間にちょこちょ こソースを変更して実行してみるほうが早かもしれない。
Previous ToC Next