Neural Networks API Introduction: Android APP背後是如何執行一個神經網路模型的?

Posted by John on 2020-11-15
Words 1.4k and Reading Time 5 Minutes
Viewed Times

前言

本篇是對於官方文檔Neural Networks API的中文閱讀筆記,內容是閱讀後透過自己的理解重新撰寫的,所以不全然是文檔的翻譯內容。

Android Neural Networks API

一個深度學習的應用分成兩個階段

  • training phase 訓練階段: 大部分的人都會在server上訓練好自家的深度學習模型(不會在手機上訓練,是想訓練多久…)
  • inference phase 推論階段: 將訓練好的模型拿來進行推論的應用,此時模型根據scenario就有可能放在手機、IOT device這些小型裝置,而不是將資料送到server上做再拿回來(因為這樣會有很高的latency)

為什麼要在device端做推論? 當然也可以把資料傳到server上推論完在下載回來,但這樣會衍生出一些問題:

  • Latency: 儘管server端的運算速度快很多,但資料傳送之間的I/O會造成很大的延遲,尤其對於一些real time的應用至關重要
  • Availability: 在沒有網路的地方就無法將資料上傳到server計算
  • Speed: 現在的行動設備上有越來越多支持深度學習運算的特化晶片,使得行動端的推論計算效率也大大提升,也逐漸能cover目前的edge ai application
  • Privacy: 對於一些有隱私議題的應用來說,將資料上傳到server並不是一個好選擇,此時在local端自己處理資料匯市比較好的解決方案
  • Cost: 使用行動端裝置自己處理推論,省掉了許多額外的成本(例如server的費用)

也因此,現在的趨勢都是在裝置端自己處理推論,靠著深度學習特化晶片來加速深度學習的運算。而為了在這些裝置上能夠更加有效的執行推論,許多相對應的議題也被提出,例如:

  • 模型壓縮及量化(Quantization)
  • 根據不同需求客製化的晶片:例如 APU、VPU、GPU、DSP…

對於手機端,為了使手機上的應用端可以更加方便的使用底層的不同裝置,Google在Android 8.1 (API level 27)後提供了ANN API(Android Neural Networks API)

ANN API使用C語言所撰寫,對於上層的深度學習框架(Tensorflow Lite, Caffe2…)提供了底層不同硬體資源的支持。

  • 例如你的手機晶片如果具備GPU、APU、或DSP等不同的硬體加速器,那就可以透過ANN API來選擇不同的底層執行你的模型

Understand the Neural Networks API runtime

NN Runtime是什麼? 他是一個Android service,用來與底層的設備溝通,並將上層應用端的操作透過NN API傳遞給底層的硬體去執行。

先來看一下NN runtime的架構圖,從圖中可以發現:

  • NN API基本上是給上層的深度學習框架來使用的,所以一般的APP並不能直接使用它
  • 透過NN API來控制ANN Runtime這個Service,Android背後透過ANN Runtime來控制底層要用那些硬體加速器執行操作
  • 而硬體必須要透過Android NN HAL(Hardware abstraction layer)向上提供自己的資訊,例如自己是誰、可以支援那些操作…

如此,ANN Runtime就可以知道上層模型有哪些指令,底層有哪些硬體,而這些指令又可以跑在那些硬體上,最後再去根據這些硬體適合哪些操作來分配他們。

  • 對於沒有特殊硬體加速器的設備,則會在CPU上執行

Use NN API to create a neural network model

這章節簡單的介紹如何用NN API寫出一個神經網路模型。

神經網路模型背後其實是一個計算圖(computational graph),所以我們必須先用NN API創造出一個對應的有向圖(directed graph),然後將對應的資料(weight, bias)指派給圖上的點。

NN API主要有4個概念:

  • Model: 一個神經網路的模型,包含了模型的相關操作(例如Conv, activation function…)
    • 創建Model的過程是一個synchronous operation,一旦創建成功就可以在不同thread和compilation之間使用
    • NN API中是一個ANeuralNetworksModel的instance
  • Compilation: 編譯器,負責將Model轉換成machine code
    • 創建Compilation的過程是一個synchronous operation,一旦創建成功就可以在不同thread和executions之間使用
    • 在NN API中是使用ANeuralNetworksCompilation instance
  • Memory: 是一個shared memory (memory mapped files,NN API可以使用該memory buffer與底層的driver有效率的進行數據存取。通常在創建一個model時,我們也必須為每個graph上的node創建對應的memory buffer,包含weight, input和output的tensor
    • 在NN API中是一個ANeuralNetworksMemory instance
  • Execution: 指定input、output,然後執行Model的Interface
    • 這是一個asynchronous operation,不同thread都可以執行相同的execution。一旦execution執行完畢,則所有thread會被release
    • 在NN API中是一個ANeuralNetworksExecution instance

了解這四個概念後,就不難理解他的Programming Flow了

  1. 透過ANeuralNetworksModel_create()創建模型,包含以下步驟:
    1. 指定graph中的operands,並可以將預訓練好的權重等data載入ANeuralNetworksMemory,然後在此時從ANeuralNetworksMemory讀進來
    2. 指定graph中的operations
    3. 指定input & output node
  2. 調用ANeuralNetworksCompilation_create()創建編譯器
  3. 調用ANeuralNetworksExecution_create()創建執行單元
  4. 調用ANeuralNetworksExecution_startCompute()呼叫底層開始執行,並等待執行結束(注意這裡是asynchronous operation,所以可以平行計算)

此外,一個編譯好的Compilation也可以給不同的Execution使用,只要給定不同的input以及create一個新的ANeuralNetworksExecution instance即可。

關於詳細的example code可以參考官方文檔學習。

References


>