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