新千葉 ガーベージ・コレクション

FPGA マガジンやインターフェースで書けなかったこと等をちょぼちょぼ書いてます。@ryos36

FPU 拡張命令

Viretex-4 の PowerPC では、APU が使える。APU を使うと、拡張命令を”自分で”作ることが出来る。まさに FPGA の真髄だ。むかし 8087 ボード(チップじゃないところが泣ける)を、秋葉原に買いに行ったのとは隔世の感がある。
Xilinx では標準で PowerPC の FPU をサポートする。ということは gcc で -mhard-float なんてやってやると、FPU 関連の処理が20倍程度(経験値)速くなるというわけだ。素晴らしい。
いろんな人が、この APU 機能に目をつけているようだが、そうは簡単にいかない。まず、FPGA の知識だけでなく CPU 内部の知識が相当必要になる。IBM はオープンにし始めているが、我々はどこまで知りえるのだろう?よしんば、ここはうまく、なんかしらのアクセラレートする機能を CPU に付け加えられたとして、今度は、アセンブラコードやコンパイラの問題が発生する。アセンブラコードをユーザが書くのは大変な上に、binutils で対応しなければならなくなるだろう。多くのユーザーは C で書けることを望むに違いない。そうすると gcc の md のあのややこしい lisp 記述を書かないといけなくなる。
まぁ、md は書けたとしよう(笑)。ちゃんとコンパイラは適切なところで、そのコードを使ってくれるのだろうか?md をざっとみると、わたしはこんな機能をもってますよと gcc に教えてあげていて、制限なども書ける。しかし、それ以上の情報をどうやって渡すのだろう?ieee浮動小数点なら、gcc は知っていようが、ユーザが特別に作ったコードを、どんな時に利用したらいいかなんてのは gcc 側ではわかりようがないのではないだろうか?SH4 にはベクトル演算機能があるが、その辺はどうなっているのだろう?きっと、md だけではなく、かなり gcc の中に作りこみを入れてやっているはずだ。すると、gcc を書き直すくらいの勢いじゃないとうまく最適化されないに違いない。
まぁ、gcc はうまく書けたとしよう(笑)。OS はどうするのだろう?当たり前の話だが、スレッドあるいはプロセスといった概念のある OS は、プロセススイッチ(スレッドスイッチ?タスクスイッチ?)の時に、余分に増えたレジスタの内容をどこかに保存、復元しなければならない。Linux では FPU や Altivec で使うレジスタに関してはそうしているはずだ。eCos でもそうだろう。つまり、ちゃんと OS が管理してやらないとまともに使えないのだ。
ハードウェア、アセンブラコンパイラ、OS これらを熟知していないと APU は使えない。当然、うちの会社ではそれを目指すことになる。gcc はある程度読み始めたので、そのうち、なんか APU 関連で試しに作ってみよう。ものすごいニッチになる。ここまで出来たら航空宇宙産業とかF1に参入できるかもしれない。

Sparc のプロセススイッチ

そういえば、レジスタウィンドウを持つ Sparc では、よくプロセススイッチのスピードが取りざたされる。レジスタが山ほどあれば、それを、退避、復元するだけで、処理時間がかかるというものだ。しかし、それはそれで、OS の技術がカバーしている。その上、世の中はマルチコアに移行しつつある。マルチコアでは、なるべく、プロセススイッチをしない、同じ CPU が同じスレッドを担当するように最適化してやらないと性能が出ない、おといった今までに無い条件が OS に要求される。Sparc は(というか SUN は)いろいろそこの辺は経験、ノウハウがあるわけで、まわりまわって、時代とベクトルが合いだした。かといって、Sparc がはやるとも思えないが。
FPU の使い方でも SUN はシュールだ。FPU のレジスタは長いビットのセーブ・リストアーを1命令(1clock?)で行う。それを利用すれば、memmove が高速に行える。SUN は OS 内の memmove にもそのテクニックを使っていた。勿論、一般デバイスドライバは FPU 命令は使えない。でも、よーく考えると、ユーザが FPU を使っていたりすると、退避復元が発生するわけで、その辺のデメリットも考慮しないとむやみやたらに FPU 命令は使えない。memmove ならどうせ1レジスタ程度しか使わないであろうからいいのか。デバイスドライバで無節操に FPU 命令を使われると、OS もアプリケーションも悪くないのに性能が落ちるということはあるかもしれない。
脱線するが、初めて Sparc を使ったとき、バウンダリに気をつけないとエラーで落ちてしまうのにはおどろいた。今考えれば RISC だから当たり前(最近の RISC はそうでもないみたいだが)だが、私の当時知っていた CPU の 68000 や 8086 系はそんなことはなかった。8086 では奇数番地の 16bit アクセスは2回の読み出しになるから遅い、ということは知っていたので、stack なんかのアクセスには十分に注意するような癖はついていたが、そもそも Sparc ではバウンダリをまたぐアクセスが出来ないということにはタイソウ面食らった。その5年後くらいに、こんどは Ultra-Sparc で 64bit アクセスをするときに同じようなミスをしてまたも面食らった。まったく学習していない。128bitの時はちゃんと対応しよう。