お気に入りタイトル/ワード

タイトル/ワード名(記事数)

最近記事を読んだタイトル/ワード

タイトル/ワード名(記事数)

LINEで4Gamerアカウントを登録
Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に
特集記事一覧
注目のレビュー
注目のムービー

メディアパートナー

印刷2017/05/19 00:00

イベント

Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 GTC 2017で大々的に発表された,NVIDIAの次世代アーキテクチャ「Volta」。そのVoltaを採用するGPU「GV100」のアーキテクチャについては,筆者による解説記事で詳しく説明しているが,その中で「Volta世代GPUに対応した新しいCUDA」として発表されたのが「CUDA 9」である。
 このCUDA 9について詳しく解説するセッション「CUDA 9 and Beyond」が,北米時間2017年5月10日に行われた。セッションを担当したのは,「Mr.CUDA」の異名を持つMark Harris氏だ。CUDAの改良点だけでなく,Volta世代GPUのアーキテクチャに対する理解を深める内容のセッションをかいつまんでレポートしよう。

セッションタイトル(左)と,講演者のMark Harris氏(Chief Technologist GPU Computing,NVIDIA)
画像集 No.003のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に 画像集 No.002のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 なお,本稿の一部は,Voltaのアーキテクチャを説明したセッション「Inside Volta」の内容を含んでいる。そのため,Voltaの解説記事と一部重複する部分があることをお断りしておきたい。


CUDA 9の新要素 その1

Tensor Coreへの対応


 セッションの冒頭でHarris氏は,CUDA 9の新要素として,以下のスライドで示した4つの項目を挙げている。ただ,セッション内容は,この4項目にとらわれず,とくにNVIDIAがアピールしたいCUDA 9のポイントをピックアップして説明するという流れで行われたので,本稿でもそれに沿って話を進めたい。

Harris氏が挙げたCUDA 9の新要素。目を引くのは「Volta Platform Support」だが,CUDA 9自体は既存のNVIDIA製GPUにも恩恵をもたらすものだ
画像集 No.004のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

Tensor Coreへの対応は,CUDA 9にとって最も重要な役目である
画像集 No.005のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に
 新要素の1つめは,Volta世代GPUが搭載する「Tensor Core」への対応だ。
 Tensor Coreとはなにかについては,アーキテクチャ解説記事で詳しく説明しているので,そちらを参照してもらうとして,ここでは簡単におさらいしておこう。
 Tensor Coreとは,機械学習用AIで多用される大規模な行列計算や畳み込み演算に有用な専用演算ユニットである。

 Tensor Coreが実行できる最も基本的な計算は,4×4要素の行列同士による積和算だ。Volta世代GPUでは,4×4要素の行列計算を2つセットにして,1つのWarp(※処理スレッドの実行単位)として扱えるようになっている。

Tensor Coreが実行できる最も基本的な計算は,4×4要素の行列同士による積和算である
画像集 No.006のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

Volta世代GPUでは,4×4要素の行列同士による積和算を,2つまとめて1 Warpとして実行できる
画像集 No.007のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 また,Voltaでは,16×16要素の行列同士による積和算を,16個のWarpに分解して実行する。CUDA 9上では,「WMMA」(Warp Matrix Multiply and Accumulate)という新しいデータタイプ(※計算モデル)を利用することで,それ以上に巨大なサイズの行列計算を行うことも可能だという。もちろんその場合は,より多くのWarpに分解して処理する必要はあるが。

このスライドは,8×8要素の行列同士による計算の例。WMMAを使うと,4x4要素以上の行列同士による積和算も計算できる
画像集 No.008のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

WMMAを対象にしたLoad,Store命令を新設。行列形態のデータをWarpのデータスレッドに展開したり,逆にメモリへ書き出したりする命令だ
画像集 No.010のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 CUDA 9のWMMAを利用して巨大な行列計算を行ったときの処理能力を,Volta世代のGV100とPascal世代のGP100で比較した結果を,NVIDIAは公表している。アーキテクチャ解説記事でも掲載したものだが,あらためて示しておこう。Volta世代にはのGPUには,Pascal以前のGPUにはない行列計算専用プロセッサのTensor Coreがあるので,圧倒的な性能差が出るというわけだ。

