GPGPU

GPGPU（General-purpose computing on graphics processing units; GPUによる汎用計算）とは、GPUの演算資源を画像処理以外の目的に応用する技術のことである 。
元来GPUはリアルタイム画像処理向けのデータ並列計算とパイプライン処理に特化した命令発行形態を持ち、またGPUとメインメモリ間の帯域幅は通例狭いことが多いものの、GPUと直結されるVRAM間には十分広い帯域幅を備えていることから、補助的なベクトル計算機の一種とも言える。GPGPUは、GPUが持つこの特性を活かした汎用的なストリーム・プロセッシングの一形態である。GPUを主体として計算機システムを構成した場合、専用設計のスーパーコンピュータと比較して導入・運用のコストが圧倒的に安くなることから、HPCの分野で特に多くの注目を集めている応用技術でもある。

特徴と課題

GPUはメモリにシーケンシャルにアクセスし、かつ条件分岐の無い計算（演算密度の高い処理）に強い。そのような例に行列計算がある。苦手な物の代表として二分探索がある。二分探索は条件分岐だらけなうえ、メモリにランダムアクセスする。ポインタをたどる操作もメモリにランダムアクセスするため、連結リストや木構造なども苦手である。密行列は得意だが、疎行列は苦手で、東京大学情報基盤センターによると100倍遅い。グラフ計算においては、例えば最短経路問題では、完全グラフのような密グラフに対しては高速に計算できるが、頂点から数本しか辺が出ていないような疎グラフに対しては遅い。

条件分岐

GPUはシェーダープロセッサ（ストリームプロセッサ、ストリーミングプロセッサとも）と呼ばれる演算ユニットを多数持ち、複数のシェーダープロセッサをまとめてクラスタとしている。これらの演算器に命令を与えるインストラクション・ユニットはクラスタごとに1台しか無く、クラスタを構成するシェーダープロセッサはそれぞれ異なるデータを与えられ、そのデータに対して同じ命令内容を一度に実行する。このようなSIMD型データ処理は3次元演算やマルチメディア処理に効果を発揮する一方で、命令中に条件分岐による分岐が入るとオーバーヘッドがかさみ、途端に効率を落としてしまう。今日のCPUでは、このようなペナルティを最小限にするためにプリフェッチ／プリデコードや投機実行／レジスタ・リネーミングといった機能を備えているが、GPUでは備えていない（限定的な条件付きで投機的実行を行なえるものもある。GPUでの動的分岐はDirectX 9.0c世代以降でようやく現実的になった）。またPC向けのGPUではシェーダープロセッサごとに分岐するためのプログラムカウンターを持たないため、条件分岐の際は個別に異なる命令を発行するのではなく、実際に命令を実行するか否かを分けるためのマスクレジスタを使って分岐する手法が採用されている 。
また、シェーダープロセッサ間でデータをやりとりする場合、遠くのデータバスを経由することになり、それがボトルネックとなってしまう。この点に関しては、DirectX 10世代の統合型シェーダーアーキテクチャ以降のハードウェアに搭載されている、小容量だがプロセッサグループ内で共有することのできる高速なキャッシュメモリ（共有メモリ）を介することで、プロセッサグループ内でのデータ交換やメモリI/Oの効率を高めることができる 。
一般のアプリケーションで条件分岐が存在しないものは珍しく、こういった制約によってGPUはオフィススイートのようなアプリケーションの実行には不向きである。GPGPUの発展にはいかに効率を落とさず条件分岐を行なうかというのが1つの課題となっている。原理的にはシンプルなアルゴリズム構造を持ったプログラムによって、並列データ処理に最適化することがGPGPUの特長を最大限引き出すことにつながるといえる。

浮動小数点演算

