一、模型使用和硬件加速原理#
前面我們知道了模型是一組數(shù)據(jù)結(jié)構(gòu)以及很多參數(shù), 最終以一個(gè)文件比如 kmodel 格式的文件的形式存在。
而這個(gè)模型要能在 MaixPy 的程序里面被使用, 首先需要程序能夠理解 kmodel 這個(gè)文件的格式, 并且支持模型里面的算法,這樣才能按照模型的描述將輸入經(jīng)過一些裂計(jì)算過程后得到輸出。
所以,重點(diǎn)就是支持模型里面的算法,稱 算子, 理論上,我們可以用軟件去實(shí)現(xiàn)這些算子, 就可以成功運(yùn)行模型了, 而執(zhí)行軟件的物理器件是 CPU , 神經(jīng)網(wǎng)絡(luò)模型的計(jì)算量很大,加上我們輸入的是圖片,圖片本身的數(shù)據(jù)量就挺龐大, 就算是 K210 400MHz 的主頻, 也無法滿足流暢的推算模型。
所以, 要么升級 CPU,但是成本太高, 要么做一個(gè)專用的硬件, 讓這個(gè)硬件專門去特定的算法,因?yàn)椴幌?CPU 一樣要做通用計(jì)算, 所以速度會非常快,在電腦上, 我們通常使用專用的圖像加速卡即 GPU 來加速圖形計(jì)算, 在 K210 上,這個(gè)專門的硬件叫做 KPU (Kendryte Proccess Unit),第一個(gè)單詞是公司名, 其實(shí)和其它芯片的 NPU (神經(jīng)網(wǎng)絡(luò)處理單元 Neural-network Processing Unit) 做的事情是一樣的。
在 MaixPy 里面,已經(jīng)集成了推導(dǎo)模型的代碼,同時(shí)使用了 KPU 進(jìn)行計(jì)算加速,使用時(shí)無需編寫很多代碼,只需要調(diào)用幾個(gè)函數(shù)即可快速運(yùn)行模型
二、關(guān)于 KPU#
雖然 KPU 是能夠加速模型運(yùn)算了, 但是由于成本、時(shí)間、功耗、體積、發(fā)熱、應(yīng)用領(lǐng)域定位等各種因素,它的能力并不能像專業(yè)領(lǐng)域的強(qiáng)力 NPU 一樣,包含了每一種算子,它只能處理一部分。
KPU 實(shí)現(xiàn)了 卷積、批歸一化、激活、池化 這 4 種基礎(chǔ)操作的硬件加速, 但是它們不能分開單獨(dú)使用,是一體的加速模塊。
所以, 在 KPU 上面推理模型, 以下要求(如果不需要訓(xùn)練和設(shè)計(jì)模型,暫時(shí)不需要仔細(xì)了解):
內(nèi)存限制
K210 有 6MB 通用 RAM 和 2MB KPU 專用 RAM。模型的輸入和輸出特征圖存儲在 2MB KPU RAM 中。權(quán)重和其他參數(shù)存儲在 6MB 通用 RAM 中。
哪些算子可以被 KPU 完全加速?
下面的約束需要全部滿足。
特征圖尺寸:輸入特征圖小于等于 320x240 (寬x高) 同時(shí)輸出特征圖大于等于 4x4 (寬x高),通道數(shù)在 1 到 1024。
Same 對稱 paddings (TensorFlow 在 stride=2 同時(shí)尺寸為偶數(shù)時(shí)使用非對稱 paddings)。
普通 Conv2D 和 DepthwiseConv2D,卷積核為 1x1 或 3x3,stride 為 1 或 2。
最大池化 MaxPool (2x2 或 4x4) 和 平均池化 AveragePool (2x2 或 4x4)。
任意逐元素激活函數(shù) (ReLU, ReLU6, LeakyRelu, Sigmoid...), KPU 不支持 PReLU。
哪些算子可以被 KPU 部分加速?
非對稱 paddings 或 valid paddings 卷積, nncase 會在其前后添加必要的 Pad 和 Crop(可理解為 邊框 與 裁切)。
普通 Conv2D 和 DepthwiseConv2D,卷積核為 1x1 或 3x3,但 stride 不是 1 或 2。 nncase 會把它分解為 KPUConv2D 和一個(gè) StridedSlice (可能還需要 Pad)。
MatMul 算子, nncase 會把它替換為一個(gè) Pad(到 4x4)+ KPUConv2D(1x1 卷積和) + Crop(到 1x1)。
TransposeConv2D 算子, nncase 會把它替換為一個(gè) SpaceToBatch + KPUConv2D + BatchToSpace。
以上說明來自這里
三、模型轉(zhuǎn)換#
前面說到, 模型其實(shí)就是一組數(shù)據(jù)結(jié)構(gòu)和參數(shù)數(shù)據(jù),不同的軟件只能識別特定格式的模型, KPU 只認(rèn).kmodel格式的模型, 一般用電腦訓(xùn)練的模型則不是, 比如 tensorflow 是 .h5 格式或者 .tflite 格式, 要給 KPU 使用, 必須經(jīng)過變成 kmodel 格式, 可以使用 nncase 這個(gè)工具來達(dá)到模型轉(zhuǎn)換的目的
如果你需要轉(zhuǎn)換模型, 具體使用方法請自行查看這個(gè)倉庫里面的介紹
四、kmodel V3 模型 和 V4 模型#
由于代碼更新, 在過程中產(chǎn)生了兩個(gè)大版本, V3 和 V4, 其中 V3 模型是指用 nncase v0.1.0 RC5 轉(zhuǎn)換出來的模型; V4模型指用 nncase v0.2.0 轉(zhuǎn)換出來的模型
兩者有一定的不同,所以現(xiàn)在兩者共存, V3 代碼量更少,占用內(nèi)存小,效率也高,但是支持的算子少; V4 支持的算子更多,但是都是軟件實(shí)現(xiàn)的,沒有硬件加速,內(nèi)存使用更多,所以各有所長。 MaixPy 的固件也可以選擇是否支持 V4。
五、MaixPy 中使用模型 kmodel#
加載 SD 卡 (TF 卡)中的模型
將模型放到 SD 卡, 然后加載
import KPU as kpu m = kpu.load("/sd/test.kmodel")
Copy
加載 Flash 中的模型
將模型下載到 Flash, 然后加載
import KPU as kpu model_addr_in_flash = 0x300000 m = kpu.load(model_addr_in_flash)
Copy
此處的 model_addr_in_flash 為模型在 Flash 中的偏移地址,模型可以通過 kflash.py 或者 kflash_gui 燒錄到 Flash 對應(yīng)的地址中
準(zhǔn)備輸入
一般情況下,我們會使用圖像作為輸入:
直接使用攝像頭采集的數(shù)據(jù)作為輸入:
img = sensor.snapshot()
Copy
這里 img 就可以直接作為輸入, 這里需要 注意: snapshot() 函數(shù)采集到圖片后,會將圖片數(shù)據(jù)放到兩個(gè)地方
(1) RGB565 內(nèi)存塊, 圖像以 RGB565 的形式存放在一塊內(nèi)存中,方便圖像處理的函數(shù)使用,注意在內(nèi)存中的排序是 [像素1 RGB, 像素2 RGB...]
(2) RGB888 內(nèi)存塊, 圖像以 R8G8B8 的形式存放在另一塊內(nèi)存中,注意在內(nèi)存中的排序是 [所有像素 R, 所有像素 G, 所有像素 B], 我們也稱之為 AI 內(nèi)存
其中,實(shí)際上作為 KPU 輸入的數(shù)據(jù)是 RGB888 區(qū)域, 這個(gè)在前面的文檔 MaixPy 圖像及常用操作 章節(jié)中有仔細(xì)講解過
從文件讀取,或者將修改過的攝像頭圖像作為輸入:
直接從攝像頭采集的圖像會自動(dòng)填充 RGB888 區(qū)域,但是我們使用圖像處理函數(shù)比如 image.resize() 時(shí),只會修改 RGB565,沒有修改 RGB888,因?yàn)橥瑫r(shí)修改兩處內(nèi)存需要耗費(fèi)大量時(shí)間,而 KPU 的輸入又是 RGB888 內(nèi)存塊, 所以在需要進(jìn)行 KPU 運(yùn)算時(shí), 需要同步(刷新)一下 RGB888 內(nèi)存塊, 使用 img.pix_to_ai() 來進(jìn)行同步,否則先前的修改將不會在 KPU 上生效。
比如:
img = image.Image("/sd/test.jpg") # 從 sd 卡讀取 test.jpg 作為輸入
img.pix_to_ai() # 同步 `RGB888` 內(nèi)存塊
Copy
img = sensor.snapshot() # 獲取攝像頭采集的數(shù)據(jù) img = img.resize(240, 240) # 使用圖像處理函數(shù)處理原圖像 img.pix_to_ai() # 同步 `RGB888` 內(nèi)存塊
Copy
前向運(yùn)行模型
前向運(yùn)行模型,也就是按照 輸入到輸出 的方向走一遍模型計(jì)算, 通過輸入得出輸出的值:
feature_map = kpu.forward(m, img)
Copy
這里得到了 feature_map, 是一個(gè)特征圖, 比如我們前面將的 小球 和 玩具 的分類,輸出特征圖是兩個(gè)節(jié)點(diǎn), 每個(gè)節(jié)點(diǎn)表示了是對應(yīng)物體的概率,我們將特征圖轉(zhuǎn)換為 list 對象:
p_list = feature_map[:] print(p_list)
Copy
就可以得到類似 [0.9, 0.1] 這樣的置信度結(jié)果了
六、KPU使用過程中的常見問題#
6.1. KPU能夠加載多大的模型?#
C 語言代碼運(yùn)行模型:
當(dāng) K210 運(yùn)行 C 代碼時(shí),能夠加載 < 6MB 左右的模型, 具體要看 C 代碼的內(nèi)容。
MaixPy 運(yùn)行模型:
* 當(dāng)運(yùn)行 MaixPy (minimum版本) 時(shí),能夠加載 4MB 左右的模型。 如果不使用攝像頭和 LCD, 最大可以加載 5MB 左右的模型(因?yàn)閿z像頭和 LCD 的緩沖區(qū)占用了很多內(nèi)存,但實(shí)際應(yīng)用也沒多大意義了)
* 當(dāng)運(yùn)行 MaixPy (完整版) 時(shí),能夠加載 2MB 左右的模型
* 另外也支持實(shí)時(shí)從 Flash 加載模型, 理論上只要單層使用內(nèi)存不超過 2MB, 整體模型可以無限大,只不過要犧牲一點(diǎn)運(yùn)算速度。 使用方法看這里。 如果對原理和實(shí)現(xiàn)感興趣,可以看這里
6.2. 報(bào)錯(cuò)"memory overflow"怎么辦?#
出現(xiàn)這個(gè)問題,根據(jù)前面講到過的 系統(tǒng)內(nèi)存管理 可知,一般有兩個(gè)可能性:
報(bào)錯(cuò)的地方跟系統(tǒng)堆無關(guān)系, 可能是 GC 內(nèi)存不夠?qū)е拢梢赃m當(dāng)增加 GC 的總內(nèi)存大小
由于模型過大引起的。可以依次嘗試如下解決方案:
更換 MaixPy mini 版本固件
進(jìn)行模型剪枝優(yōu)化
使用 kpu.load_flash 接口運(yùn)行時(shí)實(shí)時(shí)加載模型,只是執(zhí)行效率降低一點(diǎn)
如果內(nèi)存不足,且 kpu.load_flash 性能無法滿足, 那么你可能需要使用 C SDK 進(jìn)行開發(fā)。
6.3. 報(bào)錯(cuò)"load error,only support kmodel v3/v4"怎么辦?#
出現(xiàn)這個(gè)問題可以嘗試如下解決方案:
如果為加載 Flash 中的模型,請確保 flash offset 填寫正確,并保證和 MaixPy 固件的地址沒有沖突(模型在 Flash 中的地址太靠前,然后往 Flash 燒錄入固件時(shí), 固件大小超過了模型所在的起始地址, 導(dǎo)致模型被破壞)
如果是采用 nncase 0.2.0 進(jìn)行轉(zhuǎn)換的 kmodel V4,請嘗試采用 nncase 0.1.0 進(jìn)行轉(zhuǎn)換,從而生成 kmodel V3
6.4. 我想實(shí)現(xiàn)不同模型的選擇加載(例如按下按鈕運(yùn)行目標(biāo)分類,再次按下按鈕則運(yùn)行目標(biāo)檢測),應(yīng)該怎么寫程序?#
因?yàn)閮?nèi)部 RAM 有限,所以當(dāng)需要切換不同模型進(jìn)行 kpu.load(address) 前,請先執(zhí)行 kpu.deinit(k210model) 釋放之前模型占用的內(nèi)存,然后再加載新的模型。 也就是分時(shí)復(fù)用內(nèi)存
審核編輯 黃昊宇
-
AI
+關(guān)注
關(guān)注
91文章
39793瀏覽量
301381 -
RISC-V
+關(guān)注
關(guān)注
48文章
2886瀏覽量
52995 -
NPU
+關(guān)注
關(guān)注
2文章
373瀏覽量
21092 -
Micropython
+關(guān)注
關(guān)注
1文章
69瀏覽量
5834
發(fā)布評論請先 登錄
立創(chuàng)·梁山派開發(fā)板-21年電賽F題-送藥小車-K210的KPU數(shù)字識別訓(xùn)練
《DNK210使用指南 -CanMV版 V1.0》第二章 Kendryte K210簡介
串口中斷函數(shù)也需要調(diào)用k210底層的嗎?
移植Kendryte K210官方的SDK到nuttx系統(tǒng)的問題求解
關(guān)于k210使用C開發(fā)的問題
請問K210可以將驅(qū)動(dòng)LCD由并口8bit DVP方式轉(zhuǎn)為SPI方式嗎?
關(guān)于K210 KPU用途及FPU算力疑問
[測試貼]K210在maixpy固件下,復(fù)位需要多長時(shí)間?
K210 AI Accelerator適用于計(jì)算機(jī)視覺應(yīng)用
K210 AI加速器適用于計(jì)算機(jī)視覺應(yīng)用的緊湊型樹莓派HAT
K210上快速開發(fā)、低成本的MicroPython 解釋器MaixPy介紹
【01Studio x 嘉楠科技】CanMV K210 AI開發(fā)板全網(wǎng)首發(fā),千套開發(fā)板限時(shí)優(yōu)惠!
MaixPy 如何調(diào)用K210上的KPU為AI 加速?常用調(diào)用方式講解
評論