40
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Neural EngineでCore MLの処理が行われているか調べる方法

Last updated at Posted at 2020-04-21

Neural Engine(ニューラルエンジン)は、ニューラルネットワークの推論演算に特化した機構を持つことで、GPUよりもさらに高速な処理と消費電力の低下を両立するプロセッサ。A11 Bionicは毎秒6000億回、A12 Bionicではなんと毎秒5兆回の演算が可能とされている。

いうまでもなくCore MLのポテンシャルを最大限引き出す鍵となるのがこのNeural Engineなのだが、実はNeural Engineを制御するフレームワークやAPIは存在せず1、Appleは開発者向けの情報もほとんど何も出してない

残念ながら先のWWDC 2020でもその状況はあまり変わらなかった。

そんな中、書籍「Core ML Survival Guide」やOSS「CoreMLHelpers」でCore ML界隈で知らない人はいないMatthijs Hollemans氏が、GitHubでNeural Engine(ニューラルエンジン)のドキュメントのリポジトリを開設した。

氏がNeural Engineについて現状把握していることをまとめてくれたのが本リポジトリ。公開APIはない中で、プライベートフレームワークを利用してモデルの処理においてNeural Engineが使用されているか(あるいは使用されておらずCPUやGPUで処理されているか)を調べる方法や、そういった手法を用いてどういった種類のレイヤーはANEで処理されないか、といった非常に有益な情報が書かれている。本記事はそれを読んだメモ。

なお、頻出する**「ANE」はApple Neural Engineの略**。Neural Engineを扱うプライベートフレームワークのプレフィックスがこれになっているらしい。(確かにCore MLを使っているとANEなんとかは目にすることが度々あった)

ANEが使用されているかを調べる方法1

Tip: Press the Pause button in the debugger. If there's a thread H11ANEServicesThread then Core ML is using the Neural Engine.

Xcodeにつないでデバッグ中にポーズボタン(⏸)を押してスレッド一覧の中に"H11ANEServicesThread"という名前のスレッドがあれば、Core MLはNeural Engineを使用していると判断できる。(前述の通りANEはApple Neural Engineの略なので)

ANEが使用されているかを調べる方法2

シンボリック・ブレークポイント(symbolic breakpoint)を使用すると、CPU, GPU, ANEのうちどのプロセッサが使用されているかを知ることができる。

たとえば-[_ANEModel program]にシンボリック・ブレークポイントを張ってそこで止まれば、Core MLはANEを使用している。

ちなみに氏がドキュメントの中で何度も口を酸っぱくして書いてるのは、『だからといって、モデルの処理がすべてANEで処理されているとは限らない』ということ。一部のレイヤーだけANEで処理されていて、ほかはCPUやGPUで処理されているのかもしれない、という話。

またCore MLはEspressoというプライベートフレームワークで以下の3つの「エンジン」実装を使用しているとのこと。

  • ANE — Espresso::ANERuntimeEngine
  • GPU — Espresso::MPSEngine
  • CPU — Espresso::BNNSEngine

スタックトレースにこれらの名前があれば、現在どのプロセッサで処理されているかが判断できる。

また次のようにシンボリック・ブレークポイントを貼れば、CPU・GPUで処理が行われていることを発見できる。

  • Espresso::MPSEngine::context::__launch_kernel
  • Espresso::BNNSEngine::convolution_kernel::__launch

これでうまくいかなければ、以下のどちらかをブレークポイントに使用して、コードをステップ実行で追っていく。

  • Espresso::layer::__launch
  • Espresso::net::__forward

Espresso::elementwise_kernel_cpu::__launchのような関数で終われば、それはCPUで実行中というヒントとなる。

Espressoフレームワークのシンボルリストを取得する

Espressoフレームワークの他のシンボルも知りたければ、アプリ実行中にブレークポイントでアプリを止め、LLDBで次のコマンドを実行する。

(lldb) image list Espresso

これを実行するとEspress frameworkへのパスがprintされるので、そのパスを用いて次のようにdumpを実行する。

(lldb) image dump symtab 'put-the-path-here'

ANEがサポートしていないレイヤー

以下のタイプのレイヤーはANEでは処理されないことがわかっている。

  • RNN layers such as LSTM or GRU
  • dilated convolutions
  • upsampling layers
  • broadcastable and "ND" layers
  • custom layers(・・・ANEのAPIが公開されていないので当然)

各タイプの詳細はunsupported-layers.mdを参照のこと。(ここに書くとほとんどの内容を引用することになってしまうので。)

ちなみにすべてのレイヤータイプを試したわけではないので上記は網羅的なリストではないよとのこと。

coremltoolsでモデルを変換する際の注意点

上に挙がっている"Broadcastable layers"はANEで動作しないが、実はCore ML 2 の古いレイヤタイプと置き換えることができるらしい。そして古い方はANEで処理される。

しかしcoremltoolsでモデルを変換する際に、

minimum_ios_deployment_target='13'

と最新バージョンを指定すると、コンバータは新しい"Broadcastable layers"の方(ANEで処理されない方)を使用する傾向にあるらしい。

そういった場合にcoremltoolsを使って互換性のある古いバージョンのものと置き換えるといいよというTipsが紹介されている。

  • AddBroadcastableLayerAddLayer
  • MultiplyBroadcastableLayerMultiplyLayer or ScaleLayer or a linear Activation layer
  • ConcatNDConcat
  • and so on...

またSubtractBroadcastableLayerみたいに互換性のある古いバージョンのものがない場合はワークアラウンドとして別のレイヤーを使って同様のレイヤー機能を実装するといいよ的なことが書かれている。

その他

なんだかわからないが、重みを16ビット浮動小数点で保存したmlmodelファイルを使うと、32ビットモデルを使う場合よりも遅くなるらしい。GPUでは常に16ビットで扱うので個人的に最近は16ビットでいいやと思っていたのでこれは要注意。

  1. 唯一、「Neural Engineを使わない」という指定だけはできる。Neural Engineを使うという指定はできない。

40
19
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
40
19

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?