.net 怎么使用github_如何正确的使用ncnn的Extractor
最近的一篇工作里面需要頻繁的從網絡forward path中提取中間結果,因為ncnn比較好魔改,所以就選了ncnn來做工作本身的實現。同時也非常感謝nihui同學,中間獲得了nihui同學大量的幫助。這里稍微整理一下,如何正確在ncnn中取出結果。
(如果不知道什么是ncnn的話,點擊下面卡片,是一個超好用的端側inference框架!)
Github - Tencent/ncnn?github.com基本概念
這里需要理解ncnn的幾個重要的concept,方便后面解釋。
ncnn的layer對應著實際的計算node,比如說conv或者add。
需要注意的是,在轉換pytorch或者tf的模型到ncnn中時,除了對于基本graph的翻譯之外,ncnn還會插入額外的node,最常見也是最重要的就是split。split node本身的意義是將輸入的blob(也就是tensor)淺拷貝一份。ncnn不像tf或者torch,和tflite的結構類似,blob是producer和consumer是嚴格一一對應的,單一producer只支持單一consumer,不允許一個producer對應多個consumer。
2. Blob
這個概念在pytorch和tf中并不存在,所以可能廣大pythoner比較難以理解。blob的本質是構建一個producer-consumer對,其內容是tensor。在param中的表達是一個blob name,(也就是我們在input和extract中填寫的那個)。一個producer 只能對應一個consumer,如果要一對多,需要借助split layer來實行producer的拷貝。
3. Extractor
ncnn是將網絡的結構用blob鏈接構成一個DAG(有向無環圖),給定input以及extract之后,從extract向上查找,找到通往input的路徑,讓后再順序路徑forward下來。所以流程中對于output不必需要的node不會被計算,同時,如果extract一次之后,再重新extract,重復計算過的node也不會被計算。
那么,有些同學可能要問了,如果ncnn每一層都緩存,會不會占用內存特別大呢?實際上ncnn并不是每一層都會緩存,只有分叉的split,那么ncnn會在分叉的位置緩存blob。
CPU Runtime中的Extractor
在CPU上比較簡單,只需要簡單的構建一個生成器,給定輸入數據,再extract就行了。
ncnn這里的out_mat是網絡結構中的淺拷貝,并不需要實際搬運數據。如果存在packing或者使用了低精度的計算,比如說fp16/bf16,那么extractor默認也會還原成無packing的fp32狀態。
如果需要在網絡中抽取多次,同時這些還原的操作不是必要的,比如說我還需要把得到的結果feed進其他layer里處理,那么可以直接extract不經過還原的mat。
ncnn給定extract的flag為1,那么就會輸出不經過還原的mat了,實測還是可以節省幾個ms的。(mobilenetv2,抽10層的中間結果,高通驍龍855)
GPU Runtime中的Extractor
在GPU上,如果你不在意gpu到cpu上的緩存拷貝,那么可以完全參考cpu上的實現,那么這里主要介紹一下,如果我需要實現zero copy的提取gpu上的Vulkan Mat(VkMat)應該怎么做。
ncnn需要先新建一個vkCmd,這樣可以保證操作的都是同一個設備,之后使用extractor的重載,就可以直接得到GPU上的tensor了。
需要注意的是,雖然這樣不存在拷貝時間了,但是Host和Device(GPU)的Sync依舊需要一定的時間(幾百us到幾個毫秒),頻繁的extract還是會很耗時的。
大概就是這樣)下次有空講講怎么樣在程序中自己構建一個layer,并forward Mat或者vkMat。感謝nihui,小字母和大家的幫助qwq)
順路帶貨)Keras用戶也可以用ncnn啦!支持tf1或tf2導出的keras h5文件,如果遇到不能支持的layer,只要ncnn支持,開issue都會解決的qwq
https://github.com/MarsTechHAN/keras2ncnn?github.com總結
以上是生活随笔為你收集整理的.net 怎么使用github_如何正确的使用ncnn的Extractor的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: python3的float数精度_Pyt
- 下一篇: 外观模式和代理模式的联系和区别_java