単精度浮動小数点演算に関してはCPUをはるかに上回る理論演算性能とスケーラビリティを持つGPUだが、倍精度浮動小数点演算に関しては様相が異なる。もともとGPUが扱う多くの画像演算（特にリアルタイム3Dグラフィックス）では、整数演算や単精度の浮動小数点演算で足りてしまうために浮動小数点演算器は仮数部が24ビット程度とそれほど広くなく、単精度の演算器で倍精度の浮動小数点演算を行なうには、分割して幾度も演算器を使う必要があり、性能を大きく落とす要因となる。なお倍精度対応が必須とされる科学技術計算分野を含めたHPC向けに設計された製品では、倍精度専用の演算器を搭載・有効化しているものもある。
AMDは2006年に自社のGPU「R580」をベースとした、単精度浮動小数点演算対応のストリームプロセッシング向け製品「AMD Stream Processor」（第1世代AMD FireStream）を発表、続いて2007年にR6xxコアを使用した業界初の倍精度浮動小数点演算対応HPC向けGPUである「AMD FireStream 9170」（第2世代AMD FireStream）を発売した（ただし倍精度の理論演算性能は単精度の場合の1/5となる）。また2008年に発売されたRADEON HD 4850は1チップでは世界初の1TFLOPS（単精度）を達成し、このRADEON HD 4850にも使用されたR7xxコアを使用して低価格かつ高性能を売りに、HPC分野向けに第3世代AMD FireStreamを発売することになった。2010年には、さらに高性能化した第4世代AMD FireStreamを発売している。2014年に発売されたAMD FirePro S9100/S9150では倍精度演算性能が強化され、倍精度の理論演算性能は単精度の場合の1/2になっている 。
NVIDIAも、自社のGPU「G80」をベースとした、単精度浮動小数点演算対応のHPC向け製品「Tesla C870」を2007年に投入、さらに2008年に発売された NVIDIA Tesla C1060 で倍精度に対応したが、単精度933GFLOPSに比べて倍精度は1/12の78GFLOPSとなっており、倍精度演算性能が極端に低かった。2010年に発売された Fermi 世代の Tesla 20 シリーズ では倍精度演算性能が強化され、倍精度の理論演算性能は単精度の場合の1/2になったが、2012年に発売されたKepler世代のTesla K20シリーズ 、2013年に発表されたK40、2014年に発表されたK80 では倍精度の理論演算性能は単精度の場合の1/3となっている。
2015年現在でも、GPUにおける倍精度演算に関してはHPC向けを除き、省電力性能やゲーミング性能を重視・維持するために必要最低限の性能しか用意されないことが多い。また倍精度専用の演算ユニットでは単精度の演算を行なうことはできないため、単精度を優先するか、それとも倍精度を優先するかはチップ設計段階におけるトレードオフとなる。実際、NVIDIAのMaxwellアーキテクチャのGPUでは前世代に存在した倍精度演算器が省略され、単精度演算器を使って倍精度演算を行なうため、倍精度演算のピーク性能は単精度演算の1/32となる。総合的には、依然としてGPUは倍精度の浮動小数点演算が不得意であると言える。

IEEE 754サポートおよびFMA命令

DirectX 11対応となるEvergreen世代以降のAMD GPU、およびFermi世代以降のNVIDIA GPUでは、浮動小数点の演算精度はIEEE 754規格に準拠したものとなっている。なおNVIDIA GPUおよびAMD GPUでは融合積和演算命令 (FMA) をサポートしているため、CPUで同じ内容の処理をFMAを使わず実行した場合と比べて、GPUによる演算結果が異なることもある    。

共有メモリ

GPUによるVRAMへのアクセスは、複数のプロセッサ群によって並列的に発生するため、連続したメモリ領域に対するコアレスアクセス（coalesce access、≒シーケンシャルアクセス）を行なうことで効率化・高速化できる。NVIDIA GPUでは32のハードウェアスレッドを束ねるバッチ単位をWarpと呼び、AMD GPUでは64のハードウェアスレッドを束ねるバッチ単位をWavefrontと呼んでいるが、これらのユニット内ではプロセッサが完全に同期して動作するため、バッチ単位ごとにまとめて連続領域にアクセス（コアレスアクセス）することで効率が良くなる。逆に言えば、バッチ単位内のスレッドがそれぞれ遠く離れたばらばらのアドレスにアクセスするような非コアレスアクセス（≒ランダムアクセス）は効率が悪くなる。
GPGPUの本質は、大量の演算器によって実現されるハードウェアマルチスレッド集合を用いたデータ並列演算により性能を稼ぐ点にある。例えばNVIDIA GPUのFermi/Keplerマイクロアーキテクチャでは、演算器の最小単位をCUDAコア (SP, streaming processor) と呼び、また複数のCUDAコアを束ねる単位をSMX (SM, streaming multiprocessor) と呼んでいるが、GPUでの演算は、複数のSMXに対して同一の命令を発行していき、各々のハードウェアスレッドに割り当てられたデータに対して並列的に演算を行なうスタイルとなる。またWarp単位内における各スレッドはすべて同一の命令を実行する（SIMT）。基本概念としてはAMDのVLIWやGraphics Core NextといったGPUアーキテクチャにおいても同様である。
しかし、このGPGPUプログラミングが特に従来型のCPUプログラミングと異なる点は、共有メモリ（shared memory、シェアードメモリ）の存在である。共有メモリは小容量だが高速で、ユーザープログラマーが明示的に管理できるキャッシュメモリ（≒L1キャッシュ）の仕組みを果たし、複数のコアでデータを共有・交換する目的に使用できる。なお各APIにおいては、CUDAは共有メモリ、OpenCLはローカルメモリ、DirectComputeはグループ共有メモリ、そしてC++ AMPはタイル静的メモリという名称で、それぞれ同等機能を備えている。
例えばFermi/Keplerマイクロアーキテクチャでは、1SMXあたり最大48KBの共有メモリを使用できるが、外部にあるDRAMにキャッシュなしでアクセスする場合と比べて、共有メモリのレイテンシは（スレッド間のバンクコンフリクトがないかぎり）100倍小さくなる。そのため、複数のスレッドから参照されるデータの一時書き込み場所として共有メモリを活用することにより、高速な並列アルゴリズム（たとえば高速に総和を求める並列リダクションなど）や、GPUプログラミングにおける高速化に必要なコアレスアクセス（≒シーケンシャルアクセス）を実現することができるとNVIDIAは説明している。しかしながら、最大でも48KBしかない共有メモリというハードウェア制約がアルゴリズムの幅に制限をかけるため、共有メモリの存在はGPUプログラミングの難しさにもつながってしまう。また、共有メモリに読み書きする際、スレッド間の同期をとるための処理もプログラマーが明示的に記述する必要がある。
なお、インテルCPUのL2キャッシュメモリはL1キャッシュメモリに比べて容量が大きく、またプロセッサコア側に直結されているが、NVIDIA GPUのL2キャッシュメモリはL1キャッシュメモリに比べて容量がほとんど変わらず、またメモリ側に直結されているなど、データアクセス傾向の違いがハードウェア設計思想の違いにも反映されており、単純にキャッシュメモリの容量だけを比較して性能の優劣を決めることはできない  。

