大家好,這期測評一款國產芯片(龍鷹一號siengine SE1000)。 主要側重其中的AI能力部分,圍繞著“如何在開發板上跑一個完整AI應用”這一主題來寫,前期根據官方提供的信息編譯簡單app,跟大家一起熟悉流程,知道如何配置開發環境、要用到哪些工具、操作流程是啥。后面接著就跑復雜一點的AI模型,講解軟件SDK中每個模塊(parser,quant,Gbuilder,simulator,profiler)的作用,逐代碼進行講解,以及如何DIY適配自己的需求等,so, let’s go!
1.硬件信息
龍鷹一號是一顆國產 7nm 智能座艙芯片,擁有 8 核 CPU 和 14 核 GPU,CPU算力能夠達到90~100K DMIPS,GPU算力900+GFLOPS,NPU算力達到8TOPS,對標的是高通的8155,從安兔兔跑分來看確實數據差不多,目前已知是搭載在吉利汽車旗下領克08(23年9月發布)車型上
定位是座艙芯片的“龍鷹一號”不僅會負責中控屏幕的計算與顯示,還會負責汽車儀表、功能屏幕甚至HUD的顯示。“龍鷹一號”支持輸入11路相機數據(遺憾的是截至目前,我仍然無法購買適配好的攝像頭進行應用開發),最高可支持7塊高清顯示屏顯示。 “龍鷹一號”會同時運行三個操作系統,分別是儀表的RTOS操作系統、HUD的Linux系統以及中控屏幕的安卓系統(目前提供的SDK默認是使用linux系統的);開發板是交給第三方的RADXA設計的,型號為SiRider S1,具體鏈接在這:https://docs.radxa.com/sirider/s1
雖然BOM中的車規級物料改成了普通物料,但是憑借其扎實的配置(16GB LPDDR5, 128G UFS)還是使得成本達到了千元+級別,比同類的開發板(RK3588、樹莓派)是要貴上三五百塊的,其實也合理,畢竟RK3588 4核A76,6TopsNPU,450Gops都稍弱于SiRider S1; 由于我們關注的是AI這一部分,因此固件編譯部分我們就不細說了,因為板子默認就刷了ubuntu的固件,開箱后插上HDMI顯示器,插入鼠標鍵盤就可直接開干了!
可以看到,ubuntu分配了4個大核A76+兩個小核A55;內容用了12GB,剩下的都分配給FreeRTos了。 如下圖SOC框架圖所示,主要的算力擔當以及視頻編解碼部分我認為足夠驚艷了,用來做NAS,軟路由,平板,電視盒子等應用都分分鐘ok的呀!外設部分同樣如此,接口最多的是UART,IIC跟SPI口,這些都是低速通用接口,因此想要做外設控制相關的應用的話,指定不是直接去快速控制了(比如FOC無刷電機,一般是需要3PWM接口/電機來進行控制, 而外設這里只提供了2個),而是通過低速接口間接驅動外設模塊了,比如開啟車門,開啟后備箱,開啟雨刮等非實時性要求高的應用,嗯,定位非常準確,所以我們做應用的時候盡量去選這三種接口(uart/iic/spi)的封裝較好的獨立模塊就好了。
2. AI知識小科普
好的,背景介紹完畢,那我們現在開始進入AI部分的內容吧!在這個大模型百家爭鳴的時代,我相信大家對AI都有一定的了解吧!
“AI就是人工智能呀!” “AI就是像人一樣跟你對話!” “AI就能將你的口頭描述轉化成實際的圖片!”
其實除了這些高大上的AI之外,你每天使用的打卡器(打工人必備)、刷臉機、以及監控攝像頭、麥克風等都含有AI技術在里面,你肯定好奇:
AI到底是怎么跑在具體的硬件設備上的呢?
假如我自己有個idea想要實現跑在具體硬件上,而不是通用PC上,我又該怎么做呢? 接下來我將為你一一解答。 類似于如何將大象塞入一個冰箱的問題,如何做一個AI應用的頂層流程是這樣的,
第一步,你得有個天才般或者腦殘般的想法,針對這個想法提出需求;
第二步,基于需求訓練一個模型出來;
第三步,將模型部署到具體的硬件上面去。
第一步跟第二步不是我們這次的主要學習內容,接下來簡單帶過。 AI模型是由智力絕頂的算法工程師們訓練出來的,俗稱煉丹。煉丹的丹爐各式各樣,煉丹界主流的就是Tensorflow跟Pytorch;
這顆丹內部由一堆的節點組成,節點本質就是一堆數據加處理這堆數據的計算方法,如下圖所示:
在個人PC上或者服務器上,想要讓整個模型跑起來是非常簡單的,因為,整個基建部分都被各大廠商(主要是英偉達)給搭建好了,我們直接使用就好了,這就好比我們要找個地方住一晚,最方便且安全的選擇就是去找現成的五星級酒店(缺點顯然是*),而不是去自己建房子然后住進去。而且,這些AI部署的相關服務是被全球開發者多年驗證過的,好用、方便。但是,一旦你想部署到某個具體的、特定的、不通用的硬件上時,之前那一套就完全沒用了,得“入鄉隨俗”,用與特定硬件相匹配的軟件棧。具體到我們這里,就是周易SDK這一套軟件棧,想把AI模型跑到板子上我們就得學習這一套SDK的使用、開發方法。
3. 周易SDK介紹
老規矩,還是先看下整體流程:首先,假設現在已經拿到一個訓練好的模型model了,比如model.onnx,
這個模型只能是tensoflow/pytorch/caffe/mxnet/onnx格式的
然后我們用SDK中的工具鏈對模型model.onnx進行編譯得到aipu.bin,就像這樣aipubuild build.cfg 最后將這個aipu.bin封裝到應用程序APP中, 放到到板子上運行即可;
簡單來說,流程跟你gcc編譯c代碼是一樣的,只是參數格式不一樣而已,這里的輸入是模型,輸出的是NPU支持的bin可執行文件; 此外,調bug有debugger可用,性能問題可以用profiler,沒有具體硬件可以用simulator模擬硬件來跑,當然了IDE圖形化操作界面也是有的。 后續的課程中我將就每一個模塊結合SDK文檔進行詳細講解+逐代碼分析。這章回,我們先跟著教程走一遍流程,認識認識代碼框架。
4. 操作流程+代碼框架初識
第一步是搭建開發環境,跟著這個教程:https://docs.radxa.com/sirider/s1/app-development/zhouyi\\\_npu一步一步來,就能把整個環境搭建流程跑通(windows直接用WSL2即可)。 第二步是編譯模型,在x86 PC段進行模型編譯,還是上面鏈接(看編譯部分)
看到有如上文件,第一步是生成量化校準集,因為我們的原始模型是fp32的,但NPU是不支持fp32的,因此我們需要將其量化到int8/int16。 一個fp32的值量化到int8,在量化領域有非常多的算法來實現,我們這里使用的是PTQ(假設不理解也不要緊,后面我會專門講解一下量化相關的內容,因為這部分代碼開源了,因此甚至對著開源的代碼進行code級講解的)進行量化。 量化需要準備一個數據集進行數據范圍分布的采集過程,假如不理解為什么要這一步也不要緊,知道有這個流程就行了,后面講量化算法的時候就明白了。
python3generate_calibration_data.py
我們看下代碼的實現
可知就是從原訓練代碼里面摳出來的初始化代碼,處理的就是當前目錄下的images圖集,得到的是對應的npy格式對應數據; 緊接著產生輸入數據:
python3 generate\_input\_binary.py
這里稍微解釋下,首先我們需要拿到一個量化參數,也就是scale,這個值是從量化階段拿到的,量化產生文件之一就是*.json文件,從中尋找即可。 然后將輸入圖像量化成uint8格式的數據,然后轉置一下得到NHWC格式的輸入,此時即可用作模型的輸入了(因為NPU支持的外部輸入layout就是NHWC),
vim ./resnet50/build.cfg
第二行的編譯mode有兩種,第一種是build,即編譯完后輸出aipu.bin給板子跑的,第二種是run,即編譯完后可以直接在服務器上、本地電腦上模擬硬件跑(simulator)。 編譯的流程有三大步驟:
解析模型;
量化
編譯執行
Parser的作用是將標準的通用模型(ONNX、TF、pytorch等)轉換為內部專用的IR;Input\_data\_format 指的是輸入的data\_layout,我們在前面的構造輸入數據時選的就是NHWC,所以這里填NHWC;模型名字model\_name,標準填就好了;Detection\_postprocess填后處理的算子名,像檢測模型都是有后處理部分的,我們對應填,當然也可以選擇不填,直接在CPU端做后處理;其他都是所見即所得,除了注意input的配置即可,這是輸入tensor的名字,用netron打開onnx model即可得到; Optimizer中dataset字段就是指定數據集的格式,前面我們構造的是numpy格式的,所以這里填NumpyDataset;主要注意下bits部分的設置,因為一般的玩法只有這里有可調,來粗粒度的調整精度/性能的權衡,當然了,后期大家想玩的話我就帶大家進行代碼級的玩法。 Gbuilder部分就是直接編譯的,profile就是輸出perf性能數據的,會一定程度上影響性能,因此在debug階段使用即可;target指的是硬件的版本號,這里是固定的填Z2\_1104即可,這一塊沒有什么需要額外配置的,當然具體的每一個參數我們可以到后面的Gbuilder章節進行詳細解說,這里堪堪帶過。 按照官方教程直接編譯:
可以看到Gbuilder的版本是5.3.2194,開始進行解析模型了,這里由于我使用的是WSL2沒有cuda,所以會比較慢
解析完后輸出如上,此時就得到了我們NPU所需的中間表達格式(IR)了
得到IR后,我們會先做一個檢查,看解析出來的IR格式以及graph的連接關系是否合理,再初步做一個float graph級的圖優化,可以看到這里優化掉了一個Transpose層;
緊接著就進入量化階段了,可以看到整個流程里面有非常多的階段,每個階段都有在做特定的事,這里涉及的內容比較多,我們暫且按下不表,后面我們將會對照源碼進行一一解說(有機會的話,還會跟業界做的比較好的ppq框架進行相關的對比)。 這里主要關注下最后的輸出scale,用來在后處理階段使用的;以及輸出tensor的cosine值,這個值是反應模型精度的。 總之,經過量化后,我們就得到了定點格式的IR,此IR經過編譯后,可以直接在NPU硬件上跑起來的。
由于量化過程中也會有圖結構的改變,因此這里做完量化后也需要執行圖檢查以及圖優化步驟的。
到這里后,終于開始編譯模型了,這個部分主要內容包括給graph中的node進行算子匹配,整網內存分配及優化,多核調度,硬件底層圖優化等。比如上圖中的aipu\_plugin就是算子,每個標準算子都有好幾種底層硬件實現(opencl、asm),根據特定機制進行整網全局匹配。
這里是layout的調度部分,目標就是盡可能減少途中layoutconvert的個數,這個部分也是個最優化的問題,細講下去也就停不下來了,將來有機會我們詳細說說。
最后就是內存部分的內容了,整網所需的內存是26.547MB,代碼段、RO段、desc段(這個不常見,這是底層算子的特定格式),DataBss都是標準格式。最后可以看到是有個SRAM的優化的,這個是NPU內部的一個快速靜態存儲區域,用來緩存node間的featuemap的,不僅能降低footprint還能提升性能。 好了,到這里,模型終于編好了,我們看下編出了些啥:
第一個文件就是我們NPU需要的可執行文件,也就是在build.cfg指定的輸出文件;
第二個文件就是build配置腳本;
第三個時量化校準數據集;
第四個時輸入數據,第五個是輸入數據對應的圖片;
第六個、第七個就是parser后得到的浮點IR文件(圖結構文件以及權重文件);
第八個是量化產生的文件,有啥量化的問題你去這個文件內查查即可;
第九個、第十個是量化后產生的定點IR;
第十一個、第十二個文件是定點IR經過圖優化后的精簡IR;
第十三個、第十四個是浮點IR經過圖優化后產生的IR;
第十五個文件是驗證集的統計信息,有這個文件后,下次編譯就不用繼續跑耗時的校準過程了;
第十六個文件是原始的resnet50.onnx模型;
第十七個文件是 run的時候(不是跑在NPU上而是在PC上跑simulator用的)用的cfg配置文件;
可以看到除了紅框內的東西外,其余都是差不多的。 現在我們生成了模型的bin文件,但還不是最終應用的可執行文件,最終的應用是調用我們剛剛生成的模型,這部分的代碼在這:
Aiputest就是應用程序的邏輯部分,umd里面就是一堆面向用戶的庫函數,庫函數里面是直接調用驅動,以及環境構建的(待會我們直接進去看下代碼結構)。 按照軟件工程的結構,我們先查看頂層的CMakeLists.txt文件,獲取到的信息如下:
Cmake版本要搞對噢,UMDSRC變量要仔細檢查對路徑哈!設置好交叉編譯器的路徑,設置好最終的輸出路徑; 頂層配置好參數,然后直接add\_subdirectory讓子目錄自己去根據參數執行具體的編譯任務。 我們先看umd文件夾,里面直接Linux-driver/driver/umd的源碼拉進來編成動態庫,給后面的應用aiputest來動態鏈接。
Aiputest是個非常簡單的應用,因此我們只需要將umd頭文件引進來,umd動態庫鏈接進來,直接編譯即可。
我們看下main.cpp文件中的內容結構:
其中UMD相關的功能全都封裝到standard\_api.h接口文件中了,接下來的代碼無非就是初始化環境,開啟NPU任務,接受返回數據,清理“戰場”(環境)等標準步驟,沒啥特殊的,具體參數解析可以查文檔或者等我后續的文章逐代碼解析。 (ps. 其中可以看到雖然是c++環境,但是用的都是非常標準的c代碼風格,挺好的,非常適合用來直觀理解執行流程。)
研究代碼發現這里有dump profiler的邏輯;
應用中也是有profiler的程序的,其中result\_bin\_path就是上面代碼中輸出的PerfData.bin文件,因此我們可以留個坑,將來講講如何用這個來分析模型的性能優化。 好了,視角拉回,我們直接編譯得到了對應的文件,
按照官方教程的步驟將文件scp到板子后,直接就可以跑啦~
-
芯片
+關注
關注
455文章
50812瀏覽量
423581 -
開發板
+關注
關注
25文章
5050瀏覽量
97456 -
SDK
+關注
關注
3文章
1036瀏覽量
45936
原文標題:開發板測評|芯擎SiRider S1初探流程·流暢
文章出處:【微信號:Ithingedu,微信公眾號:安芯教育科技】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論