Ryuz's tech blog

FPGAなどの技術ブログ

VLIWとスーパースカラについて考えてみる

はじめに

少し前に SIMT であるGPUの話 とか SIMDを持ったCPUの話 とか書いてきました。

MIMD についても考察しないといけないなと思いつつ、先だって頭の中で VLIW について気になり始めたので、引き続き個人的な見解を書いてみたいと思います。

また、命令実行方式の違いはあれど、データフローは VLIW と スーパースカラは良く似ているので合わせて考えてみたいと思います。

VLIW(Very Long Instruction Word)

VLIW というと、IA-64 (Itanium) を思い出す方も多いかもしれませんし、トランスメタ社の Cursor を思い出す方もいるかもしれません。最近だと Qualcomm Hexagon が割と成功しているようです(触ったことないですが)。

また 筆者が知っている範囲ですと、AMD の Versal や Ryzen で利用されている XDNAVLIW だったと思います。

VLIW はその名の通り、複数の命令を束ねて1つの長い命令を実行できるようにしたものです。 身も蓋もない言い方をすると、近代のCPUがスーパースカラによる並列実行を行う際に性能を出すためのアウトオブオーダー実行機構などを、CPUがハードウェアで実行時に行うのではなく、プログランのコンパイル時に静的に行おうというものです。

必然的にプロセッサの内部構造が生々しく命令セットに反映されがちですので、バイナリ互換性をどう保つか が一つの重要なファクターであり、互換性を無視して使うケースでの VLIW は普通に実用的だと思います(都度都度コンパイラ作る人はたまったもんじゃないのかもしれませんが)。

一方で、「バイナリ互換性を保ったまま、将来並列性を拡張したい」となると途端に難易度が上がり、「プロセッサの並列数が変わっても互換性のある、並列命令ってどうするの?」という素人目に難しい話になるように思います。

たしか Itanium では命令の並列数を固定せずに、並列実行できる区切りだけを与える命令フォーマットにしていたと思いますし、Cursor では、コードモーフィングによって x86 命令から変換する事で次の Efficeon に拡張しようとしました。

が、結果的に、ハードウェアで変換する今の x86-64 が一番柔軟性があって性能が出て生き残ってしまったという歴史になっているように思います。

一方で、おそらく今の x86 の内部で μOPS を実行する部分は VLIW みたいなものにはなっている気はします。

ソフトウェアパイプライニング

さて、命令セットの問題を置いておくと VLIW にせよ スーパースカラにせよ、異なる命令を同時に実行する と言う点では同じです。 SIMDやSIMTでは同じ命令を同時に実行することしかできませんでした。

しばし当サイトではFPGAの得意な処理として、データ並列の対局としてパイプライン並列の話をしてきましたが、まさにそれが可能でして、ソフトウェアパイプライニングなどと呼ばれます。

これはコンパイラで自動的に行われたり、実行時にアウトオブオーダー機構がいい感じにしてくれたりすることもありますが、明示的に書くなら下記のような感じです。

// prologue
a0 = x[0];

// pipelining
for (i = 1; i < N; i++) {
    a1 = x[i];
    b0 = a0 * 3 + 1;
    y[i-1] = b0;
    a0 = a1;
}

// epilogue
y[N-1] = a0 * 3 + 1;

で、どういう事が起こるかと言うと、下記のような事が起こることを狙っていくことになります。

ソフトウェアパイプラインの狙い

ここでは、あるデータを Store Unit で書いているときに、加算器で次のデータを加算しつつ、その次のデータを乗算器で乗算しつつ、さらにそのまた次のデータを Load Unit で読んでくるという、パイプラインができます。

規模こそ限定的ですが、以前 こちら で発表させて頂いたような動きが CPU でも出来てしまう事になります。

複数の異なる動作ができる実行ユニットを並列実行できるVLIWやスーパースカラ計算機だから出来る事で、特筆すべきことだと思っています。

もっとも、ほとんどの実行ユニットは1サイクルでは処理が終わりませんので、実際にはもう少したくさんのデータで各実行ユニット内のパイプラインの深さを埋めることになります。

1命令で4つずつデータを処理する MN-Core は、非常に合理的に出来ている VLIW の一つだと言えるのではないかと思います。

おわりに

SIMD や SIMT ほど長い話にはならなかったですが、異なる命令を並列実行できる と言う点は、並列化の難しい多くの複雑な問題に対して非常に有効に機能すると思われます。

一方で並列化の規模や粒度の点で、アウトオブオーダーのスーパースカラは命令デコードの負荷から限界があると思います。

しかしながら、「バイナリ互換性を求めないVLIW」であればまだまだ発展の余地がありそうにも思います。

いずれにせよ、同時に異なる演算を実行できる という利点を最も持っているのは FPGA だと思っておりまして、以前、「FPGAは1命令を繰り返すVLIWプロセッサ?」という記事を書かせて頂いた話に繋がるわけです。

世の中で何か面白いアイデアが生まれてくることを祈りつつ、筆をおきます。