後藤弘茂のWeekly海外ニュース

汎用コンピューティングを強化したSandy Bridgeのグラフィックス



●非グラフィックスプログラムを走らせるためのコア

 Intelの次期CPU「Sandy Bridge(サンディブリッジ)」に内蔵しているグラフィックスコアは、全体の構造こそ従来のIntelグラフィックスを引き継いでいるが、内部アーキテクチャは大きく変更されている。3Dグラフィックスと、汎用コンピューティング、そしてメディアプロセッシングの3分野それぞれの処理を高めるために、プロセッサと周辺機能が大幅に強化されている。

 中でも目立つのは汎用コンピューティング向けの拡張。Intelは、Sandy Bridgeグラフィックスコアでは、レジスタファイルを増大させてレジスタを多く必要とする汎用コンピューティングでも、レジスタ溢れのメモリアクセスが発生しにくくした。しかし、それだけではない。Sandy Bridgeグラフィックスコアでは、他にも重要な汎用コンピューティング向け拡張がなされている。

 今どきのGPUでは、非グラフィックスの汎用ソフトウェアを効率的に走らせることが重要なテーマになっている。NVIDIAやAMDのGPUは、そのための機能を強化し続けてきた。その中で、プロセッサ部分では、汎用コンピューティングのために4点セット的な機能が浮かび上がってきた。(1)プレディケーション(Predication)によるフローコントロール制御、(2)スキャッタ/ギャザー、(3)バリアによる同期、(4)アトミックオペレーションの4つだ。

 汎用コンピューティングでの、Sandy Bridgeグラフィックスコアの最大のポイントは、この4点セットを揃えたことだ。ざっくりと言えば、今までのIntelグラフィックスコアでは、多様な汎用プログラムを効率的に走らせることは難しかった。しかし、Sandy Bridgeグラフィックスコアでは、この4点セットによって、汎用コンピューティングが得意なNVIDIA GPUとある程度同じように、汎用プログラムを走らせることができるようになった。ようやく、他社GPUに並んだとも言えるが、Intelコアにとっては大きなジャンプだ。

IntelのSandy Bridgeのグラフィックス
PDF版はこちら

●ベクタ条件分岐でプログラミングが容易に

 ベクタ演算では、同じ命令を複数のデータに対して実行する。しかし、プログラムが複雑になると、条件分岐などのフローコントロールの制御が必要になってくる。プレディケーションはそうした場合のベクタ条件分岐を実現する機能だ。条件分岐によって、1つのベクタの各データ要素に対する命令ストリームが分岐した場合も、プレディケーションによって制御が可能になる。

 例えば、条件分岐によって、ベクタの中の特定のスレッド(またはストランド)が分岐し、他のスレッドが分岐しなかった場合。実行ユニットは、分岐のテイクンとノットテイクンの両方の分岐パスを交互にシリアルに実行する。そして、条件が成立したスレッドのみ、その演算結果をレジスタに書き込む。分岐条件が成立したかどうかはプレディケーション用のマスクレジスタに保存する。命令実行では、マスクレジスタのフラグを参照して、マスクされていないスレッドだけがレジスタに書き込む。

 この機能があると、プログラムを書く側は、マシンがベクタであることを意識しないで、分岐のあるプログラムを書くことができる。分岐でパフォーマンスが大幅に落ちる心配がなくなるからだ。

 そのため、スカラのプログラムを書けば、それが自動的に多数のデータに対して実行される「Single Program, Multiple Data(SPMD)」モデルを、より広汎に適用することが簡単になる。GPUでは、もともと、1ピクセルに対してシェーダプログラムを書くと、SPMDモデルによって自動的に何百万ものピクセルに対して実行される。プレディケーションがあると、複雑な分岐を持つコードでもSPMDモデルで、ある程度効率的に実行することができる。

 これはCPUの現在のSIMD(Single Instruction, Multiple Data)系命令との違いだ。Sandy Bridge CPUコア側のAVX(Advanced Vector Extensions)でも、マスクしたロードとストアは可能だが、GPUのようにマスク専用レジスタは持たず、命令単位でのマスクもできない。

ベクタにおける条件分岐
PDF版はこちら
Sandy Bridgeのグラフィックスの構造

