GPUコンピューティングの歴史とCUDAの誕生

2010年7月2日(金)
平野 幸彦

NVIDIA Tesla GPUスパコン、TOP500リスト2位に!!

スーパー・コンピュータ(スパコン)の高性能ランキング「TOP500」を運営するTOP500.Orgは2010年5月28日、NVIDIA Teslaを搭載したスパコンがTOP500の2位になったことを発表しました(ニュースURL)。これを公式に反映した2010年6月のTOP500リストは、ドイツのハンブルグで開催されたカンファレンス「ISC' 10」(International Supercomputing Conference)で、2010年5月31日に提示されました。

今回のニュースは世界のHPC(High Performance Computing)業界を駆け巡りましたが、GPUスパコンがTOP500の上位に入るという事実は、2009年9月に米国のサンノゼで開催された「NVIDIA GPU Technology Conference」において次世代GPUアーキテクチャ"Fermi"が発表された時点で、ある程度予測できたことでもあります。

さかのぼれば、2008年11月に東京工業大学のスパコン「TSUBAME 1.2」が、既存のシステムへの追加アクセラレータとしてTesla GPUを680個導入し、GPUスパコンとしては世界で初めてTOP500の上位にランクインしました(当時29位)。TSUBAME 1.2は、GPUコンピューティングがHPC業界で注目を集める大きなきっかけになったとともに、TOP500の歴史においても1つのターニング・ポイントになりました。

2008年12月、東京工業大学 学術国際情報センターにて。
東工大 松岡聡教授(左手前)、米NVIDIA CEO兼社長ジェン・スン・ファン(右手前)
図1: Tesla T10 GPUを680個搭載したTSUBAME1.2

近い将来を展望すると、東京工業大学が「TSUBAME 2.0」の導入開発をすでに表明しています。Fermi世代のGPUを4000個以上使うことで、世界最高クラスとなる2.4ペタFLOPSを実現する予定です。2010年11月には、米国のニュー・オリンズでスパコンのカンファレンス「SC10」が開催されます。ここでの上位ランク・インを目指して、世界各地で"TSUBAME"型のGPUスパコンが産声を挙げることが予想されます。

なぜGPUでコンピューティングなのか

GPUは、十数年前まではコンピュータ表示出力専用のLSIやASIC(特定用途向けIC)として、グラフィックス・コントローラやGUIアクセラレータといった名称で呼ばれていました。これがなぜGPUと呼ばれるようになり、汎用計算機能を備えるようになり、CPUを上回る浮動小数点演算能力を身に付け、スーパー・コンピュータに利用されるまでに発展したのでしょうか。

米NVIDIA(以下、NVIDIA)のグラフィックス製品を例に、簡単にGPUの歴史を振り返ってみましょう。

NVIDIA GPUの歴史

1995
NVIDIA初のグラフィックス・アクセラレータ 「NV1」を発表
1996
Direct 3Dのサポートにより、ゲーム開発業界での重要な役割を確立
1999
「NVIDIA Quadro」「GeForce 256」を発表し、GPUと命名
DirectX 7対応、T&L(座標変換&ライティング)機能実装
2001
業界初のプログラマブルGPU「GeForce3」を発表
DirectX 8対応、Vertexシェーダ/Pixelシェーダ搭載
2004
「GeForce 6800」を発表
DirectX 9、Shader Model 3.0対応
2006
コンピューティング統合開発環境「CUDA」を発表、GPU コンピューティング革命がスタート
「GeForce 8800」を発表、DirectX 10、Shader Model 4.0対応
2008
「GeForce GTX 200」グラフィック ス・プロセッサ・ファミリを発表
「Tesla 10」シリーズのコンピューティング・ソリューションを発表
2009
次世代CUDA GPUアーキテクチャ(コードネーム「Fermi」)を発表
2010
Fermi世代GPU「GeForce GTX 480」「GTX470」を発表。DirectX 11対応
Fermi世代Tesla GPU「C2050」「M2050」「S2050」を発表

画像表示コントローラからGPUへ

初期のPC用画像表示コントローラは、CPUがビデオ・メモリー(VRAM)に書き込んだテキストあるいはグラフィックス・データを、CRT(ディスプレイ)や組み込みフラット・パネルといった特定の表示装置に合わせたビデオ信号に変換するのが主な役割でした。

その後、WindowsやOS/2などのGUI(Graphical User Interface)対応OSの登場に伴い、CPU主体の描画処理の限界をカバーするために、グラフィックス・アクセラレータまたはGUIアクセラレータと呼ぶ、OSのAPI(Application Programming Interface)に対応したハードウエア描画機能を取り入れたASICが開発され、描画のパフォーマンスや機能が強化されました。

