Maxwellではアトミックメモリアクセスを改善
ヒストグラムを作る場合などでは、複数のコアで処理を行うと、2つ以上のコアが、同時に同じ区分のカウントを増加させることが起こるが、2つのコアが同じ値を読み、その値に+1して、メモリに書き戻すとカウントが誤ってしまう。このため、正しいカウントをするためにはメモリアクセスの排他制御を行う必要がある。Maxwellでは、このために使われるアトミックなメモリアクセスの性能を向上させている。
次の図は、画面内にどの明るさの画素が何個あるかというヒストグラムを作る処理で、グローバルメモリを使って処理を行う場合、シェアードメモリとグローバルメモリを使う場合、バンク競合の無いシェアードメモリとグローバルを使う場合のKeplerとMaxwellの実行時間を比較したグラフである。横軸は画素の値の偏りであり、偏りが大きく、同じアドレスをアクセスする比率が高くなると処理時間が増加している。
グローバルメモリだけを使う場合は、KeplerとMaxwellの実行時間はあまり違わず最大で数ms掛かっている。一方、シェアードメモリを使った場合は、Atomicsが高速化されたMaxwellでは、最悪の100%偏りのケースでも100μs程度の実行時間であり、Keplerと比べて大幅に速くなっている。
![]() |
ヒストグラムを作成する処理の実行時間の比較。グローバルメモリだけを使う場合は、KeplerとMaxwellの実行時間は大差ないが、共有メモリを使う場合は、Maxwellでは最悪の条件でも100μsとKeplerより大幅に高速になっている |
FP16ストレージをサポートしたCUDA7.5
CUDA7.5の主要な改善点は、16bitの半精度浮動小数点データ(FP16)がサポートされたこと、cuSPARSEという密行列と疎ベクトルの演算ライブラリが追加されたこと、命令レベルのプロファイリングができるようになったことであるという。
ディープラーニングなどの計算では、浮動小数点演算の精度はそれほど必要ではなく、16bitのFP16で良いと言われている。このようなケースでは半精度のFP16を使う方が、メモリ領域とメモリバンド幅の節約になる。これを行うのがFP16ストレージである。
しかし、現在のKeplerやMaxwell GPUは半精度浮動小数点の演算器を持っていないので、メモリから読んだFP16の数値はhalf2floatで32bitに変換して演算を行い、演算結果はfloat2halfで16bitのFP16に戻してメモリに格納することになる。
次の表は、5×5の畳み込みを行うフィルタを適用する処理をFP32のデータを使う場合と、FP16データを使う場合で比較したものである。FP32を使った場合の性能は1,180GFlopsである。この場合は実効メモリバンド幅が204GB/sとピークの64%に達しており、メモリバンド幅ネックで性能が抑えられていると考えられる。
一方、FP16データを使う場合は、実際の演算はFP32で行われ、FP16とFP32の変換処理が加わるのであるが、1,716GFlopsと45%の性能向上が見られる。この状態でもメモリバンド幅は164GB/sと余裕があり、こちらは演算ネックになっていると考えられる。この例のように、データの精度が半精度で良い場合で、かつ、メモリネックとなっている場合はFP16の使用で性能を改善することができる。
もちろん、これは最適ではなく、FP32演算器を2分割してFP16の演算を2つ並列に実行できるのが望ましいが、現在、これができるのは「Tegra X1 GPU」だけである。しかし、PascalになるとFP16演算がサポートされ、メインラインのGPUでFP16演算ができるようになる。
CUDA7.5では密行列×疎ベクトルの演算ライブラリのcuSPARSEがサポートされた。疎行列×密ベクトルは科学技術計算でも良く出てくるが、その逆の密行列×疎ベクトルは自然言語処理で使われるという。
性能チューニングに重要な命令レベルプロファイルをサポート
プログラムの実行が遅い場合は、プロファイルを取ってどこが遅いのかを調べるのであるが、KeplerまでのGPUでは、実行時間のプロファイルはカーネル単位でレポートされ、そのカーネルの中のどこで時間が掛かっているのかは分からなかった。単純で短いカーネルならば、これでも問題は無いが、大きなカーネルでは問題個所の特定が難しかった。
これに対して、Maxwell世代のGM200以降のGPUとCUDA7.5の組み合わせでは、GPUで実行されるカーネルプログラムの内部のGPU命令レベルでホットスポットが特定できるようになった。
GPUのネイティブアセンブラであるSASSという命令レベルで問題点が指摘されるが、仕様が非公開のSSASで言われても一般ユーザには分からないので、左側のウインドウでは、対応するCUDAステートメントも表示される。これでGPUのプロファイラもCPU並になったと言える。
CUDA7.5では、その他にも下記のような新機能や改善が追加されている。
まとめであるが、MaxwellはPascalのベースとなるアーキテクチャであり、Keplerより効率重視のアーキテクチャになっている。そして、高速なシェアードメモリAtomicsが実装されたことが主要な改善点である。
CUDA7.5 はFP16ストレージのサポート、cuSPARSEのサポート、命令プロファイリングのサポートが主要な改善点であると成瀬氏は総括した。