接続バスの速度

コンピュータのマザーボードとディスクリートGPUを接続するPCI Express規格は、CPU-システムメモリ間やGPU-ビデオメモリ間と比べてはるかに帯域幅が狭く、安易にGPGPUを導入しようとするとデータ転送がボトルネックとなって逆に性能の低下を招いてしまう可能性もありうる。この点に関しては、NVIDIAが開発した独自のインターコネクト技術であるNVLink などの解決策が模索されている。

開発およびチューニングの難しさと移植性

2015年現在、GPGPU対応プログラムの開発環境・APIとして代表的なものはCUDA、OpenCL、およびDirectComputeであり、GPGPU黎明期の開発環境に比べればはるかに開発しやすくなっているものの、依然としてアクセラレーターとなるハードウェアを意識したGPGPU特有のプログラミング知識が不可欠である。また、規格によってある程度標準化・抽象化されているとはいえ、いずれもデバイスとの通信を行なうローレベルのAPIを使いこなさなければならないなど、通常の C/C++ や Fortran を用いたソフトウェア開発とは次元の異なる難しさがあり、導入のハードルが高い。特に OpenCL と DirectCompute はハードウェアに共通にアクセスできる API を規定しているだけであり、CUDAよりもさらにローレベルの抽象度である。この点に関しては、アクセラレーターの存在を抽象化し、従来のCPUベース並列プログラミング用の共通規格 OpenMP に近い高レベルプログラミング環境を提供する OpenACC や C++ AMP といった規格も徐々に整備されつつある。
CPU上で動作するプログラムは組み込み環境を除き、ライブラリも含めて高レベルに洗練された開発環境が整っていることが多い。例えばC++、Java、C#言語などの代表的な高級言語では、単純な連続メモリの配列構造だけでなく、リンクリスト・二分探索木・ハッシュテーブルといった基本的なデータ構造はプログラミング言語標準ライブラリで提供されていることがほとんどだが、GPUプログラミングの場合は高速に処理できないという理由から基本的には配列構造しか用意されていない。フォトンマッピング手法の開発者であるWann Jensen博士によると、複雑なデータ構造をGPU上で扱おうとするとCPUよりもはるかに困難となる場合が多いと評されている。他にも、GPUプログラミング言語であるHLSL、GLSL、およびOpenCL CではC++テンプレートのようなジェネリックプログラミング機能がサポートされないため、生産性が低い。なおBLASやFFTに関しては、NVIDIAによるCUDA実装のcuBLASやcuFFT、およびAMDによるOpenCL実装のclMath (clBLAS, clFFT) が存在する。そのほか、二分探索、ソート、リダクション、スキャンといったよく使われるアルゴリズムに関しては、NVIDIAによるCUDA実装のC++テンプレートベース並列アルゴリズムライブラリThrustや、AMDによるOpenCL/C++ AMP実装の同等ライブラリBoltが存在するが、両者に互換性はない。
また、GPUで演算した結果をCPUで読み出して利用する場合、従来アーキテクチャではGPUメモリからCPUメモリへのデータ転送が必要となる。その逆もまた然りである。こうしたCPU-GPU間のメモリ転送にかかる処理時間およびプログラミング上の手間が、性能のボトルネックやソフトウェア開発の難しさにつながるという問題も抱えている。これは物理的にメモリが分離されているディスクリートGPUとCPUによる構成だけでなく、従来型のオンボードグラフィックスやCPU内蔵GPUといった、物理メモリを共有する構成においても同様である。CUDAやOpenCLにはソフトウェア（ドライバー）レベルでこの転送の手間を解決する仕組みとして統合メモリ (unified memory) 機能や共有仮想メモリ (shared virtual memory) 機能が用意されてはいるが、あくまでメモリ空間のアドレッシングを仮想化して転送処理を自動化するだけの仕組みであり、アプリケーションプログラマーが明示的に転送処理を記述してチューニング・最適化する場合と比べてパフォーマンス上の問題もある。この点に関しては、AMDが推進しているHSA (Heterogeneous System Architecture) におけるhUMA (heterogeneous Uniform Memory Access) といった解決策が模索されている。
GPGPUプログラムの移植性に関しては、CUDAはNVIDIAハードウェア専用であり、また DirectCompute (DirectX) はMicrosoftプラットフォーム（Microsoft Windows、Xbox Oneなど）専用という制約がある。一方でOpenCLは、GPUだけでなく対応するあらゆるハードウェア・あらゆるプラットフォームへ展開できる高い移植性を持っているが、性能に関するポータビリティは必ずしも確保・保証されず、場合によってはデバイスやチップごとにコードをチューニングする必要がある。

