メニーコア時代のプログラム高速化手法とは?
プログラミングモデルとは違って、やや下級の泥臭い話をすれば、2012年から2020年のCPU & GPU統合型プロセッサでは、命令セットとしてスカラ命令とベクトル命令が透過的に利用できることから、プログラムの高速化手法として、コンパイラが積極的なベクトルコード生成を努めるようになる、とTIM SWEENEY氏は予測する。
これはマルチスレッド・プログラミングとは違って、プログラマはそれほど意識せずに(もちろん、ある程度は意識的にプログラム構造に気を使うのもいいだろうが)プログラムしても、コンパイラがそのプログラムの構造を読み解いて、積極的にベクトル命令化して実行コードを吐き出すようになる…ということを言っている。
ここでいうベクトルは、数学的な概念とは若干ずれているので少々わかりにくいかもしれない。
数学的なベクトル計算を直観的に高効率実行する仕組みなのが、IntelのSSEなどの4要素ベクトル計算命令、いわゆるSIMD命令系の"ベクトル"だ。ここで取り扱うベクトルはx,y,z,wのような1セットで意味を持つデータになる。
一方でATI、NVIDIAのGPUやIntelのLarrabeeなどでは16要素(16-Wide)などの規模の大きいベクトルを取り扱える命令形態になっている。これはベクトルとはいっても、実際にはバラバラのアドレスから得られる複数のスカラ値のまとまりのことでx,y,z,wからなる幾何学的なベクトルとは異質のものであり、むしろ「データ列」といったほうがイメージはしやすいかもしれない。そして、この"大規模ベクトル"(データ列)を任意の組み合わせで任意の演算を行って、演算結果をこれまたバラバラのアドレスのメモリやレジスタに出力する。これがTIM SWEENEY氏のいう「新しいベクトル」化だ。
これで何が嬉しいかというと、ループ制御変数とインデックス変数を制御して複数データに渡って処理を実施するようなループ構造のプログラムで、そのループ内の命令に実行順列依存がない場合は、そのループを展開して、その複数データをベクトル命令に展開すれば並列実行をさせることができるのだ。もともとのループを回して実行していたのに比べ、例えば16要素ベクトルの取り扱いに対応していてこれが1命令として実行できるならば、1命令を16回実行するのと比べて、単純計算で16倍の高速化が実現されることになる。
こうした"新しいベクトル"ユニットでは条件や状態に応じた動的な処理系を組み込みたい場合に対応するために、取り扱えるベクトル幅と同じ分だけのマスク機構を持っており、これを活用することで並列実行性の効果を発揮しつつ、条件分岐的な処理系も実装が出来る。
これは、比較的クラシックなGPUでも、実装されてきたアイディアなのだが、未来のCPU & GPU統合型プロセッサでは、このGPU的アイディアが応用されるであろうという予想をTIM SWEENEY氏は立てている。ちなみにLarrabeeの1コアあたりに実装される32ビット16要素ベクトル演算ユニットはまさにそんな実装になっている。
この積極的なプログラムコードのベクトル化展開の仕組みはプロセッサのアーキテクチャに著しく依存するのが問題と言えば問題だ。例えば、新世代のベクトル幅32のベクトルユニットに旧世代のベクトル幅16でベクトル展開したコードを実行させても16分が無駄に空回りするだけで最大性能が得られない。ベクトル幅8のベクトルユニットにベクトル幅16で展開したコードを実行させるのもなかなか難しい問題だ。