ogochan
最近の強めのSoC、シングルボードコンピュータ(SBC)に使われるようなSoCには「NPU(Neural network Processing Unit)」なるものが搭載されています。
宣伝文句を読むといかにもパワーがあって人工知能に有効そうに見えるのですが、果してそうでしょうか?
いろいろ試したり調べたりしたことについて書いておきます。
はじめに
「人工知能」が実用になる側面が見えて来て、いろんなところで使われ始めています。前世代人工知能(五世代コンピュータとか)の頃の「人工知能」と比較すれば、隔世の感があります。あの頃は川崎の某所に... 昔話はなしってことで。あの頃と比べると、本当に実用になって来ているなと感じます。
それに連れて、いろんな問題がはっきりして来ていて、一番大きな問題は
演算量が多過ぎる
ということではないでしょうか。「あの頃」と比べるとプロセッサの速度は何桁も速くなっているのですが、結局計算速度とかメモリで悩んでいるというのは面白いと言うか滑稽にすら感じます。
それに対応して「コプロセッサ」というアプローチが取られるようになりました。早くには「GPU」なんてもので計算力やメモリ量を嵩上げするのが流行って、今も続いています。ただし、計算力やメモリ量が嵩上げされることにも増して消費電力や費用まで嵩上げされてしまい、結局一般には手の届かないものになってしまいます。幸いにして「あの頃」と違って今はインターネットなんてものがあってクラウドサービスが廉価に使えたりするので、かろうじて天上界のものではなくなってくれています。五世代コンピュータの頃は専用ハードウェアが買えないと勉強すら出来なかったことを思えば、これもまた幸いなことですね。
「人工知能」がさらに一般的になるに連れ、「コプロセッサ」もいろいろ改良されて、スマホに使われるようなSoCにも入るようになりました。消費電力に問題も、様々な工夫で許容範囲に納められているので、気軽にスマホアプリでも使えるようになって、スマホ用OS(iOSとかAndroidとか)にはAPIも用意されるようになりました。このコプロセッサがいわゆる「NPU」です。
SBCはスマホのSoCの流用で作られることが多いので、結果的にSBCにもNPUが搭載されるようになりました。また、スマホ等と直接関係がない組み込み用のCPUにも、NPUが搭載されることが増えました。
NPUの例
SBCで使われるSoCに入っているNPUには大きく分けて以下の3種類あると言えます。
- GPUの延長にあるもの
- 主にCNNを想定したもの
- DSPの延長にあるもの
です。
GPUの延長にあるものの代表は、NVIDIAのJetsonに搭載されているものですね。中身はパソコン以上の機器で使われているGPUと同じです。いわゆるGPUと違うのは、グラフィックのためのものとして搭載されていないということでしょうか。違いと言えばその程度で、汎用演算が可能です。
「CNN用と思われるNPU」は、主にスマホ用のSoCに入っているものです。軽いハードウェアの割に凄い速度が出るように書かれています。RK3588(Orange Pi 5)で6TOPSとか書かれていますね。
DSPの延長にあるものは、組み込み用SoCにあります。STM32に搭載されているNPUはここに分類して良いと思います。「今時の人工知能の計算」は結局のところ一番プリミティブなレイヤでは「大量の積和演算」なので、積和演算専用プロセッサとも言えるDSPが使えない理由はないですね。昔、「ニューロコンピュータ」とか言われていた時代にはDSPをコプロセッサとして使っていた例が少なからずあります。「じゃあそれで十分じゃないの?」という話もあるのですが、メモリの制約上処理がメインメモリの上で行われるために、メモリバンド幅が広く取れないという問題があります。計算速いだけではパフォーマンスは出ないのです。
雑に3つの例を挙げましたが、スマホ用SoCは二番目のものです。以下で「NPU」と言えば、特に何か説明をしない限りこれを指すものと思って下さい。
NPUの特性
スマホのSoCに入っているNPUは基本的には「スマホのアプリのため」です。
スマホで期待されるものとしては、主には画像の処理です。具体的には、
- 画像を認識して何かを行う
- 画像を綺麗にする
- 背景や被写体の差し替える
といったことです。これ以上の処理(音声認識とかチャットとか)となると、クラウドにデータを送ってやるものが多いようです。
こういった処理で求められるのは、主には「畳み込みニューラルネットワーク(CNN)」です。ですから、スマホのSoCのNPUは主にこのための処理が強化されています。
また、NPUで行う処理は基本的に「推論」です。そして、推論の演算はほとんど量子化されていて、FP32(32bit浮動小数点)の演算を行うことはあまりありません。調べた範囲だと、INT16とかINT8、INT4といった演算が多いようです。こういった演算が速くなるように設計されているわけです。なので、速度を表現する時もGPUの宣伝で使われるTFLOPSという単位ではなくTOPSになっているわけですね。量子化が成功して実用になっていれば、TFLOPS = TOPSになりますが、それはあくまでも量子化された範囲だということです。
「学習」のためにはいろんな計算の都合上、浮動小数点の演算が必要になります。最近はQLoRAというような「量子化された状態で追加に学習する」という手法が出て来ていますが、わざわざ言葉がある程度には特別なものです。どのような結果をもたらすかは、今のところは未知数なところが少なからずあります。そういった事情もあって、NPUは学習にはあまり向いていません。
まとめてしまえば、NPUは
CNNでの推論の高速化
のためめのものであって、汎用のものではないということになります。
NPUの問題点
NPUはCNNの推論のためのものだという話をしましたが、本質的でないにしろ他の大きな問題があります。それは、
仕様がほとんど公開されていない
ということです。
NPU
-
- 6TOPs @int8
- Support int4/int8/FP16/BF16/TF32
- Support deep larning frameworks: TensorFlow, Caffe, Tflite, Pytorch, Onnx NN, Android NN, etc
とか書いてあるのですが、実のところこれらのフレームワークが使えるわけではありません。ただ単にプロプラなモデル変換を通じてモデルが変換可能だというだけです。ですから、「これでPyTorchの処理が高速化されるぜ」というようなことはありません。(運良く)モデル変換ができれば使えますよという意味に過ぎません。
hackerとしては「なければ作ればいいじゃないか」と思ってそれ用のコードを書きたくなりますが、NPUの中身についてはほとんど情報がありません。データシートを見てもAPIの使い方は書いてありますが、それ以上のことはありません。また、BLASを対応させようというようなことを考えて、せめてプリミティブな演算だけでも使えないかと調べても、「matrixの乗算」くらいしか情報がありません。それ以外の情報はありませんので、せいぜいmatrixの乗算が高速化できるだけです。最大限成功しても、前掲の「DSPの延長にあるもの」でしかありません。
Rockchipが公開する情報やコードのどれを見ても、公開されていること以上のことは出来ません。以前Useful Transformerについて書きましたが、あれは本当に頑張っているものです。それでも、matrixの乗算のためにNPUを使っているだけです。使い方がわからないのでしょうがありません。
さらに言えば、メモリは大きく制限されています。RK3588は結構自由度が高いように思えますが、それでもNPUからはせいぜい1GB弱程度のメモリを使えるに過ぎません。
このように、NPUが載っていても、汎用目的に使う道は事実上閉ざされています。ベンダー公式のモデルをロードして使うくらいしか使い道はありません。
また、ここではRK3588についての話として書きましたが、この事情は他のNPUもだいたい同じです。ベンダーの作ったモデルの範囲で使えるのがせいぜいで、運が良ければモデル変換したものが使えるかも知れないという程度です。
まとめ
結論から先に書くと、NPUはAI全般に対しての機能はありません。また、ベンダーが「俺達のNPUはこれだけのフレームワークに対応してるぜ」と宣伝していても、
ほぼ嘘
と言っても言い過ぎではありません。それらのフレームワークが使えるわけではなくて、それらのフレームワークで作られたモデルが運が良ければ変換して使えるかも知れないという程度です。ベンダーはモデルを公開していますが、それを見る範囲だと「YOLO専用プロセッサ」と言っても、ちょっとしか言い過ぎじゃないです。つまり、今時流行りの「生成系AI」が気持ち良く動いたりするようなことはありません。ましてや、「AIの勉強のためにPyTorchを動かして」みたいな用途には使えません。それがしたければCPUでやらなければなりません。
そういったわけで、NPUは
- ベンダー提供のモデルを使う
- CNNのモデルをモデル変換して使う
- 人柱が頑張った成果を使う
という範囲のものでしかありません。この範囲で納まるものであれば加速されますが、そうでなければないのと同じです。あまり期待のできるものではありません。まぁYOLOとそのバリエーションだけは豊富にありますけどね。
なので、汎用目的で使いたいのであればJetsonを選んでおいた方が無難だろうと思います。その結果をスマホ用SoCを使ったSBCで展開して行くことは、あるいは可能かも知れませんが。
PS.
とは言え、最近このようなものが出ました。
Rockchip NPU update 2: MobileNetV1 is done
RK3588のNPUを動かすオープンソースなライブラリです。
上に書いたように汎用性は微妙ですが、もうちょっとマシな状況にはなるようです。