最近小編收到一個(gè)客戶(hù)模型,其中使用了一個(gè)叫做PRelu的算子,想要運(yùn)行在RT170上。本來(lái)小編是信心滿(mǎn)滿(mǎn)的答應(yīng)客戶(hù)說(shuō):速度上放心,我們這主頻1GHz的CPU絕對(duì)沒(méi)問(wèn)題,包您滿(mǎn)意。沒(méi)想到跑分結(jié)果出爐直接給了小編沉重一擊。
直接依賴(lài)TFLm推理引擎的默認(rèn)實(shí)現(xiàn),PRelu算子的運(yùn)行時(shí)間竟然高達(dá)188ms。于是小編本著工程師本有的探索精神,決定迎難而上,徹底將它優(yōu)化一下。
所謂知己知彼,百戰(zhàn)不殆,首先我們來(lái)看一下什么叫做PRelu算子。
PRelu,看著好像特別的高大上,我們將其拆分來(lái)看,將其分成P+Relu,是不是瞬間就覺(jué)得熟悉了。沒(méi)錯(cuò),他實(shí)際上就是我們常用的Relu算子的變種。其中,P,是Parametric的縮寫(xiě),因此,所謂PRelu就是帶參數(shù)的Relu,只不過(guò),這里的參數(shù)實(shí)際上是可以被訓(xùn)練的,而非一個(gè)固定值。那么PRelu到底長(zhǎng)什么樣呢?小編馬上揭開(kāi)它的神秘面紗:
上圖就是PRelu的廬山真面目。i 表示不同的通道。alpha的個(gè)數(shù)是跟著通道走的,不過(guò)好消息是,各個(gè)通道之間參數(shù)是可以共享的,這樣看著清爽了不少。特殊的,如果我們配置H和W通道共享參數(shù),那么參數(shù)alpha就變成了類(lèi)似于bias的功能,逐通道共享一個(gè)參數(shù),因此,其shape = (1, 1, c);
為了對(duì)客戶(hù)負(fù)責(zé),外加能夠更加方便地進(jìn)行模型測(cè)試,小編首先收利用Keras手動(dòng)構(gòu)建一個(gè)具有PRelu算子的小巧模型。正所謂小巧而又不失優(yōu)雅,我們構(gòu)建模型如下所示:
這個(gè)小巧的模型本身具備了我們所常見(jiàn)的多個(gè)算子,例如Conv2D,MaxPool2D,F(xiàn)ullyConnect等,因此作為PRelu算子的測(cè)試模型也不至于顯得過(guò)于寒酸。
接下來(lái)和大家聊聊小編的調(diào)試經(jīng)歷:
第一步,就是要對(duì)TFLm的源碼進(jìn)行分析,了解為何其運(yùn)行緩慢。
PRelu算子實(shí)際上就是一個(gè)進(jìn)階版本的Relu算子,根據(jù)其輸入值的正負(fù)分別進(jìn)行計(jì)算,當(dāng)輸入為正是,就等于本身;當(dāng)輸入為負(fù)時(shí),將結(jié)果乘以一個(gè)系數(shù)alpha。看似非常簡(jiǎn)單的計(jì)算方式,為啥TFLm的參考實(shí)現(xiàn)能算的這么慢呢?口說(shuō)無(wú)憑,show me the code:
if (input_value >= 0) { output_value = MultiplyByQuantizedMultiplier( input_value, params.output_multiplier_1, params.output_shift_1); } else { auto alpha_index = SubscriptToIndex(desc2, b, y, x, c); const int32_t alpha_value = params.alpha_offset + alpha_data[alpha_index]; output_value = MultiplyByQuantizedMultiplier( input_value * alpha_value, params.output_multiplier_2, params.output_shift_2); }
看到這里,恰似風(fēng)平浪靜,的確是按照我們分析的那樣,按照輸入值的正負(fù)進(jìn)行計(jì)算。但是...細(xì)心的讀友可能發(fā)現(xiàn)了問(wèn)題:
1) 這里的alpha_data有個(gè)index,沒(méi)錯(cuò),這就是運(yùn)行慢的第一個(gè)原因。剛才說(shuō)過(guò),PRelu中的alpha參數(shù)是和通道數(shù)相關(guān)的,也就是說(shuō)每個(gè)通道都可以擁有自己的值,而且各通道之間還可以共享,因此并不能直接順序訪問(wèn),而是需要根據(jù)index進(jìn)行查找。
2) 這里多了一個(gè)叫做MultiplyByQuantizedMultiplier的函數(shù),為啥不直接計(jì)算?這是另一個(gè)原因。熟悉深度學(xué)習(xí)的伙伴們一定知道,MCU平臺(tái)常被稱(chēng)作:資源受限平臺(tái),這里的受限不僅體現(xiàn)在算力上,還有內(nèi)存空間上,相較于MPU那種動(dòng)輒幾個(gè)G的DDR的龐然大物,MCU上的內(nèi)存資源也是捉襟見(jiàn)肘。
想要將我們訓(xùn)練的模型部署運(yùn)行在MCU上,第一步就是對(duì)模型進(jìn)行量化操作,將浮點(diǎn)類(lèi)型的模型轉(zhuǎn)換為int8類(lèi)型的模型,這樣直接縮小到之前的1/4。同時(shí)由于量化后的模型采用int8表示,同時(shí)能夠借助于優(yōu)化后的運(yùn)行庫(kù)進(jìn)行加速。
這樣一來(lái),為了既想要使用int8模型帶來(lái)的遍歷,又保證模型精度,就需要對(duì)輸出結(jié)果進(jìn)行反量化表示,已達(dá)到使用int8類(lèi)型結(jié)果表達(dá)浮點(diǎn)數(shù)的效果。因此,就需要調(diào)用類(lèi)似MultiplyByQuantizedMultiplier這樣的函數(shù)進(jìn)行反量化處理。
基于以上兩點(diǎn),我們也就發(fā)現(xiàn)了算法本身所存在的慢速隱患,接下來(lái)的優(yōu)化操作也正是基于此展開(kāi)。
下一篇會(huì)繼續(xù)介紹通過(guò)內(nèi)存外加反量化函數(shù)的改造提升算法執(zhí)行速度。
-
mcu
+關(guān)注
關(guān)注
146文章
17984瀏覽量
367055 -
NXP
+關(guān)注
關(guān)注
61文章
1348瀏覽量
189407 -
恩智浦
+關(guān)注
關(guān)注
14文章
5981瀏覽量
116862 -
內(nèi)存
+關(guān)注
關(guān)注
8文章
3125瀏覽量
75274 -
算子
+關(guān)注
關(guān)注
0文章
16瀏覽量
7348
原文標(biāo)題:PRelu算子調(diào)優(yōu)經(jīng)歷-先行篇
文章出處:【微信號(hào):NXP_SMART_HARDWARE,微信公眾號(hào):恩智浦MCU加油站】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
PRelu算子調(diào)優(yōu)經(jīng)歷-函數(shù)優(yōu)化策略

Labview 調(diào)用Halcon 算子gen_rectangle1異常?
基于GFO算子的圖像增強(qiáng)算法如何去實(shí)現(xiàn)?
邊緣檢測(cè)的幾種微分算子
LOG算子在FPGA中的實(shí)現(xiàn)

基于修正的直覺(jué)模糊集成算子
canny算子的語(yǔ)法原理分析

HALCON機(jī)器視覺(jué)算子的詳細(xì)資料理解
Laplacian算子的FPGA實(shí)現(xiàn)方法

Sobel算子原理介紹與實(shí)現(xiàn)方法
自定義算子開(kāi)發(fā)

評(píng)論