実用ソフトウェアの登場

GPGPU技術の話題は、コンピュータ（特に資源やスペースの制約が強いパーソナルコンピュータ）の進化において2000年代中盤までのトレンドであり課題であった。しかし、デモンストレーションばかりが先行し、実際に活用できるソフトウェアが発売されることはなかった。そもそも、CUDAやOpenCLなどの汎用APIや、それらに対応するDirectX 10世代の統合型シェーダーアーキテクチャGPUが出現するまでは、GPGPU開発環境は制約の強いリアルタイムグラフィックス向けのAPIやシェーディング言語を直接利用したものか、もしくは研究機関が独自開発した固有のプログラミング言語基盤であり、ハードルも高く、決して開発効率や再利用性が良いとは言えなかった 。
2008年秋から、S3がGPUを利用したGPGPU用写真修正ソフトウェア「S3FotoPro」を発表、また動画編集加工ソフトでは動画エンコードソフトの代表格であるTMPGEncがCUDAに対応したことを皮切りに、CyberlinkのPowerDirector 7がCUDAとATI Streamに対応した。さらに、2009年にはSuper LoiLoScope (Pixel Shader 2.0を活用) が発売、CyberlinkがMediaShow Espresso (CUDAとATI Streamに対応) を発売している。GPGPUを利用した無料で利用可能な動画エンコードソフトとして、AMDのATI AVIVO (完全無料) やNvidiaのBadaboom (30日間無料体験版) 、MediacoderのCUDAエンコーダが挙げられる。
米Adobe社はCreative Suite 4 (CS4) の一部製品においてCUDAベースのGPUアクセラレーションをサポートしていたが、2010年5月28日に発売したCreative Suite 5 (CS5) においてGPGPUを正式にサポートした。CS5はOpenCLベースで開発されており、ほとんどすべての機能においてGPGPUによる演算を行うことができる。本来GPUは画像処理を得意とするため、画像処理を主体とする同社のアプリケーションへの適性は高い。また、After Effects CCでは、レイトレーシングエンジンにNVIDIA OptiXを採用している。その他にも、V-Rayなど、レイトレーシングのアクセラレータとしてGPUを活用しているレンダラーが存在する。AMDもOpenCLベースのレイトレーシングエンジンとして、Radeon ProRender (旧称AMD FireRender) を開発・公開している  。
オープンソースの統合型3DCG作成ソフトウェアBlenderでは、GIレンダリングエンジンであるCyclesにおいてNVIDIA CUDAによるGPUレンダリングが可能となっている。なお、バージョン2.6時点ではOpenCLによるGPUレンダリングも試験的に実装が進められている。また、Autodesk 3ds Maxサブスクリプションなどに搭載されている物理ベースのGIレンダリングエンジンであるNVIDIA Irayでは、CUDAベースのGPUアクセラレーションが行なわれる  。
その他、ネットワーク上の仮想通貨ビットコインの採掘処理にもGPUが使われている。
倍精度浮動小数点数への対応も進みつつあり、中堅クラスのスーパーコンピュータの演算装置としても普及しつつある。
このように、学術・研究目的や産業用途以外にも、一般的なプロダクション向け・コンシューマー向けに関してもGPGPU技術を利用したソフトウェアが続々と登場しており、ようやくGPGPUを本格的に活用できる環境が整ってきたといえる。しかし、万能に処理をこなすCPUと比較して、GPUはピーキーな特性を持ち、ソフトウェア開発においてはパイプライン処理や並列計算等の知識だけでなく、ハードウェア仕様およびAPIの知識も必要になるため、未だにGPGPU活用のノウハウが一般化したとは言い難い。