DirectX(Direct 3D)やOpenGLといった標準APIの発達とともに、3次元(3D)グラフィックスの機能が追加されるようになり、3次元オブジェクトを構成する各三角形(ポリゴン)の頂点座標の計算(Vertex Shading)、ポリゴンの位置の計算(Geometry Shading)、ポリゴン内の描画(Pixel Shading)、といった、3Dグラフィックスにおける描画パイプラインの各工程が、段階的にハードウエアとして実装されていきました。

こうした流れの中、NDIVIAは1999年8月31日にGeForce 256を発表し、その拡張された機能や強化されたパフォーマンスに見合った製品の呼称として、"GPU"という名称を提唱しました。

技術的な意味として、GPUは「1秒あたり1000万ポリゴン以上を処理できる、座標変換、ライティング、トライアングル・セットアップおよびクリッピング、レンダリングなどの各エンジンを統合したシングルチップ・プロセッサ」と定義されています。

図2: CUDAへとつながるNDIVIA GPUの歴史(クリックで拡大)

GPUの進化

GPUの登場によって、グラフィックス処理にかかっていたCPUの負荷が激減しました。これに対して、2000年以降のGPUの進化は、半導体集積技術の進歩に合わせた3Dグラフィックス・パイプライン処理のさらなる高速化による、それまで実現できていなかった、リアルタイムで高精細・高品質なグラフィックスを実現していく歴史でもあります。

Vertex Shader(バーテックス・シェーダ)やPixel Shader(ピクセル・シェーダ)が行う計算式をプログラム可能にするプログラマブル・シェーダ技術が登場し、DirectXやシェーダ・モデルを用いたプログラミングの標準化が進みました。こうした動きに合わせ、2002年にはNVIDIAからグラフィックス向けC言語「Cg」が発表されました。高級シェーダ言語「HLSL」(High Level Shader Language)や「GLSL」(OpenGL Shader Language)とともに、ゲーム開発者やデジタル・コンテンツ・クリエータが簡単かつ迅速に高品質なリアルタイム・グラフィックスを実現する環境が整い始めました。

2004年に発表されたGeForce 6シリーズは、DirectX 9とシェーダ・モデル3.0に対応したスーパースカラー設計のGPUです。複数シェーダによる並列パイプライン処理が可能になり、さらなるパフォーマンスの向上に寄与しました。

DirectX 9対応のGPU は、Windows Vistaから搭載された新しいGUI「Windows Aero」のシステム要件の1つにもなっています。

図3: GPUが3次元グラフイックスを処理するための専用パイプライン処理

統合シェーダとGPGPU

2008年11月19日にNVIDIAが行った2つの発表は、GPUの役割がグラフィックスの枠を突き破って新たな世界に飛躍する、という、パラダイム・シフトの到来を告げるものでした。

  • GeForce 8シリーズGPUの発表(G80世代GPU)
    • 統合シェーダ・アーキテクチャ(Unified Shader Architecture)
    • ジオメトリ・シェーダ(Geometry Shader)
    • DirectX 10、シェーダ・モデル4.0
  • 統合開発環境CUDA(Compute Unified Device Architecture)の発表

まず最初に、統合シェーダの必要性と、そのメリットについて考えましょう。

シェーダは以前から、スーパースカラー設計に基付き、同じ機能を持つ複数のシェーダを並列で動作させることが可能でした。ところが、アプリケーションの種類によっては、すべてのシェーダが効率よく使われるというわけではありませんでした。

例えば、対象オブジェクトの動きが大きいジオメトリ変換に処理負荷が偏重している状況では、バーテックス・シェーダはフル稼働しているもののピクセル・シェーダはほとんど休止している、という状態になります。逆に、大きな動きがなくピクセル描画偏重の状況では、ピクセル・シェーダはフル稼働しているもののバーテックス・シェーダは休止している、という状態が存在します。

図4: パイプラインを構成する目的別シェーダを1つに統合した理由(クリックで拡大)

統合シェーダの当初の目的は、このような無駄を省くことでした。1つのシェーダが臨機応変にすべてのシェーダの機能を受け持つことで、なるべく多くのシェーダを並列に効率よく使用し、パフォーマンスを向上させる、ということでした。

図5: 統合シェーダはさまざまな役割をこなす

このような経緯を経てシェーダがプログラマブルになり、単一機能にとどまらない汎用性を持つに至ったことは、GPUがグラフィックスの枠を飛び越えて汎用計算という新たな役割を担うことになる出発点となりました。

G80世代(GeForce 8シリーズ)のGPUは、最大128個のシェーダを持っていました。また、最新のGPUでは、最大400個以上のシェーダを持っています。これらのすべてのシェーダに並列的に浮動小数点演算を実行させることによってCPUのマルチ・コアを上回る計算能力を引き出そうというのが、GPGPU(General Purpose GPU: 汎用目的GPU)という考え方です。