CUDAの算術ライブラリ「cuBLAS」で,正方行列同士の積算(GEMM:GEneral Matrix-matrix Multiplication)における性能を,GV100とGP100で比較したグラフ。FP32精度では1.8倍,FP16精度では9.3倍もGV100のほうが速い
画像集 No.011のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に


CUDA 9の新要素 その2

データスレッドの自由なグループ化


 Harris氏が解説したCUDA 9の新要素における2つめのポイントは,Volta世代よりも前,具体的にはKepler世代からPascal世代までのGPUにもメリットのある機能であるという。
 その新要素は,「Warpを任意のサイズにグループ分けして,グループ間で同期をとる」というものだ。NVIDIA製GPUにおける一般的な1 Warpは,32個のデータスレッドからなるが,たとえば,それを4個のデータスレッドからなる8つのグループに分けることが可能になるという。

Warpのグループ分けとは,32個のデータスレッドからなる1 Warpを,4個のデータスレッドからなる8グループに分けるといったもの
画像集 No.012のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 そしてグループに分けたデータスレッドは,任意のグループ同士で同期をとれる。グループごとに処理するGPUが異なる可能性のあるマルチGPU環境であっても,CUDA 9では明示的に同期がとれるようになったのだ。
 CUDA 8までの場合,データスレッドの処理が終了した時点を暗黙の同期ポイントとしていたのだが,CUDA 9では,開発者が明示的に同期ポイントを記述できるようになった。

同期可能なデータスレッドの例
画像集 No.013のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

データスレッドの同期は,データスレッド単位での同期,1 Warpまたはそれより小さい個数のデータスレッドで構成されるグループ間の同期。複数のGPU間にまたがって展開するデータスレッドグループの同期という3パターンが可能だ
画像集 No.014のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 「CUDA 9でのグループ分けと同期の仕組みは,信頼性と安定性の高いデータ処理を行ううえで非常に重要だ」と,Harris氏は説明する。
 一般的なGPUの命令実行は「Single Instruction Multiple Threads」(以下,SIMT),つまり,1つの命令で複数のデータスレッドを処理する形態だ。
 また,異なるデータスレッドに同一メモリアドレスのデータが含まれていて,それらに対して処理が並列実行された場合,明示的な同期指定が行えなかったCUDA 8までは,想定した計算結果が得られなかったり,デバッグ困難なバグの原因となったりする可能性があった。それに対してCUDA 9では,明示的な同期の仕組みを導入することで,問題を解消できるというわけである。しかも,Pascal世代以前のGPUでも利用できるという点が大きなポイントといえよう。

CUDA 8以前は同期の概念がなく,すべてのデータスレッドに対する処理が終わったら終了という仕組みだった
画像集 No.015のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

CUDA 9では,データスレッド単位からGPU単位まで,さまざまな同期をとることができるようになった
画像集 No.016のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

明示的なデータスレッドの同期は,複雑なデータスレッドの並列実行を安全に行うための仕組みである,という説明スライド
画像集 No.017のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に


CUDA 9の新要素 その3

データスレッド間でデータの参照や書き換えを可能に


 Pascal世代以前のGPUでも使える同期の機能だが,本領を発揮するのは,やはりVolta世代GPUで利用するときだ。この本領発揮に当たる要素が,CUDA 9における3つめの大きなポイントだ。
 Volta世代GPUでは,データスレッドの同期を取るだけでなく,データスレッド同士でメッセージをやりとりしたり,データを参照したりできるのである。

 Harris氏が提示した極端にシンプルな例をもとに,この仕組みを説明してみよう。なお,開発者であれば一目で分かると思うが,これは説明のための概念的なプログラムコードであり,実際に動作するものではないのでご注意を。
 A,B,Cという3つのリスト構造データがあり,AとCに対して何らかのGPGPU処理が行われているとしよう。処理自体が何かは問題ではないので,ここでは考慮しなくていい。
 このAとCは,互いのメモリアドレスを参照し合うリスト構造のデータであり,そこに別のリスト構造データであるBを組み込みたいとしよう。リスト構造データの組み替えは,次のデータを指し示すポインタ(メモリアドレス値)の書き換えで行うので,ポインタの書き換えが他のGPGPU処理によって上書きされたりしないように,まずは書き換え対象であるAとCをロックする。

