ネイティブコンパイラの善悪
C#を始めとして.NET系のcompilerはネイティブコードを生成できない。VC++(Visual C++)だけはネイティブコードを生成しようと思えば出来る。思うのだが、VC++でネイティブコードを生成できる以上、マイクロソフトの手にかかれば、C#であろうが、VB(Visual Basic)であろうがネイティブコードを生成することぐらいたやすいことである。VBなんか、前のバージョンまではネイティブコードを生成していたわけで、わざわざ生成出来なくしているわけである。
マイクロソフトがご乱心になられたというわけでもない。たとえば、VC++.NETは、プロセッサ別の拡張機能を利用する最適化オプションがある。MMXは利用したとしてもコンパイラはまともなコードを生成できないだろうが、SSEは違う。浮動小数演算にSSEが利用できれば全然話しは違ってくる。
かと言って、そのようにコンパイルしたコードはSSEの搭載マシン(具体的にはPentiumIII以降か)でなければ動作しない。SSE2に関してはPentium4以降である。そのようにコンパイルしたバイナリが現実的に役に立つのかどうかはわからない。自分で使う、自分だけのソフトならばともかく、もし製品としてリリースすることが前提ならば、少なくともSSEを使うバージョンと、SSEを使わないバージョンとの二つのバイナリを用意しなければならない。細かい話をすれば、Pentiumに有って、Pentium以前のプロセッサには無い命令を使っていいのかという話もある。まあ、i486とかはもう市場から消えているだろうから、構わないと言えば構わないのかも知れないが。
そんなわけでVC++.NETでSSEを利用する最適化オプションがあるというのは、たいていの場合、それは魅力でも何でもないし、ほとんど取り沙汰されないのはそういった事情からだ。
そして、ネイティブコード生成で問題となってくるのは、ItaniumやAthlon64のような64bitプロセッサへの対応である。市場では誰もが想像しているよりも遙かに速いスピードで64bitプロセッサに移行しようとしている。32bitプロセッサとはパフォーマンスが違いすぎるからである。現在、そういった過渡期に差し掛かっているのだということを開発者ならば自覚しておかなければならない。
Itaniumに限らず、いまどきのプロセッサはすべてEPIC (Explicitly Parallel Instruction Computing:明示的並列コンピューティング) という技術を採用している。効率的に実行するためには、並列に実行できる命令を事前に明示的に詰め込んでおかなければならない。いくらItaniumで32bitアプリが動くからと言っても、64bit用にチューンされたアプリとでは10倍ぐらい速度差があるんじゃないかと思う。そう考えると「ネイティブコードしか生成出来ない」ことは、今後、長所どころか短所となる。
.NETのようにいったんIL(中間言語)にしてから実行する環境に応じてJITでコンパイルするという方式は、そのへんを見越していたのだとも言える。将来的には、gccとかもIL用のコードを生成出来なければ使いものにならなくなってくる、ということは大いにありうる。多種多様なプロセッサが出てきて、プロセッサごとに必要とされる最適化がまったく異なるからである。
そんなわけで.NETで使われているILの言語仕様について見ていくとしよう。(つづく)