ARMは、Project Trillium MLプラットフォームの次期ARMv8-AアーキテクチャにBFloat16のサポートを追加します。これは、ディープラーニングコミュニティを席巻しているこの新しいデータフォーマットの普及における新たな大きなマイルストーンとなります。この記事では、このフォーマットの起源と利点について詳しく説明します。
数値形式
当たり前のことのように思えるかもしれませんが、コンピュータチップをゼロから構築しようとすると、必ず遭遇する根本的な問題の一つが、数値をどのように表現するかです。整数の場合、解決策は至ってシンプルです。10進数に相当する2進数を使えばいいのです。(負数はハードウェアでの計算を容易にするために、もう少し複雑な仕組みが考案されているので、ここでは無視します。)しかし、無理数はもちろんのこと、有理数の場合はもう少し注意が必要です。
最善の方法は、コンピュータサイエンスで浮動小数点と呼ばれる(2進の)科学的表現を使用することです。科学的記数法では、数値は有理数(仮数部)として表され、その後にこの仮数部と、ある指数で累乗された基数の乗算が続きます。1つの注意点として、仮数部には小数点の前に1桁しか含まれないため、2進の科学的記数法の最初の桁は常に1になり、実際にはコンピュータによって保存されません。 1.11 * 2 1111の例を示します。その値は 1.75 * 2 15または 57,344 です。小数点の後の最初の桁は0.5、2番目の桁は0.25などを表すため、仮数部は1.75と評価されます。したがって、2進数の 1.101 は、10進数では 1.625 になります。
要約すると、このような数値には、符号、仮数部(仮数部自体は正または負の値をとる)、指数という3つの情報が含まれています。簡素化のため、IEEEはコンピュータ向けにこれらの浮動小数点数形式をいくつか標準化しており、その中で最も一般的に使用されているのはbinary32(またはFP32)とbinary64(またはFP64)です。数値は、数値を表すために使用される桁の総数を指し、精度が高いため、ほとんどの桁が仮数部に割り当てられます。これらは単精度(SP)および倍精度(DP)とも呼ばれます。前述のように、仮数部の最初の桁は常に1であるため、この形式には含まれません。
チップの性能について語る際、浮動小数点演算回数(FLOPS)という用語が用いられます。これは通常、単精度を指します。しかし、古典的なTOP500リストのような高性能コンピューティング(HPC)では、倍精度の性能が注目されます。しかし、モバイルグラフィックス、そして特に最近ではディープラーニングにおいて、半精度(FP16)も流行しています。Nvidiaはこのトレンドを早くから認識し(おそらく当時のモバイルへの意欲も後押ししたのでしょう)、2014年にMaxwellでFP32の2倍のスループット(FLOPS)で半精度のサポートを導入しました。これは数値形式が小さいため、精度と範囲は狭くなりますが、ディープニューラルネットワークにおいては、より高い性能と引き換えに実現可能なトレードオフであることが判明しました。
Bフロート16
もちろん、仮数部と指数部のビット分割方法は、原理的には自由に選択できます。指数部のビット数が多いほど、表現できる数値のダイナミックレンジ(大きい数値から小さい数値まで)が広くなりますが、仮数部のビット数が多いほど、表現の精度が向上します。通常は後者が好まれます。例えば、浮動小数点表現を用いて円周率を可能な限り正確に近似するには、仮数部にほとんどのビット数を割り当てる必要があります。
IEEE規格は、仮数部と指数部のビット間の除算を標準化するのに便利なだけでなく、丸め、オーバーフロー、アンダーフローなどの例外をハードウェア間で一貫して処理するのにも役立ちます。SPはビット数が2倍(16ビット多い)であるにもかかわらず、そのうち指数部に割り当てられたのは3ビットだけです。ただし、これにより最大値は約65,000から約10 38に大幅に増加します。FP16からFP32への移行により、マシン精度は約10,000倍向上します。下の図は、単精度形式と半精度形式、そして新しいbfloat16形式を示しています。
Tom's Hardware の最高のニュースと詳細なレビューをあなたの受信箱に直接お届けします。
Bfloat16は、この点、つまり仮数部と指数部の間のビット割り当て方法においてFP16と大きく異なります。本質的には、bfloat16はFP32と同じですが、16ビットに収めるために精度(仮数部)を大幅に削減しています。言い換えれば、FP32(のダイナミックレンジ)から仮数部(精度)の16ビットを削除したようなものです。つまり、FP16と比較すると、仮数部が3ビット減る代わりに指数部が3ビット増えていることになります。
ここで当然浮かぶ疑問は、FP16が既に存在するのに、なぜbfloat16をわざわざ使う必要があるのか、ということです。まず、bfloat16はFP32を切り捨てただけのものなので、FP32形式への切り替えや変換は非常に簡単です。また、FP16は確かにスループットを向上させますが、範囲が大幅に狭まっているため、メリットが必ずしもありません。そのため、モデルをFP16に適合させるには、せいぜい余分な時間がかかりますが、結果が劣る可能性も否定できません。FP32から仮数部16ビットを削除しても、FP32の動作に大きな変化は見られず、bfloat16はFP16のスループットの利点を備えた、FP32の代替品としてほぼ理想的であることが判明しました。
これだけではありません。FP16が支持される主な理由はハードウェアコストです。どちらも16ビット形式であることを考えると、意外かもしれませんが、これは驚くべきことです。Googleが最近のブログ記事で説明しているように、ハードウェア面積(トランジスタ数)は仮数部幅の2乗にほぼ比例します。つまり、仮数部ビットが3ビット少ない(10ビットから7ビットに減る)だけで、bfloat16乗算器は従来のFP16ユニットの約半分の面積を占めることになります。FP32乗算器と比較すると、サイズは8分の1に小さく、消費電力も同等に削減されます。逆に言えば、同じシリコン面積内で、より有用なハードウェアを配置することで、より高いパフォーマンスを実現できるということです。
最後に、低精度フォーマットに共通する利点として、メモリと帯域幅の節約が挙げられます。値がFP32の半分のスペースしか占有しないため、例えば16GBのメモリをbfloat16に変換すると、32GBのメモリ使用量にほぼ匹敵することになります。これにより、より深く、より幅広いモデルの学習が可能になります。さらに、メモリ使用量が小さいため、メモリ帯域幅が制限される演算の速度も向上します。
Google は、複数の Cloud TPU リファレンス モデルで bfloat16 混合精度を使用した場合、幾何平均トレーニング速度が 13.9% 向上したと報告しました。
Flexpointの敗北:広範な導入への道
Bfloat16は、考案元となったGoogle Brain研究グループにちなんで、正式名称はBrain Floating Point Format(略してBF16)です。Google AIシニアフェローのジェフ・ディーン氏が一連のTwitter投稿で説明したように、GoogleはTensorFlowの初期からこのフォーマットを使い始めていました。より具体的には、2017年にリリースされたTensor Processing Unit(TPU)の2番目のバージョンであるTPU v2以降、ハードウェアでサポートされていました。しかし、Googleがこのフォーマットについて本格的に公に語り始めたのは、2018年5月のGoogle I/O(26時頃)まででした。
また、2018年5月、インテルは初のAI DevConを開催し、28nm Lake Crestディープラーニングプロセッサのパフォーマンスデータを初めて提供し、16nmの後継としてSpring Crestと、2019年後半に発売予定のNervanaの最初の量産製品を発表しました。(インテルは推論チップの開発に取り組んでいることも初めて示唆しました。)
Lake Crestは、Intelが2016年秋にNervanaを買収した際に継承したニューラルネットワークプロセッサ(NNP)であり、買収から数ヶ月後には包括的なAI戦略を発表し、AI製品グループを設立しました。NervanaがLake Crestで謳ったイノベーションの一つは、再利用されたGPUではなく本格的なディープラーニングプロセッサであることに加え、演算密度の向上を目的としたFlexpoint(Intel FPGAのHyperFlexアーキテクチャとは別物)と呼ばれる新しい最適化された数値データフォーマットを採用した点です。
bfloat16とは異なり、Flexpointは、固定小数点(つまり整数)ハードウェアは浮動小数点ハードウェアよりもトランジスタ消費量(および消費電力)が少ないという洞察から考案されました。これはIntelが2017年の詳細なブログ記事で説明している通りです。ある表では、Intelは整数乗算器の面積コストが、同じビット数の浮動小数点乗算器の半分以下であることを示しました。あまり重要ではありませんが、加算の場合、この差はさらに大きくなります。整数加算器はビット数に比例して増加するのに対し、浮動小数点加算器は2乗して増加するため、面積に大きな差が生じます。
Flexpointの背後にある考え方は、整数演算をディープラーニングで活用できるようにすることです。Flexpointは実際にはテンソル数値形式です。Flexpointテンソルの要素は(16ビット)整数ですが、共有(5ビット)指数を持ちます。この指数の保存と通信はテンソル全体で分散できるため、指数のコストはごくわずかです。この形式は、完全にはflex16+5と表記されます。ただし、テンソル内の共通指数は完全に無料というわけではなく、指数管理の複雑さを伴います。そのため、NervanaはAutoflexと呼ばれる管理アルゴリズムを導入しました。Intelは、「厳密に言えば、これは単なる数値形式ではなく、整数テンソルを関連する適応型指数管理アルゴリズムでラップするデータ構造です」と結論付けています。
つまり、2017年頃には、32ビットトレーニングと同等の「数値パリティ」を提供しつつ、より効率的な16ビット形式を採用すると主張する、2つの競合する16ビットトレーニング手法が登場していました。Bfloat16は仮数ビットを指数ビットに置き換えることでFP16を改良し、Flexpointは整数演算(ただし指数管理のオーバーヘッドは若干)に移行することでFP16を改良しました。興味深いことに、flex16+5は16ビットの仮数部(独立した5ビットの指数部)を持つため、実際にはFP16(またはbfloat16)よりも精度が高くなります。
しかし、Intelが2018年のAI DevConでSpring Crestを正式に発表した頃には、Flexpointの概念はすべて消え去っていました。Nervanaの共同創業者でAI製品グループのSVPであるNaveen Rao氏は、代わりに同製品がbfloat16をサポートすると発表しました。数か月後、IntelのデータセンターグループのSVPであるNaveen Shenoy氏が、Intelはbfloat16に全面的に取り組み、同社のポートフォリオ全体に導入すると発表したことで、この発表はさらに強固なものとなり、Cooper Lakeは新しいDLBoost機能としてそれをサポートする最初のXeon CPUとなりました。2018年11月、IntelはIntelアーキテクチャにBF16ユニットを統合するための独自のbfloat16ハードウェア数値定義ホワイトペーパー(PDF)をリリースし、GoogleのBrain Floating Point Formatの正当性を明確に示しました。
インテルがなぜBF16に力を入れすぎたのかは依然として謎のままです。Flexpointがなぜ廃れてしまったのか、インテルはその理由を一切説明していません。インテルは、FP32からflex16+5への移行には追加のソフトウェアエンジニアリングは不要で、BF16と同様に容易に置き換え可能だと宣伝していました。もしかしたら、数値フォーマットをめぐる争いは割に合わないと判断し、BF16をディープラーニングの標準トレーニングフォーマットとして採用し、さらには推進することにしたのかもしれません。結局のところ、どちらの提案もFP16と比較して約50%の面積削減を謳っていました。
NNP-TプロセッサとXeonスケーラブルプロセッサは、BF16をサポートするIntel製品としてはおそらく唯一のものではないでしょう。Ice Lakeがこのフォーマットに対応するかどうかはまだ不明ですが、Intelの10nm Agilex FPGAもこのフォーマットをしっかりとサポートしています。
FlexpointではBF16よりもおそらく容易な、もう一つの疑問が残ります。なぜ16ビット(で止まる)なのか? 結局のところ、中程度の精度は推論において大きな進歩を遂げています。例えば、GoogleのTPUv1はINT8のみをサポートしていました。Intelは、低精度はいくつかの理由からトレーニングにおいて依然として課題であると回答しました。そのため、今のところはbfloat16がNvidia以外のハードウェアにおけるディープニューラルネットワークトレーニングの事実上の標準となるでしょう。ただし、トレーニング市場の大部分をNvidiaが占めていることは留意する必要があります。
ARM、BF16へのコミットメントを確認
ARMは先日、詳細なブログ記事で、同社もこの新フォーマットへの取り組みを表明しました。ARMが追加する命令は、ニューラルネットワークにおいて圧倒的に最も一般的な演算であるBF16乗算専用です。具体的には、SVE、AArch64 Neon、AArch32 Neon SIMD命令セットにそれぞれ4つの新命令が追加されます。(SVEはNeonを補完するARMv8拡張であり、ベクトル長を128ビットから2048ビットまで拡張できます。)これらの命令はBF16入力を受け付けますが、他のBF16実装と同様に、FP32に累積されます。1つの命令でBF16への変換が可能です。
ARMはまた、BF16の数値動作(丸め動作)に関するニュアンスについても説明しました。ARMは、異なるアーキテクチャやソフトウェアライブラリが丸め処理に若干異なるメカニズムを採用していること、そしてARM自身もFP32を厳密に追従しておらず、いくつかの簡略化を導入していることを指摘しました。しかしARMは、この簡略化によって、そのようなブロックの面積(およびそれに伴う消費電力)が35%以上削減されたと述べています。また、ARMは既存のFP32ブロックを再利用することで、わずかな面積増加でBF16のスループット(FP32と比較)を2倍にすることができると述べています。
新しい命令は、ARMのヘテロジニアス機械学習プログラム「Project Trillium」に属するものです。新しいBF16命令は、Armv8-A命令セットアーキテクチャの次期アップデートに含まれる予定です。まだ発表されていませんが、これはARMv8.5-Aとなる予定です。その後、パートナー各社のARMプロセッサに搭載される予定です。
まとめ
ディープラーニングの性能向上を追求する中で、ハードウェアとソフトウェアは演算ユニットのハードウェアサイズを削減し、スループットを向上させるために、より精度の低い数値形式へと移行してきました。FP16は値の範囲が狭いため課題を抱えていましたが、Googleは2017年にTPUv2で独自に考案したbfloat16形式に移行しました。これはFP32の優れた代替手段であり、FP16と比較してハードウェア面積を半分、FP32と比較して8倍削減するものです。その魅力は、FP32を単純に切り詰めただけである点にあります。
一方、IntelはNervana買収によりFlexpointを継承しました。Flexpointは、FP32モデルのパフォーマンスとFP16に比べて向上した演算密度というエンドユーザーにとってのメリットを、整数ハードウェアを採用しながらも同等に謳っていました。しかし、Intelはある時点でBF16をポートフォリオ全体に展開する方向に進みました。現在、NNP-Tアクセラレータ、Xeon Scalable(現時点ではCooper Lake)、そしてAgilex FPGAへの搭載が発表されています。
NVIDIAはこの件に関して発表を行っていませんが、ARMは先週、ARMv8-Aアーキテクチャの次期リビジョンで、複数のSVE命令とNeon命令を用いたbfloat16乗算をサポートすると発表しました。この発表により、2つの主要なCPUアーキテクチャは、現在、強化されたBF16サポートの導入を進めています。