他のデータスレッドに更新されないように,AとCをロックする
画像集 No.018のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 続いて,AとCの間にBが来るように,ポインタを書き換える。

Bのスレッドで,AとCのポインタを書き換える
画像集 No.019のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 書き換えが終わったら,AとCのロックを解除する。

AとCのロックを解除
画像集 No.020のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 こうした処理系を実現するには,データスレッドごとに異なる処理を行う必要がある。しかし,CUDAは本来,「そういう処理はしない」という前提で設計したプラットフォームだった。
 Pascal世代以前のGPUでは,データスレッド32個からなるWarpは,1つのプログラムカウンタ(※スライドではPC)と1つのスタックポインタ(※スライドではS)で管理されていた。プログラムカウンタが示すメモリアドレスに格納されている命令を,複数のデータ――1 Warpなら32個のデータスレッド――に対して実行していたわけだ。

Pascal世代以前のGPUでは,1つのWarpにつき,プログラムカウンタとスタックポインタを1つしか持っていなかった
画像集 No.021のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 そのため,下のスライドに示したように,条件分岐プログラムの命令が実行されたとき,条件(if)を満たしたデータスレッドに対してだけ「A;」と「B;」の処理を実行し,それ以外の条件(else)を満たしたデータスレッドに対しては,「X;」と「Y;」の処理を行うというやり方で,スレッドごとに異なる処理を行っていた。

条件分岐が発生したら,その分岐ごとに対応した処理を対象のデータスレッドに適用していく。プログラムカウンタは1つしかないので,特定のデータスレッドに対してだけ,並行して個別の処理をかけたりはできない
画像集 No.022のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 Warp内のデータスレッドは,共通のプログラムカウンタとスタックポインタで処理するので,各データスレッドに対して,個別の処理を適用するメカニズムがCUDAにはなかった。「A;」と「B;」で,あるいは「X;」と「Y;」で同期を取ることも,アーキテクチャ上できなかったのだ。

 これに対してVolta世代GPUでは,Warp内のデータスレッドが個別のプログラムカウンタとスタックポインタを持てるように,GPUのアーキテクチャが改良された。

32個のデータスレッドが,個別にプログラムカウンタとスタックポインタを持てるように
画像集 No.023のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 これにより,ifの条件を満たしたデータスレッド「A;」の処理が終わった段階で,ほかのデータスレッドと同期を取ったり,ほかのデータスレッドによる演算内容を参照したりといった異なる処理をさせることが可能になったと,Harris氏は説明していた。

Volta世代では,分岐が発生したら,データスレッド別に異なる処理を行えるようになった
画像集 No.024のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

 なお,Harris氏が扱った話題は,プログラムの並列度を上げて性能を引き上げるためではなく,より複雑なプログラミングモデルを可能にするための拡張という点に注意してほしい。

 そのほかにも,Volta世代GPUでCUDA 9を利用すると,同期時にデータスレッドの内容を任意に入れ替えたり,任意のルールに適合するスレッドだけに,特別な処理を行ったりといったことが可能になるという。こうした処理は,各データスレッドが個別のプログラムカウンタとスタックポインタを持ったことで実現できるようになったものだ。

「シャッフルシンク」と呼ぶ同期の例。任意のデータスレッドが持つデータをコピーしたり,データスレッド同士の内容を統合したりといった処理ができる
画像集 No.025のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に

