2015年に開催された「GTC 2015」と2016年開催の「GTC 2016」でNVIDIAのTony Scudiero氏が「GPU MEMORY BOOTCAMP」と題するチュートリアルを行った。GPUは大量の演算器を搭載しているので、演算よりもメモリアクセスがネックになるケースが多い。ということで、いかにメモリを上手く使うのか、といった技術の解説を行った。このチュートリアルは2015年に1回目と2回目、2016年に3回目が行われているが、ここでは、先ず、第1回の内容を紹介する。

1. メモリアクセスあたりの演算回数

Boot Campは、新たな入隊者を一人前の兵士にする訓練のことで、新人のCUDAプログラマを一人前に育て上げるコースという意味で名付けられている。

プログラムの性能を上げる場合、第1に考えるのはアルゴリズムの最適化である。計算量をO( )で表わし、計算量のオーダを小さくすることを考えるが、抽象的なマシンで問題サイズを無限に大きくした場合の演算量が小さくなっても、論文を書くのには役に立つが、あまり、実益は無い。

このような評価法は、実際のハードウェア上でプログラムを実行する際に出てくる細かい問題を考慮していなかったり、データの局所性の影響を考慮していなかったりする。例えばNが小さい場合は、a>>bの場合は、a*O(N logN)アルゴリズムよりも、 b*O(logN2)の方が計算量が少ないことがあり得る。また、O(logN2)アルゴリズムは並列化可能であるが、O(N logN)アルゴリズムは並列化できないという場合は、O(logN2)の方が速いという場合もある。

一方、GPUを使う場合、メモリアクセスがネックになることが多いので、メモリアクセスの回数を数えることは有効である。

一般的には演算量を減らすアルゴリズムを考えるが、GPUの場合、アルゴリズムが並列化できるか、メモリアクセスの回数はどうか、アクセスに局所性があるかなどで、実際の性能は大きく左右される (この連載のすべての図は,GTC2015におけるScudiero氏の発表スライドのコピーである)

行列とベクトルの積(GEMV)と行列と行列の積(GEMM)を比較したのが次の表である。演算量はGEMVでは3N2-N、GEMMでは3N3-N2であり、GEMVの演算量はO(N2)、GEMMの演算量は(N3)となる。

一方、メモリアクセス回数は、GEMVは2N2+N、GEMMは3N2で、どちらもメモリアクセス回数はO(N2)である。メモリアクセスあたりの演算数はGEMVでは1であるのに対して、GEMMではO(N)となる。

一般的にメモリアクセスは演算よりも時間がかかる処理であり、演算とメモリアクスが同じオーダで発生するGEMVはメモリアクスがネックになる。一方、GEMMはNがある程度大きくなると演算がネックになる。

行列×ベクトル(GEMV)と行列×行列(GEMM)の演算とメモリアクセスの比較

このチュートリアルの時点でハイエンドの科学技術用GPUである「K40」と、スーパーコンピュータ(スパコン)などに用いられるCPU「Xeon E5-2690 v3」を単精度(SP)と倍精度(DP)で、ピーク性能を比較したのが次の表である。K40はSPのピーク演算性能は4,290GFlops、ピークメモリバンド幅は288GB/sである。この比率はおおよそ15Flop/Byteと計算される。

つまり、メモリから読みこんだデータ1バイトあたり15回以上のSP演算を行うプログラムでないと、メモリバンド幅がネックとなり、ピーク演算性能は実現できない。SPのデータは4バイトであるので、ワードあたりで数えると、メモリからの1ワードのデータを60回演算に使用しないと、ピーク演算性能は実現できないことになる。

一方、Xeon E5-2690 v3の場合は、SPのピーク演算性能は416GFlopsで、ピークメモリバンド幅は68GB/sである。演算/バイトの値は約6であり、メモリから読んだ1バイトあたり6回の演算を行えばメモリネックとはならない。しかし、ワードで考えると24演算となり、K40の60演算よりは少ないが、メモリネックにならないようにするには、メモリからのデータの使い廻し回数を大きくすることに注意する必要がある。

また、DPの場合は、K40ではワード(この場合は8バイト)当たりの演算数は約40回となり、Xeonの場合は24回となる。

なお、このメモリバンド幅はチップ外のDRAMメモリを読むバンド幅であり、データが全てキャッシュに入ってしまう場合は、そのキャッシュのメモリバンド幅で考える必要がある。しかし、データが巨大で一部しかキャッシュに入らない場合は、結局はDRAMのアクセスが必要となり、DRAMのバンド幅がネックになるという場合も多いので、Scudiero氏のチュートリアルではDRAMメモリのバンド幅で考えている。

K40 GPUとXeon E5-2690 v3のピーク演算性能とピークメモリバンド幅の比較。K40では1ワードのデータに40~60回の演算、Xeonでは24回の演算を行わないとメモリネックになる

ここではメモリバンド幅がネックになる演算回数を見積もったが、メモリバンド幅という点では、ステーションワゴン車に磁気テープを一杯詰め込んで運んでも高いメモリバンド幅は実現できる。これは、Linuxの前身とも言えるMinixを開発したことで有名なAndrew Tannenbaum(アンドリュー・タネンバウム)の言葉である。

ステーションワゴンに磁気テープを一杯詰め込んで運ぶ場合のバンド幅を過小評価してはいけない。Andrew Tannenbaum