年末も終わりに近づきますと、多少の時間的余裕が生まれてきます。そこで本年を振り返る、なんてことをやるのですが、このブログの過去記事も見直したりしております。そこで、9/7の「苦境のインテルに欠けたもの」と題する記事を読み返したのですが、じつはこの解を提供するようなことを私、10年ほど前にやっていたのですね。本日は時間もありますので、ちょっとこのお話をいたしましょう。
三つの道
9/7のブログにも書きましたが、20年ほど前の議論では、将来のコンピュータの向かうであろう方向として、三つの可能性が考えられておりました。一つは「マルチCPU」、「メニーコア」などと呼ばれる多数のCPUを用いる手法、もう一つがゲートアレイをプログラム可能にした「FPGA:フィールド・プログラマブル・ゲートアレイ」上に専用演算回路を形成する手法、そして最後がグラフィック処理に用いられていた「GPU:グラフィック・プロセッサ・ユニット」を計算に転用する方式でした。
現時点で顧みれば、当面の正解はGPUで、この分野で先行するNVIDIA社が大成功を収めたのはよく知られたところです。しかし、20年前では、まだ何が正解かは、よくわかっていなかったのですね。
20年前の時点で、高速演算をする際の常道は、多数のCPUボードを並べた「スーパーコンピュータ」なり「ベクトルプロセッサ」と呼ばれる装置を使う方法でしたから、メニーコアは、確実性の高い手法でした。複数のCPUコアをひとつのLSIに搭載したチップも出ており、複数のプロセスの並列動作を高速に行うことができました。
FPGAを用いる高速化技術は、天文学の膨大な演算を高速に実行する目的で「Grape」というシステムが製作され、大学などで使用されておりました。また、組込みシステムでは、ゲートアレーに専用の演算論理を組み込む形で高速演算を実行することも行われておりました。実は私も、高速演算が必要なアプリケーションにFPGAを使い、四苦八苦しながら演算論理を組み立てていたのですね。これを簡単に組める「論理設計支援ソフト(CAD)」をつくれば、ひょっとすると商売になるのではないか、「マイクロプロセッサが出始めたころのマイクロソフトのようなまねができるかも、、、」などと考えて、会社を一つこさえた、そういう話の流れになっております。(まあ、実際は、そこまで甘く考えていたわけでもなく、宝くじを買うノリで始めたわけですが。)
Signal-Process-Logic社
このブログページの上の方に固定ページへのリンクがいくつか置かれているのですが、その一番右、「SIGNAL PROCESS LOGIC」と書かれた部分にカーソルを合わせて左クリックいたしますと、Signal-Process-Logic社の各種情報へのリンクページが現れます。
Signal-Process-Logic社は、じつは私が興した会社で、FPGAを用いて数値演算をするコードを、簡単に入力するソフト“CodeSqueear”の開発を目指した会社です。この会社、現在も存在するのですが、ソフト開発の方は休止状態で、現在はコンサルティング中心に業務を展開しております。
Signal-Process-Logic社のウェブページ(http://signal-process-logic.com)の中では、「評価版のページ」が充実しております。以前は製品版のページもあったのですが、現在は製品版の販売を中止しておりますので、製品版のページは削除しております。実は、評価版も、現在使用期限切れ状態となっております。使用期限を延長することは、ヘッダーファイルをいじれば簡単にできるのですが、問題は、PCを買い替えたりWindowsがバージョンアップしたりして、開発環境が使えなくなってしまい、ヘッダファイルもいじれなくなってしまいました。製品を出さないなら、評価版を提供し続ける理由もなかろうということで、そのままになっているのですね。
アプリケーションソフトは、PCが変わったりWindowsがバージョンアップしたりしても、そのまま動きますから、私の手元にある製品版は現在でも動かすことができます。そこで、今回はこのソフトのできることを簡単にご紹介いたします。なお、「CodeSqueezer取扱説明書」に完全な説明がなされております。
CodeSqueezerの現状
このソフト、自分でいうのもなんですが、結構よくできたソフトで、起動すると下のような画面が現れます。

新たなコードを入力するには、FileプルダウンメニューからNewを選びます。そして、画面下部を占める大きな窓にmhdl(メタ・ハードウエア・ディスクリプション・ランゲージ)のソースコード(数式など)を打ち込めばよいのですね。ここでは、通常のコンピュータ言語のように、複数の数式を並べて記入したり、関数定義したりすることもできるのですが、まずは簡単なところで式を一つだけ、「x = 12 * (a + b)」などと打ち込みます。
何かを入力すると、コンパイルが可能となりCompileボタンが押せるようになります。

コンパイルボタンを押すと、コンパイル条件を指定するための下図のウインドウがポップします。ここでは、最上位となる関数名(関数の内部でない場合は、関数「_root」の内部とみなされる)と、入力ポート(値が代入されていない変数は入力ポートとみなされる)の数値型を指定します。

数値型は、仮数部(man)と指数部(exp)につき、信号線を伝わる値の最小値と最大値、これに加わる下駄(bias)を指定します。下駄の指定は、信号線のビット幅を少なくしたい場合に便利ではないかと思います。また、下駄だけを指定することで定数を指定することができ、指数部に定数を指定することで固定小数点数を扱うことが可能となります。定数部は、開発環境が認識しているだけで、それだけでは論理回路には反映されないのですが、他の変数と乗算すると定数乗算のコードが形成されるなど、必要に応じたコード化がなされます。
最大値と最小値を指定する方式の有利な点は、符号付と符号なしを一体で扱うことができる点で、指数部指定の有無で整数と浮動小数点数を扱うことができます。w/errチェックボックスは、この信号が誤差を含む(☑)か否か(☐)の指定で、誤差を含む信号に対しては、有効桁に配慮した信号線が形成されます。最後に「close」をクリックするとコンパイルが始まり以下の画面が表示されます。

上図で表示されているのはVerilog HDLのコードで、これをFPGA開発環境に入力すれば、そのままFPGAが動作する論理に変換することができます。画面表示は、上段右側のラジオボタンで選択することが可能で、ソースコード(mhdl)に戻って書き直すことも簡単にできます。また、funcは式を関数呼び出しに変換した結果(下図)で、演算フローを示すブロックダイアグラムに対応しています。将来、最適化などを行う場合、おそらくは、関数呼び出し形式の段階で最適化することになるのではないかと考え、このレベルの表示形式もきちんと定めております。このあたりは、2010年のDAシンポジウムでの発表資料をご参照ください。

CodeSqueezerのその他の機能として、タイミング調整とシミュレータが含まれています。タイミング調整は、それぞれの論理ゲートの遅延を積算して、一定レベル以下に収まるようにレジスタを挿入して同期演算回路化するツールで、レジスタを経由することで発生するクロック遅延が、演算の複数入力間で同じになるように遅延用のレジスタを挿入しています。またシミュレータは、入力ポートの値の範囲指定を利用してテストベクターを自動発生し、これを順次入力したときの出力を画面表示し、またエクセルファイルの形で出力します。
CodeSqueezer2.0で予定していたこと
こうしてみる限り、このソフトは完成度が高いのですが、いろいろと問題があります。その一つが、誤差のキャンセルという問題で、同じ値を足したり引いたりする形の演算が行われた場合、この同じ値が非常に大きいと、その誤差によって小さな方の値に含まれていた有効桁が失われてしまうという問題なのですね。
たとえば、二次方程式の解の公式「x = (-b ±√(b2 - 4 a c)) / (2 a)」ではbの符号によって±の一方でその値の大部分がキャンセルされます。特にbがa cに比べて大きい場合にこれが顕著なのですね。この場合、bの符号が特定の場合に「-b ̠∓√(b2 - 4 a c)」を分子分母に乗じることにより、この問題が回避できます。これを、演算式一般に対して自動で行うことが課題となります。この解は、AIの利用ではないかと考えられるのですが、これを一朝一夕に行うことは困難で、ペンディングとなっておりました。
もう一つの問題は、マトリックス演算で、今日AIのコーディングにPythonが用いられる一つの理由がマトリックス演算を簡単に記述できる点ではないかと思われるのですが、forループもないmhdl言語ではこれが難しい。そこで考えたのが、テンソル記法の導入だったのですね。
実は、テンソル記法はC++など、通常のコンピュータ言語にも導入できるのですが、「アインシュタインの縮約記法」を用いますと積和演算を簡単に書くことができる。これをmhdl2には導入してやろうというのが、少々大それた試みであったわけです。結局、この試みは完成を見ることなく終わってしまいました。
テンソル記法は、「#dimension #i #j 2」などの形で、#i、#jの次元を2であると宣言した後、「x = y#i * z#i」と記述した場合には、「x = y[0] * z[0] + y[1] * z[1]」と解釈するやり方です。実際には、添え字を上に書く反変テンソルと添え字を下に書く共変テンソルがあり、縮約は反変と共変の間で行っております。これを正しく表示するのであれば、「x = y#i * z^i」などと書いて下付きを「#」、上付きを「^」と使い分ければよいのですね。一応このやり方への対応を念頭に、排他論理和には「!」を二項演算子として用い、べき乗には「**」を用いることとしました。ただし、現行のバージョンではべき乗演算子は引き続き「^」が用いられております。
テンソルを扱う際には配列が必要になるのですが、このためにmhdlは「リンクリスト」という概念を用いております。このあたりは、2016.5.1の「シグナル・プロセス・ロジック業務日誌」に詳しいのですが、要は、引数に使われている「(a, b, c)」などの記法を「リンクリスト」と呼ぶ。そしてリンクリストの第三要素を「(a, b, c)@2」で参照できるようにする(最初の要素が0ですので)というものです。これをおこないますと、if式「x ? a : b」は「(b, a) @x」と書くことができ、「?」と「:」の記号はコンパイラには不要になります。なおリンクリストは番号でも記述可能とし「:」の記号は、中間を省略した範囲記述に使用することとしております。
反省ですけど、そういうことをいろいろやりますと、仕様が膨大となり、これが頓挫した一つの理由ではないかと思います。まあ、最初に公開したツールの評判が今一つであった、ということもあるのですが。
今後の計画
実は今年の3月のブログにも、このようなお話を書いたのですけど、そろそろこの手のツールが必要になってきたような気がすることも事実です。いずれWindowsが12にバージョンアップするはずですから、その際にPCも新調して開発環境も整え直し、改めてCodeSqueezerの開発を再スタートするのも良いかもしれません。
まあ、全ては闇の中、ではあるのですが。
参考情報
シグナル・プロセス・ロジック管理人日誌では、この言語関連の話題をいくつか公開しております。
2013.9.1:単項演算子、修飾ワイヤとゼロ判定について
2013.10.1:ノイズビットと四捨五入について
2016.4.1:ブロックツリーの形成
2016.10.1:誤差キャンセルへの対応
2016.11.2:全体の考え方とパーサの数式解釈部分の解説
2017.2.1:テンソルの導入:この中で、関数呼び出しの際の引数の区切りに用いる6種類の記号「,」「;」「+,」「+;」「-,」「-;」について解説しております。これは、加減算や乗除算を、それぞれ一つの関数で処理することで、効率的なコードを形成できるようにしたもので、特に、多数の乗除算を、分子と分母を先に演算して、最後に除算を行う形にコード化することで、資源消費の大きな除算を減らすことを目指しております。この場合は、「,」に続く引数が乗じられ(加算され)、「;」に続く引数で除される(減算される)ことを意味します(invに対応)。その前につく「+」と「-」は、比較演算子の「<」「=」「>」を識別するものです(selに対応)。処理マクロと演算子の関係を下表に示します。詳細は2016.11.2の管理人日誌をご参照ください。なお、この段階ではテンソル識別子「#」は導入されておりません。

2017.8.1:テンソルその2
2017.9.1:リンクについて
vhdl