統合開発環境CUDAの登場

しかし、登場したばかりのGPGPUの開発環境は、未熟なものでした。例えば、GPGPUの簡単な計算の例として、
Y[i] = a * X[i] + Y[i] という計算を、i=0 から n-1 まで行うサブルーチンを考えてみましょう。図6に示した参考例のように、ループを使うCPUの標準Cプログラムに比べると、グラフィックス言語を用いたGPUによる並列計算の複雑さは一目瞭然です。また、目的とする計算そのものとは直接関係のないグラフィックス言語を学習する必要があり、本当の意味でのGPUによる汎用計算の普及を支える技術にはなりませんでした。

図6: 旧方式のGPGPUで使われた言語は、処理の記述が複雑だった

こうした初期のGPGPUの未熟さを解決すべく登場したのが、G80世代GPUと同時に発表された「CUDA」 (Compute Unified Device Architecture)です。CUDAとは、NVIDIAのGPUを用いた並列コンピューティングのための統合開発環境です。CUDAを利用して簡素化・効率化したCPUとGPUの複合並列計算手法を、CUDA GPUコンピューティングと呼んでいます。

図7: CUDAでは、C言語ライブラリなどによりGPGPUの開発環境を整備した

CUDAを構成する主な要素は以下の通りです。

  • NVIDIA GPU (G80世代以降のGPU)
  • CUDA対応Driver、CUDA Toolkit、CUDA SDK
  • "CUDA C"をはじめとするプログラミング言語やDirectComputeなどのAPI
  • ライブラリやミドルウエア
  • GPUコンピューティング・アプリケーション

図8: CUDAの構成要素(クリックで拡大)

CUDAによるプログラミング

図9は、CUDAによるプログラミングの例です。CUDAがサポートする言語の1つである"CUDA C"では、いくつかのCUDA特有のユニークな記述が必要にはなるものの、元のC言語に近い、シンプルで分かりやすいものになっています。

図9: CUDA Cによるプログラミング例(サブルーチン)

ただ、これは、あくまでもGPUが計算を行うサブルーチンの部分だけであり、CPUからこのルーチンを起動するためには、以下のような、いくつかの前設定や手続きが必要になります。

  1. GPUメモリー領域の確保
  2. DMA転送によるCPUからGPUへの元データのコピー
  3. GPUのサブルーチンを呼び出し、GPU上で計算を実行
  4. DMA転送により、計算結果をGPUからCPUに戻す

図10: CUDA Cによるプログラミング例(メインルーチン)

GPUコンピューティングでは、CPUのマルチコアを有効に並列的に使用する場合と同じようなレベルでアルゴリズムを考える必要があります。GPUの構造やCUDAの機能を理解したうえでアルゴリズムを考えることが、GPUプログラミングの前提条件になります。

GPUプログラムのコンパイル方法の一例として、Linux上でCUDA C言語を使用する場合について簡単に説明します。以下のようなプロセスを経て、自動的にコンパイルされます。

  1. "nvcc"(NVIDIA C compiler)によるGPUコードとCPUコードの分離
  2. GPUコード、CPUコードそれぞれのコンパイル
    1. GPUコードは、"nvcc"によっていったん中間言語PTX(Parallel Thread Execution)コードになり、最終的にターゲットのバイナリ・コードを生成
    2. CPUコードは、標準GCC(GNU Compiler Collection)によりコンパイル
  3. GPUとCPUそれぞれのバイナリ・コードがリンクされ最終実行ファイルを生成

図11: CUDA CコンパイラによるGPU/CPU混在コードのコンパイル

CUDAによる複合並列計算プログラミング

CUDAによるGPUコンピューティングは、CPUとGPUの共存の上に成り立つものであり、GPUがCPUを置き換えるといった類のものではありません。

かつて、コンピュータの画面出力はCPUが主役でしたが、GPUの登場によってCPUの大幅な負荷軽減と高品質リアルタイム3Dグラフィックスが実現しました。このように、CUDA GPUコンピューティングも、CPUとGPUがそれぞれの得意分野を受け持ちます。こうした連携によって、ハイ・パフォーマンスな複合並列計算環境の実現を目指しています。

NVIDIA Tesla Quadro事業部 GPUコンピューティング担当 シニア・エンジニア

外資系コンピュータ・メーカーにてPCグラフィックス・サブシステムやASICの設計開発、経営企画部門、製品開発プロジェクト・マネージャなどを経験し、2007年NVIDIA入社。現在、GPUコンピューティングの技術的なサポートを担当。
 

連載バックナンバー

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています