後藤弘茂のWeekly海外ニュース

第3世代のディープラーニングプロセッサはモデル圧縮技術が鍵

プルーニングは第3世代のディープラーニングプロセッサの重要技術

 ディープラーニングプロセッサは、まだ進化の途上にあり、人類進化にたとえるなら、現在は猿人から原人に進化したばかりの段階にある。ホモサピエンスレベルへの進化には、まだワンステップ以上が必要となる。

 2018年のプロセッサ学会「Hot Chips」のチュートリアルで、MIT(Massachusetts Institute of Technology)のSong Han氏(Assistant Professor, MIT EECS)は、ディープラーニングプロセッサの進化のスライドを示した。Han氏は、元スタンフォード大学でNVIDIAなどと共同で行なった「Deep Compression」の研究の中心人物だった。

2018年のプロセッサ学会Hot Chipsのチュートリアル「Accelerating Inference at the Edge」(S. Han, Hot Chips 2018)のスライド。スライド上ではAmpereが原人、Voltaが猿人となる。
Song Han氏(Assistant Professor, MIT EECS)

 Han氏のスライドで示された原人の項目の技術は「SW/HW Co-design: Compression before Acceleration」だ。つまり、ニューラルネットワークのモデル圧縮と、それに対応したハードウェアアーキテクチャが、第3世代のディープラーニングプロセッサの技術項目となっている。モデル圧縮技術は、猿人から原人への進化と同程度の重要なステップという認識だ。

 ディープラーニングのモデルの圧縮にはいくつか方法がある。NVIDIAがスタンフォード大学などと共同研究したDeep Compressionでは、「プルーニング(Pruning:刈り込み)」、「量子化(Quantization)」、「ウェイトシェアリング(Weight Sharing:重み共有)」、「ハフマン符号化(Huffman Coding)」が研究されていた。

 プルーニングでは重要度の低いパラメータを削除する。量子化では、たとえば32-bit浮動小数点から8-bit整数などにパラメータのビット数を下げる。ウェイトシェアリングでは、ウェイトを共有することで、ウェイトパラメータの量を減らす。プルーニングとウェイトシェアリングでパラメータの数を減らし、量子化でパラメータのビット数を減らし、パラメータの符号化でデータ圧縮を行なう。

 こうした圧縮技術によって、パラメータとそのデータ量を削減し、必要なメモリ量やメモリ帯域、演算量や演算精度を下げて、消費電力やチップの規模を小さくする。それも、ディープラーニングの処理精度を落とさずに。

 一連の圧縮技術のなかでもプルーニングはもっとも重要だ。それは、パラメータ数を劇的に減らすことができる可能性があるからだ。また、パラメータを減らすことで、メモリ量だけでなく演算量も減らすことができる。パラメータ数を10分の1やそれ以上に減らすと、その分、消費電力が減り性能が向上する。プロセッサ側からすると、アーキテクチャの対応だけで、性能を劇的に伸ばすことができる魅力的な技術だ。

トレーニングでスパース化してインファレンスで実行

 基本的な事項を抑えておくと、ニューラルネットワークには、トレーニング(学習)とインファレンス(推論)の2つのフェイズがある。トレーニングでは大量の学習データを使ってニューラルネットワークモデルに学習をさせる。インファレンスではトレーニング済みのニューラルネットワークで認識を行なう。

 たとえば、大量の動物の写真を使ったトレーニングで動物種を学習させたネットワークを作る。すると、インファレンスでは、ネコの写真を入力されると、ネコと推論する。プルーニングは、基本的にはインファレンスで効果を発揮するが、トレーニングでの最適化が必要となる。

ディープラーニングのトレーニングとインファレンスの2つのフェイズ
ディープラーニングのフェイズ
PDF版はこちら

 では、この2つのフェイズの間で、プルーニングはどうやって行なうのか。まず、トレーニングフェイズで、学習済みのフル接続のネットワークを作る。このときは、まだ、デンスネットワークだ。

 次に、学習済みのデンスネットワークをプルーニングして、重要度が低いウェイトやノードを削除する。そして、プルーニング済みのスパースネットワークを、さらに再トレーニングして、ネットワークを完成させる。再トレーニングを省くこともできるが、その場合は精度が低下する。

プルーニングの仕組み
PDF版はこちら

 一般的には、学習済みのネットワークのウェイトパラメータのうち、絶対値が小さい値を0値にする。0値化することで、ネットワークから削除できるようにする。ウェイトの分布を見ると、ほとんどの値が0近くに分布している。しかし、絶対値の大きなウェイトしか、モデル精度に寄与しない。絶対値の小さなパラメータを0に落としてもインファレンス精度に大きな影響が出ないとされる。また、ウェイトの絶対値の総和でチャネルごとプルーニングする手法もある。

ウェイトの分布。GTC 2020のセッション「S22085 Accelerating Sparsity in the NVIDIA Ampere Architecture」(J. Pool, et al., GTC 2020)
0値や0値に近いパラメータを格納や演算しないことでスピードアップすることがプルーニング

実際には0値化できるパラメータが多い

 これをパラメータのマトリックスとしてビジュアル化すると、下のスライドのようになる。ウェイトパラメータのうち正の値が赤、負の値が青、プルーニングされた0値が黒で示されている。左がデンスネットワークで、パラメータ群は赤か青の値を持っている。それに対して、一定の絶対値でプルーニングを行なったのが右の2つの図で、値が小さいパラメータは0値化され黒になっている。

スパースネットワークのビジュアル化。2018年のプロセッサ学会Hot Chipsのチュートリアル「Accelerating Inference at the Edge」(S. Han, Hot Chips 2018)

 上のスライドで黒が大半を占めることでわかるとおり、プルーニングしたスパースネットワークは、多くの0値パラメータを含んでいる。インデックスをつけて0値のパラメータを削除することで、パラメータデータを圧縮する。圧縮したプルーニング済みのスパースネットワークは、元のデンスネットワークより大幅にサイズが小さくなる。モデルサイズが小さくなるため、インファレンスを行なうときに効率的になる。

デンスネットワークからプルーニングによってスパースネットワークを作り、インデックスをつけて圧縮する
PDF版はこちら

 サイズが小さくなったネットワークモデルは、より小さなメモリに収まるため、メモリ量が少なくて済み、メモリからの読み出しも少なく、メモリアクセスの消費電力が下がる。また、演算量も減るため、演算の消費電力が下がるだけでなく、性能が上がり、インファレンスのレイテンシが短くなる。トレーニングでプルーニングを行なうことで、インファレンスがアクセラレートされる仕組みだ。ちなみに、プルーニングでトレーニングもアクセラレートするというアイデアもあるが、これは、まだ研究段階だ。

プルーニングへのハードウェア対応

 トレーニングでプルーニングを行なう段階では、ハードウェアの特殊な対応は必要とされていない。GPUなどの汎用のプロセッサでトレーニングして、ソフトウェア的にプルーニングでパラメータを間引くことができる。

 しかし、インファレンスフェイズは異なる。プルーニングの効果をインファレンス時に引き出すには、ハードウェアの対応が望ましい。とくにプルーニングの粒度が小さくなり、値のばらつきに規則性が少なくなると、ハードウェアが対応しないかぎり、プルーニングによる圧縮の効果を十分に活かすことができない。粒度が大きい場合は、ハードウェアの対応がなくてもいい。

 プルーニングのスパースネットワークへのハードウェア対応には、いくつかのステップがある。スパースにして圧縮したネットワークは、ハードウェアのサポートがない場合、メモリ上でデンスネットワークに展開してプロセッサに読み込まなければならない。

 しかし、メモリレベルでスパースに対応している場合、圧縮されたスパースネットワークをプロセッサのなかに直接読み込むことができる。その場合は、モデルに必要なメモリ量と、メモリ読み込み量が削減され、電力消費と必要メモリ量が抑えられる。

 場合によっては、オンチップのメモリに圧縮されたパラメータをすべて収めることも可能になる。メモリレベルだけの対応の場合は、読み込んだスパースネットワークは、プロセッサの内部で逐次に展開されて、削除されていた値は、0値としてデンスネットワークと同じように実行される。

スパースネットワークへのハードウェア対応のレベル
PDF版はこちら

 コンピュートレベルでスパースネットワークに対応する場合は、メモリでのサポートに加えて、読み込んだスパースのパラメータ群のうち、プルーニングで0値化されたパラメータの演算がスキップされる。無駄な演算がスキップされるため、省電力制御を行なえば電力消費が抑えられる。スキップするだけなので、演算ユニットがマトリックス演算(GEMM:General Matrix Multiply)に最適化されていても、演算時のハードウェアの制御は容易だ。

コンピュートレベルのスパースネットワーク対応で、0値のパラメータの演算がスキップされる例。「ENVISION: A 0.26-to-10 TOPS/W Subword-Parallel Dynamic-Voltage-Accuracy-Frequency-Scalable CNN Processor in 28nm FDSOI」(B. Moons, et al., ISSCC 2017)

 演算レベルでスパースネットワークに対応する場合は、さらに進んだサポートとなる。演算スパーシティ対応では、読み込んだ圧縮されたスパースパラメータは、そのまま演算ユニットアレイで実行される。圧縮されたネットワークでは、しきい値以下のパラメータは0値化されて削除されており、パラメータ数が減っている。そのため、実行する演算ユニットアレイ側に空きができる。

 そこで、圧縮されたスパースマトリックスをハードウェアで制御することで、演算ユニットアレイの空いた演算ユニットに、別なロウのパラメータの演算を割り当てる。空きユニットを効率よく使って、性能を引き上げる。演算を単純にスキップする場合と比べると、演算ユニットを無駄なく稼働させることができる。制御は複雑になるが、その分、性能と電力効率が向上する。