●Larrabeeと類似のプレディケーション機能を実装

 Sandy Bridgeでは、命令単位のプレディケーション機能の実装によって、今どきのGPUらしいコントロールフローの制御が可能になった。無制限なネスティングも可能となっている。IntelはIDFで次のように説明していた。

 「OpenCLやDirectX 11など、次々と並列コンピュートモデルが現れてきた。ここで明確なことは、グラフィックスコアはピクセルを処理するだけでなく、通常のスカラコードのように分岐が多いコードを処理することも増えると仮定しなければならない、ということだ。そのため、SIMDユニットの中で非常に効率的に分岐をハンドルする必要がある。分岐でソフトウェアオーバーヘッドが生じないようにしなければならない」。

 「また、ハードウェアをプログラムする方法について、われわれは隠喩的なプログラミングモデルを取る必要がある。ソフトウェアの観点から言えば、誰がソフトウェアを書く場合でも、スカラプログラムとして書けるようにすることが望ましい。シングルのスカラコードを書けば、それがベクタへとスケールされ、マシンの中のベクタを考慮する必要がないようになる。ハードウェアが複数のスカラプログラムを、並列ハードウェアにマップするわけだ」。

 「その場合、プログラムする側は、どのような分岐も効率的にハンドルされることが確信できていなければならない。コードの観点からは、気軽に分岐を扱うことができるようにすることが重要だ。プレディケーションがあれば、実質、スカラとしてプログラムして、全てを並列に実行することが可能になる」。

 「Sandy Bridgeでは、分岐において、ifステイトメントやDo/Whileで、無限のネスティングを扱うことができる。また、その際に、命令セット上のオーバーヘッドは一切ない。Sandy Bridgeでは、(分岐を)管理するビット群などがあるため、全てハードウェアで制御される。シェーダはずっと自由度が高くなっている」。

 このように、Sandy Bridge GPUコアではコントロールフローの制御と、それによるプログラミングモデルの変化が実現されている。これは、IntelがLarrabee(ララビ)のベクタユニットで行なおうとしていたことにある程度近い。下はLarrabeeでのプレディケーションのスライドだ。

Larrabeeのベクタユニットで行おうとしていた実行方法

●スキャッタ/ギャザとバリヤ同期も実装

 「スキャッタ(scatter)/ギャザー(gather)」も汎用コンピューティングでは重要な機能の1つだ。GPUは、メモリ上に特定のデータ配列でストアされたデータを扱うことに特化して、演算ユニットやレジスタもそれに合わせて構成していた。しかし、汎用コンピューティングでは、多様なタイプのデータを扱うため、必ずしもメモリ上のデータ配列に沿って処理を行なうとは限らない。

 そのため、メモリからレジスタへデータをロードする際に、メモリ(またはキャッシュ)上に分散しているデータを集めるギャザーのハードウェア処理が重要になる。ストアする際にはその逆にデータを分散するスキャッタが重要になる。

 通常の実装の場合、スキャッタ/ギャザもプレディケーション同様にマスクレジスタを参照して、ロードまたはストアするアドレスを選択する。Sandy Bridgeグラフィックスコアも似たような方式を取っていると推定される。さらに、Sandy Bridgeでは、データタイプの変換やデータシャッフル(ベクタレジスタの中のデータ要素を入れ替える)などの機能も備えている。こうした点は、消えたLarrabeeアーキテクチャとも共通する。

 並列マシンでは、スレッド間の同期が問題となる。グラフィックスタスクの場合は、スレッド間に依存性がない(ピクセル間の依存はROPが処理する)ため、同期の必要がない。しかし、汎用コンピューティングではそうはいかない。

 同期についてGPUで一般的な手法は、並列に実行しているスレッドが一定のバリアに達したら、そこで処理をストップして同期を取るバリア方式だ。関連する全てのスレッドがバリアに達するまで待たせておき、バリアで揃えてから再び各スレッドをスタートさせる。バリアの間に、一定の粒度の処理があるなら、有効な方式だ。

 Sandy Bridgeのグラフィックスコアは、こうしたバリア同期の機能を備えている。同様の機能はNVIDIAなどのGPUも備えており、Intelコアも同等にスレッド同期を取れるようになった。さらに、IDFでは、Intelは前後のスレッド間のデータ依存を解決するために、依存性をハンドルするスコアボードをセットアップできることも説明している。こちらの詳細は、まだわかっていない。