データスレッドごとに異なる処理を行わせる例。ここでは「ビットマスク」と呼ぶルールを複数用意して,ルールに適合するデータスレッドを分類し,分類ごとに異なる処理,たとえばスレッド同士の同期を行わせることが,Volta世代GPUでは可能になる
画像集 No.026のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に


GeForce向けVoltaにTensor Coreは載るのか?


 CUDA 8からCUDA 9へのアップデートは,プログラミングモデルが大きく拡張されたこともあり,CUDAを扱う開発者に大きな影響を与えそうだ。
 NVIDIA側の説明によると,CUDA 8以前のCUDAアプリは,CUDA 9で再コンパイルすることで,互換性を維持できるとのこと。とはいえ,今後はCUDA 9スタイルで開発することを,NVIDIAは強く推奨している。とくにデータスレッドを明示的に同期できる点は,CUDA 9にとってかなり重要な要素と位置付けているようだ。

 では,そのCUDA 9がいつリリースされるのかだが,GTC 2017では未定とのことで,明言されなかった。しかし,Volta世代GPUのリリース時期に合わせて登場することは間違いないので,順当に考えれば2017年第3四半期頃になるだろう。
 CUDAは,TeslaやQuadroといった製品群だけでなく,GeForceでも動作するわけだが,Volta世代GPUを採用すると思われる将来のGeForceで,CUDA 9の全機能が動作するのかは,現時点では分からないというのが正直なところだ。NVIDIAのスタッフに探りを入れてみても,「将来の製品に関する質問には回答しないよ」と,お決まりの台詞が返ってくるだけだった。

Volta世代のTesla V100搭載製品は,シングルスロットサイズのPCI Express拡張カードも発表されている。しかし,Volta世代GeForceの構成や登場時期については,何も明らかになっていない
画像集 No.027のサムネイル画像 / Volta世代GPUにあわせて進化した「CUDA 9」の改良点とは? Tensor Coreへの対応やプログラミングモデルの拡張が鍵に
 GeForceを使うCUDAユーザーが気になるポイントは,おそらく「GeForceのGPUにTensor Coreが載るかどうか」だろう。
 Tensor Coreは事実上,機械学習用AIやコンピュータビジョン処理向けの演算ユニットという位置付けであり,現状ではDirectXやVulkanといった,業界標準の汎用グラフィックスAPIから利用する方法もない。たとえば,NVIDIA製GPUによるアクセラレーションが可能な物理シミュレーションエンジン「PhysX」で,Tensor Coreに対応することがあれば,ゲームで活用することもできなくはなさそうという程度である。
 筆者は,短期的にはGeForceのGPUにTensor Coreを載せる可能性は低いと見ているが,さてどうなるだろうか。

 一方で,Tensor Coreの搭載を除くと,VoltaとPascalのアーキテクチャにおける違いは,16nmプロセスと12nmプロセスといった物理設計以外に,今のところほとんどないようにも思える。Voltaの詳細が明らかになってくれば,Tensor Core以外の違いもクリアになるだろう。

 NVIDIAは2017年4月に,ウルトラハイエンドのGPUとして,(GeForceの名は付かないが)「TITAN Xp」を発表済みである。また,2017年5月17日には,エントリー市場向けのPascal世代GPU「GeForce GT 1030」をリリースするなど,上から下までPascal系のラインナップが揃ったばかりだ。
 そんな事情を考慮すると,Volta系GeForceがすぐに出てくる可能性はないと筆者は予想している。何か動きがあるとすれば,AMDの新世代GPU「Radeon RX Vega」が出てきたあとではないだろうか。

NVIDIAによるCUDA 9についての開発者向けblogポスト(英語)

GTC公式Webサイト(英語)

  • 関連タイトル:

    CUDA

  • 関連タイトル:

    NVIDIA RTX,Quadro,Tesla

  • この記事のURL:
4Gamer.net最新情報
プラットフォーム別新着記事
総合新着記事
企画記事
スペシャルコンテンツ
注目記事ランキング
集計:12月26日〜12月27日