実際のプロセッサでのプルーニング対応

 プルーニングへのハードウェア対応自体は、すでにインファレンス専用のディープラーニングプロセッサの世界には浸透している。たとえば、Armのマシンラーニング(ML)専用プロセッサIP「Arm MLプロセッサ(Machine Learning Processor)」は、プルーニングにハードウェア対応している。NVIDIAが、SoC「Xavier」に組み込んだディープラーニングアクセラレータコア「NVDLA(NVIDIA Deep Learning Accelerator)」も同様だ。また、Centaur Technologyが発表した新しいx86 SoC「CHA」に内蔵されるディープラーニングアクセラレータ「Ncore」もメモリレベルだがスパースに対応する。

 インファレンスの研究チップを見ると、スパースネットワークへのハードウェア対応は、すでに一般的だ。スタンフォード大学やNVIDIAなどの「EIE(Efficient Inference Engine)」と「ESE(Efficient Speech Recognition Engine」、MIT(Massachusetts Institute of Technology)やNVIDIAなどの「SCNN」や「Eyeriss v2」、Princeton大学の「SPRING」、Michigan大学やNVIDIA、MITの「Stitch-X」、KAISTの「Centaur」、Toronto大学の「Cnvlutin」など、多数の研究が発表されている。企業ではNVIDIAが絡む研究が多い。

 ただし、NVIDIAの実際の商用製品であるAmpereアーキテクチャでのプルーニング対応は、インファレンス向けに最適化したディープラーニングプロセッサでの対応とは多少異なる。一言で言えば、インファレンス向けのプロセッサの研究チップは、リソースを投入してプルーニング効率を追求する傾向が強い。それに対して、NVIDIAのAmpereはプルーニングのためのリソースを慎重に抑えて、プルーニング効率は2倍までに留める。

 NVIDIAは、制御ロジックやインデクシングを複雑にすることで、汎用のプロッッサとしての、トレーニング性能やニューラルネットワーク以外の性能を削がないように気をつけている。その一方で、スパーシティへのハードウェア対応は、メモリやコンピュートレベルではなく、演算レベルのサポートへと踏み込んでおり、電力効率を高める。NVIDIAの対応は、汎用性の高いプロセッサでのプルーニング対応の今後を示すかもしれない。

重要となるプルーニングの粒度と構造

 プルーニングのハードウェア対応を考える場合に重要な要素は、スパースネットワークの粒度(Granularity)と構造(Structure)だ。粒度が大きく構造に規則性があれば、ハードウェアでの対応は容易になる。また、インデクシングのオーバーヘッドも小さくなり、その分、データ圧縮の比率が高まる。粒度が非常に大きく規則的な場合は、ハードウェアのサポートがなくても、スパースネットワークによって効率が上げられる。

プルーニングによるスパースネットワークの粒度と規則性。プルーニングの粒度はいくつかのタイプに分類できる。米スタンフォード大学(Stanford University)と、NVIDIA、中国Tsinghua Universityによる研究「Exploring the Regularity of Sparse Structure in Convolutional Neural Networks」(H. Mao, et al., NIPS 2017)
スパースネットワークで重要なファクタは規則性と粒度。「S22085 Accelerating Sparsity in the NVIDIA Ampere Architecture」(J. Pool, et al., GTC 2020)

 プルーニングで0値化するパラメータが規則性なく分布しているのが「Unstructured Sparsity(非構造化)」とか「Irregular sparsity(イレギュラー)」と呼ばれるスパースネットワークだ。それに対して、0値パラメータの分布が規則性を持つスパースネットワークを、「Structured Sparsity(構造化)」とか「Regular sparsity(レギュラー)」と呼ぶ。多くのケースでは、スパース性は非構造化となる。

非規則性のスパースネットワークの例。2018年のGTCのBaiduのセッション「Sparsity in Recurrent Neural Networks」より

 粒度では、0値が細かく分布しているスパースネットワークを「Fine-Grained Sparsity(細粒度)」や「0-D」と呼ぶ。粒度の小さなFine-Grained Sparsityの場合には、規則性としては基本は非構造(Unstructured)だが、構造化(Structured)にすることも可能だ。

 一方、粒度が大きい場合は基本的に規則性のあるStructured Sparsityで、粒度としては「Coarse-Grained Sparsity(粗粒度)」と総称するが、さまざまな粒度のレベルがある。0値がロウに並ぶ場合は「Vector Level Sparsity」や「1-D」と呼ばれる。

 ベクタではなく、一定のブロック単位の場合は「Block Sparsity」と呼ばれる。ブロックが大きく、マトリックスのすべてのパラメータが0値となる場合は「Kernel Level Sparsity」や「2-D」と呼ばれる。さらに大きな場合は「Filter Level Sparsity」、「Channel Sparsity」、「3-D」となる。CNNでフィルタやチャネルごとプルーニングされるようなケースだ。

ブロックレベルのスパーシティの例。2018年のGTCのBaiduのセッション「Sparsity in Recurrent Neural Networks」より
ブロックレベルのスパーシティの例
スパースネットワークは、ストラクチャと粒度で分けられる。2018年のプロセッサ学会Hot Chipsのチュートリアル「Accelerating Inference at the Edge」(S. Han, Hot Chips 2018)
粒度と構造はさまざまなトレードオフが絡む
プルーニングのタイプ。Ampere以前のNVIDIAは、GPUではハードウェアの対応の必要がない粗粒度(Coarse-Grained)プルーニングにフォーカスしていた

スパースネットワークのインデックスオーバーヘッド

 粒度と規則性は、スパースな行列を、どうやって圧縮するか、どうやってインデックスをつけるか、インデックスのオーバーヘッドがどの程度で、圧縮がどれだけ効率的か、という点にも大きく関係する。

 スパースネットワークの圧縮方法では「Compressed Sparse Row (CSR)」フォーマットなどが一般的だ。CSRではポインタでカラムインデックスの頭を指定して、カラムインデックスにロウのバリッドな値の位置を指定する。CSRなら、規則性のない非構造化(Unstructured)な、細粒度(Fine-Grained)のスパースマトリックスも格納できる。しかし、CSRをそのまま適用すると、インデックスのオーバーヘッドが非常に大きくなってしまう。

 とくに、圧縮したニューラルネットワークの場合、パラメータを量子化していると、値自体のビット数が小さいので、インデックスのビット分のオーバーヘッドが無視できない。また、プルーニングによる圧縮の比率が小さい場合もオーバーヘッドが大きくなる。たとえば、各要素が8-bitで、50%しか圧縮できない場合は、CSRなどのフォーマットではオーバーヘッドで圧縮が相殺されてしまう。そのため、モデル圧縮では、インデックスの仕組みも重要になる。

 下のGTCでのBaiduのスライドでは、一定のブロック単位の大きな粗粒度(Coarse-Grained)で、規則的な構造化(Structured)があれば、ブロックに合わせてオーバーヘッドが小さくした「Block Sparse Row (BSR)」などの圧縮フォーマットを使うことができるとしている。しかし、柔軟性を持たせて細粒度(Fine-Grained)のスパーシティのままでインデックスのオーバーヘッドを減らすためには、インデックスの持たせ方などに工夫が必要となる。これは、後述するNVIDIAのAmpereのプルーニングの重要なポイントとなっている。

スパースマトリックスの圧縮フォーマット。NVIDIA主催の2010年のGTC(GPU Technology Conference)のセッション「CUSPARSE Library」より
Compressed Sparse Row (CSR)のオーバーヘッド
Compressed Sparse Row (CSR)とBlock Sparse Row (BSR)。2018年のGTCのBaiduのセッション「Sparsity in Recurrent Neural Networks」より
Ampereのテンサーコアでのスパース対応ではインデックスの低減も重視

 プルーニングでは、ニューロンに当たるノード自体が削除されるケースがある。シナプス結合の重みをエミュレートしたウェイトの値が小さい場合に、プルーニングで0値化される。プルーニングによってシナプス結合が消えることは、ネットワーク上でのウェイトの0値化で表される。シナプスが散発的に刈り込まれる場合は、0値もマトリックス上でばらつく。

 しかし、大きな範囲でネットワークの消滅も発生する。たとえば、あるニューロンから次のニューロンへのアウトプットのシナプスがすべて消滅すると、そのニューロン自体が意味を持たなくなる。すると、消えたニューロンにつながる部分のサブネットワークをごそっと削ることが可能になる。人工ニューラルネットワークでは、これは一群のノードがプルーニングで削られることを意味する。マトリックス上の一定の範囲のウェイト(重み)が、すべて0値化されることになる。すると、ブロックのスパーシティが産まれる。

ノードも削除されてサブネットワークが消滅すると、Coarse-Grained Sparsityが産まれる