●メモリとLLキャッシュに対してアトミックオペレーション

 アトミックオペレーションも、今どきのGPUが挙って実装している機能の1つだ。メモリからデータを読み出し、演算して書き戻す、その一連の処理の間にメモリ上のデータを他のスレッドが書き換えたりしないようにロックする。一貫性を保つための仕組みで、Sandy Bridgeグラフィックスコアの場合は、LL(ラストレベル)キャッシュとメモリに対してアトミックオペレーションを行なっている。

 Intelはこうしたグラフィックスコアのプロセッサの拡張を「Native Strengths Enhanced」と呼んでいる。Sandy Bridgeグラフィックスでは、固定機能ユニットを充実させてオフロードしたことに注目が行きがちだが、実際にはプロセッサの命令や機能の拡充の価値も非常に大きい。汎用コンピューティングだけでなく、グラフィックス向けのシェーダプログラムも、複雑度を増す傾向にあるため、コントロールフローの制御などは価値を持つ。

 Sandy Bridgeグラフィックスコアでは、前回の記事で説明したように固定機能ハードウェアを強化した上で、プロセッッサの機能を強化している。そのため、プロセッサであるEU(Execution Unit)の個数は変わらなくても、スループットは向上していると主張する。

 「Sandy Bridgeは12個のシェーダユニットを備えている。3年前は8ユニットだった。しかし、シェーダユニット数で比較してはいけない。Sandy Bridgeのシェーダユニットは、完全に異なる種類(Animal)だ。我々はシェーダユニット数当たりで2倍のスループットを実現している。12ユニットが、かつての24ユニット相当のスループットを発揮する。超越関数のような一部のケースでは、それ以上のスループットになる」とThomas Piazza氏(Intel Fellow, Director, Graphics Architecture)は語る。

 もちろん性能はケースバイケースで、ベンチマークでは、Intelが主張するだけの性能レンジに達するかどうかは別だ。しかし、アーキテクチャを見る限り、汎用コンピューティングについては、全く別物になっているはずだ。

Sandy Bridgeのダイレイアウト
PDF版はこちら

●CISC的なアプローチの命令を追加

 こうした、汎用性と柔軟性のためのプロセッサの機能拡張に加えて、Sandy Bridgeではネイティブ命令セットをグラフィックスAPIに近づけ、グラフィックスアルゴリズムに合わせるという拡張も行なっている。面白いのは、これがCISC(Complex Instruction Set Computer)命令セット的な、より複雑な命令を作るアプローチであることだ。

 Intelによると、もともとIntelグラフィックスコアのネイティブ命令は、RISC的な命令セットアーキテクチャからスタートしたという。また、RISC系プロセッサで見られる、乗算と加算の2命令を1命令に融合させた積和算命令も持っていた。これは、他のGPUもほぼ同じだ。

 しかし、Intelによると、グラフィックスでは必ずしもRISC的な命令セットが適合するとは限らないという。「特定のケースで使われる方程式では、(RISC的な)ISAを超えた方がいい場合もある」(Thomas Piazza氏)。

 そのため、Sandy Bridgeでは、グラフィックスコア内部命令に、これまでよりCISC的なアプローチを取りこみ、より複雑な命令を増やしているという。まず、Sandy Bridgeグラフィックスコアの新ネイティブ命令では、グラフィックスAPI側のCISC的な命令にほぼ1対1で対応するという。命令ステップ数を減らし、プログラムサイズを小さくし、命令当たりのパフォーマンス効率を上げるためと見られる。

 そして、新命令には、非常にグラフィックスに特化したものが含まれるという。グラフィックスで多用される特定の方程式に適合させるためだ。「例えば、3Dグラフィックスでは、2つの乗算と2つの加算の組み合わせが登場する場合が多い。通常なら、このアルゴリズムの実行には、(積和算の)2倍の命令数が必要になる。しかし、Sandy Bridgeはこれら全てを1命令にまとめた命令を用意した」(Piazza氏)という。

 この命令の効用も同じで、命令ステップ数を半分に減らすことで、命令効率を上げることだと推定される。もっとも、実際にはグラフィックスコア内部では、1命令を内部の命令発行ユニットが複数オペレーションに分解して、個別の実行ユニットに発行しているという。Intel CPUがx86 CISC命令をuOP(Micro-Operation)に分解するのと同じことを、Sandy Bridgeグラフィックスコアも行なっていると推測される。

 そのため、同じメソッドを使うことで、将来のIntelグラフィックスコアで、倍精度演算浮動小数点(FP)をサポートすることも比較的容易にできるという。「このこと(2つの乗算と2つの加算の1命令化)は、倍精度演算も非常にクリーンに実装できることを意味している。1命令の(倍精度の)積和算を4命令に分解して、特定の実行ユニットに割り当て1サイクル(スループット)で実行するといった方法が可能だからだ。倍精度を実装する時が来ても、それほど多くのゲートを加える必要はないだろう」(Piazza氏)。

 AMD GPUも4個の単精度積和算ユニットを使って、1個の倍精度積和算を、少ないトランジスタの追加で実行している。似たような方法での倍精度演算のサポートが、近い将来のIntelグラフィックスコアでも可能になると推定される。Sandy Bridgeグラフィックスコアの汎用コンピューティング機能で欠けている要素は倍精度演算なので、Intelは次にはそこを強化して来るだろう。

Sandy Bridgeでの強化
Sandy Bridgeの概要
PDF版はこちら