簡単に言えば,Electronic Arts(以下,EA)の独自開発ゲームエンジン「Frostbite」で,16bit浮動小数点数(FP16)を徹底活用して性能を改善できるか検討したというものだ。
近代ゲームグラフィックスでは,頂点シェーダが扱うジオメトリ(幾何学)的な演算において,単精度と呼ばれる32bit浮動小数点数(FP32)を活用することが多い。一方で,ピクセルシェーダが扱うテクスチャを絡めたピクセル演算では,FP16がよく使われるものの,途中の演算はすべてFP32で行う実装になっている事例も少なくはない。
ではなぜ,このタイミングでEAは,FrostbiteエンジンのFP16最適化に取り組んだのか。それは,スマートフォンや携帯電話,Nintendo Switchのような,演算性能やメモリ性能が高くないハードウェアでは,FP16のほうが演算負荷やメモリ負荷を低く抑えられるので,FP32演算時よりも高い実効性能が引き出せる可能性があるからだ。
というわけで,開発チームによる取り組みと,その結果について見ていこう。
FP16とはなにか
本題に入る前に,浮動小数点とは何かのおさらいをしておきたい。
浮動小数点とは,「小数点が動く」仕組みを取り入れた,小数を含む実数の表現手段である。正負を表す符号ビット(Sign 0が正,1が負を表す)と,指数項(Exponent),仮数項(Mantissa)からなり,実際の値としては「(−1)^(符号)×仮数×2^(指数項)」で表す。
FP32とFP16の場合,内訳はこうなる。
- FP32:符号1bit,指数項8bit,仮数項23bit
- FP16:符号1bit,指数項5bit,仮数項10bit
仮数項は,仮数の最上位ビットが必ず「1」になるように決まるので,これを省略するのが仕様だ。そのため,実行桁数は「仮数の有効ビット数+1」となる。つまり,FP32の有効桁数は24bit,FP16の有効桁数は11bitだ。
FP16はもともと,映画「スター・ウォーズ」の監督で知られるGeorge Lucas氏により,同作の特撮部門として作られた映像制作スタジオ「Industrial Light&Magic」(ILM)が,1999年に提唱した「OpenEXR」が起源となっている。「現実世界と同等品質の情景をCGで表現するためには,3原色の赤緑青(RGB)の表現幅を,人の目における感度の上限である120dB相当にすべきだ」という根拠をもとに,ILMがFP16形式を提唱したのだ。2008年には,浮動小数点表記の標準規格である「IEEE754」の拡張仕様「IEEE754-2008」にて,FP16が正式に採用された。
こうした経緯で生まれたFP16のダイナミックレンジは,ちょうど120dBである。一方,FP32のダイナミックレンジは830dBもあり,オーバースペックなのだ。ちなみに,8bit整数は24dB,16bit整数は48dB,32bit整数は96dBである。
ゲームグラフィックスの世界では,DirectX 9世代GPUがハイダイナミックレンジ(HDR)レンダリングに対応したことで,2000年代初頭からゲーム業界でもOpenEXR相当のFP16が活用され初めた。今では,GPUがFP16を処理できるのは当たり前だ。さらに,GPUで汎用演算を行う「GPGPU」でもFP16が利用できるようになり,これが機械学習におあつらえ向きだったことから,AIの研究開発にGPGPU活用が盛んとなったのは,あまりにも有名な話である。
FP16の優位性。しかし,乗り越えるべき壁は高い
セッション冒頭にGriffin-Lira氏は,FP16の優位性と,FP16ならではの課題を上げた。
たとえば,FP16はFP32の半分の長さであるために,多くのGPUで,ひとつの32bitレジスタに2つのFP16を収納できることから,レジスタの利用効率が良くなる。演算器が32bitレジスタに2つのFP16をパックした形式で演算できれば,演算器の稼動率を上げやすくなるので,理論的にはFP32に対して2倍の演算性能が期待できるという理屈だ。
レジスタの利用効率が良いと,GPUが同時に実行できるスレッド数も多くなる。
また,演算結果をレジスタからメモリに書き出すときも,メモリ帯域幅の消費量がFP32の半分で済むというメリットもある。
もちろん,FP16にもデメリットはある。それは演算精度が低くなること。FP16は,ダイナミックレンジがFP32と比べて7分の1程度しかないので,巨大な絶対値を表現できない。またFP16は,FP32に対して有効桁数が少ないことから,多段演算で誤差が蓄積する傾向が強い。
とくに,多ポリゴンによるジオメトリ表現をFP16に丸め込んで行おうとすると,遠近が正確に表現できず,破綻しやすくなる。
そこで,Frosbiteエンジン開発チームは,エンジンが有する各種シェーダと,その実行を担当するGPUドライバ(ハードウェアドライバ)との間に,FP16化するための抽象化レイヤー「FP16 API」を挟み込む仕様を実装した。これを活用することで,Frostbiteエンジン上の各種シェーダをFP16化する実験を試みたそうだ。
ここでGriffin-Lira氏は,FrostbiteのFP16 APIの設計において,対象ハードウェア(GPU)を3種類にカテゴリー分けしたと述べる。つまり,3種類の対象ハードウェアを3段階のFP16対応レベルに分けて,FP16 APIを設計したということだ。
「Full FP16」は,FP16をフルサポートできるハードウェアだ。定数バッファも16bitで定義される。いうなれば,最も理想的なFP16化を期待できるハードウェアになる。
次の「Relaxed FP16」は,FP16の対応度が少々低めのハードウェアだ。具体的には,「この命令はFP16対応だが,この命令はFP32対応」というパターンだ。このハードウェアカテゴリーでは,定数バッファが32bit仕様となる。
最後の「Remapped FP16」は,FP16の対応度が著しく低いハードウェアだ。そのため,ソフトウェア的にFP16からFP32への変換コードが,適宜介入する仕様となる。こちらも定数バッファは32bit仕様だ。
実行結果に関しては,要素テストを開発して,対象ハードウェアがどの程度の品質で描画しているかを,視覚的にチェックできるようにしたという。
ところが,実際にさまざまなプラットフォーム(≒GPU)で結果を検証したところ,正しい動作をしていそうなプラットフォームにおいても,FP16化が性能向上につながったか否かは,まちまちだと分かったという。つまり,FP16にしても簡単には速くならないプラットフォームが,そこそこ存在したわけだ。
また,特定の処理系をFP16で行った場合の振る舞いが,プラットフォームごとに変わることもあったそうだ。
詳しく調べてみたところ,同じシェーダプログラムのソースコードをコンパイルしても,プラットフォームごとに異なる意味のFP16ネイティブ命令を出力することが分かったという。
こうした現象は,コンパイル後のシェーダプログラムが「SPIR-V」のような中間言語を経由する場合に,とくに発生しやすい。たとえば,シェーダプログラムのHLSLソースコードと,コンパイル後のSPIR-Vコード,そしてハードウェアレベルのネイティブ命令のそれぞれに表現力の違いがあった場合,FP16への単純な置き換えは,かなり困難となる。
こうした問題に対処するには,特定のコードをプラットフォームごとに,個別に最適化して対応しなければならない。こうした作業を,仮に手作業で対応するにしても,場合によっては,コード内のFP16〜FP32相互変換コードが増加してしまい,最終的にはFP16の軽さが意味を成さなくなってしまうこともあるようだ。
また,FP16の値をGPU側の32bitレジスタに2つ,64bitレジスタに4つ,128bitレジスタに8つ入れられて,さらに命令も,そうしたレジスタ内容に対して一括で演算できたとする。しかし,実際に演算器自体が内部で一括に演算できなければ意味がなく,FP16化がまったく意味をなさないこともあったようだ。
Griffin-Lira氏の肌感では,携帯端末向けGPUは,もともと「FP16を積極活用していこう」という思想で設計されているためか,FP16化の恩恵を得やすかったそうだ。それに対して,PCや据え置き型ゲーム機では,FP16化の恩恵は少なかったと振り返っていた。
PC向けGPUでは,FP16値を32bit以上のレジスタにパックする処理系自体が速くなかったり,GCN世代以前のRadeonでは,FP16とFP32のパフォーマンスがまったく変わらなかったりしたようだ。
FP16化によって生じる品質の低下
続いて,Griffin-Lira氏は,FP16化にともなって生じる品質の低下について説明した。
以下に示す2枚のスライドは,FP32ベースのピクセルシェーダによるライティングと,FP16ベースのピクセルシェーダによるライティング結果を示したものだ。
次のスライドは,各ピクセルの色に1%よりも大きな誤差が検出されたところを,赤い点で印を付けた画像となる。
開発者ではないゲーマーは,その違いに不自然さを感じることはないと思う。だが,「物理ベースレンダリング×HDRレンダリング」を行うと,誤差はそれなりに発生するということだ。
Griffin-Lira氏によれば,FP16とFP32とでは,法線ベクトルや曲げ法線ベクトルに比較的大きな誤差が生じやすい。そのため,これらのベクトルから算出した反射ベクトルをもとにするライティング結果は,FP32時とFP16時で違いが大きくなるそうだ。具体的には,先に示した相違点の拡大図のような,鏡面反射のライティング結果や鏡像表現に,大きな差が出やすいということである。
もっとも,そのゲーム映像を初めて見たときに,FP16化されたバージョンの品質に目くじらを立てる人は,ほとんどいないだろう。とくにスマートフォン向けゲームであれば,画面も小さいので気にならないのではないかと思う。
ただ,雑多なAndroid端末においては,GPUドライバソフトの完成度が低いことも多い。そのため,シェーダコードに問題がなくても,正体不明のライティング結果になることも多いとのこと。そうした端末での原因探しは,ほとんどあきらめるしかなかったようだ。
肝心の描画性能はどうなった?
最後にGriffin-Lira氏は,FP32を主体としたオリジナルのFrostbiteエンジンと,FP16化したFrostbiteエンジンで,テストシーンを描画した場合の描画性能比較を示した。プラットフォームは,PlayStation 5とiPhone 12だ。
テストシーンは,比較で使った宇宙船内シーンのトーンマッピング処理と,テンポラルアンチエイリアシング(TAA)処理,そしてタイルベースのライティング処理の3種類だ。実装は,すべてComputeShaderベースである点に注意してほしい。
結果は,PS5では期待したほどの性能向上は見られず,TAA処理では,FP32のほうが微妙に高速という逆転が起きてしまった。対してiPhone 12では,15〜23%程度の性能向上が見られ,FP16化で恩恵が得られることが分かる。
3種類のテストは,どれもスマートフォン向けGPUが不得意なメモリアクセスが比較的少なく,演算負荷の大小が結果に表れやすいものだ。つまりスマートフォン向けGPUでは,想定どおりにレジスタ利用効率が改善して,並列度も上がったということだろう。
FrostbiteエンジンのFP16化へのモチベーションはどこから?
Griffin-Lira氏は,FrostbiteエンジンのFP16化について,「まだ,すべてを試せたわけではない」と振り返っており,今後は,各GPUが持つ独特なベクトル命令の仕様に合わせた,より深い最適化に挑戦してみたいと述べていた。
それにしても,FrostbiteエンジンチームがFP16化に情熱を上げるのはどうしてなのだろうか。本稿のまとめとして,筆者なりの見解を述べておきたい。
Frostbiteエンジンは,かつての「Unreal Engine 3」と同様に,長らく「その時代のハイエンドプラットフォームに最適化されたゲームエンジン」であった。しかし,ここ最近は,「Unreal Engine 4」以降で開発されたゲームがPC,ゲーム機のみならず,スマートフォン向けにリリースされることも珍しくなくなってきた。
最近では,カプコンのハイエンドプラットフォーム向けとして開発されたゲームエンジン「RE ENGINE」ベースの「バイオハザード」シリーズや,Guerrilla Games製のゲームエンジンの「DECIMA」を使った「DEATH STRANDING」のようなリッチなゲームが,続々とiPhoneやiPadにリリースされている。今や,PCやPS5/4向けに作られたゲームが,スマートフォン向けに移植されることは,珍しくなくなってきている。
おそらく,EAのFrostbiteエンジンも,こうした流れに乗りたいという思惑があるのではないだろうか。
鄭重声明:本文の著作権は原作者に帰属します。記事の転載は情報の伝達のみを目的としており、投資の助言を構成するものではありません。もし侵害行為があれば、すぐにご連絡ください。修正または削除いたします。ありがとうございます。