1. 深度學(xué)習(xí)模型在FPGA上的部署

        共 8569字,需瀏覽 18分鐘

         ·

        2021-06-12 16:30

        編輯丨阿chai帶你學(xué)AI


        我是來自山區(qū)、樸實、不偷電瓶的AI算法工程師阿chai,給大家分享人工智能、自動駕駛、機器人、3D感知相關(guān)的知識


        今天給大家介紹一下FPGA上部署深度學(xué)習(xí)的算法模型的方法以及平臺。希望通過介紹,算法工程師在FPGA的落地上能“稍微”緩和一些,小白不再那么迷茫。阿chai最近在肝一個開源的項目,等忙完了會給大家出幾期FPGA上從零部署的教程,包括一些底層的開發(fā)、模型的量化推理等等,因為涉及的東西太多了,所以得分開寫。

        FPGA與“迷宮”

        深度學(xué)習(xí)這里就不多介紹了,我們接下來介紹一下FPGA是什么。FPGA是現(xiàn)場可編程邏輯門陣列,靈活性非常高,現(xiàn)場編程真的香。說到這里小伙伴們可能還是不太明白,那么我們和ARM對比一下,ARM可以理解為比如這有一個迷宮,迷宮有很多進口也有對應(yīng)的出口,道路中間有很多“暗門”可以走,對ARM芯片做編程就是觸發(fā)當(dāng)中一條通路,路是死的,我們不好改變。FPGA是如果我們想要一個迷宮,F(xiàn)PGA給提供了一個大的“盒子”,里面有很多的“隔板”,我們自己搭建一條就可以了,你想要什么樣的路就什么樣子,類似玩我的世界,只不過“礦”是各種邏輯門。那就意味著,F(xiàn)PGA可以設(shè)計外圍電路也可以設(shè)計CPU,是不是很爽,當(dāng)然,爽的背后開發(fā)難度也是相當(dāng)?shù)拇蟮模@種“特定屬性”非常時候做人工智能的算法加速。由于制作特殊電路,F(xiàn)PGA之前經(jīng)常用做信號處理中,配合DSP或者ARM使用,后來也有用FPGA或者CPLD搭建“礦機”當(dāng)“礦老板”(祝愿”挖礦“的天天礦難)。

        小白入門A:PYNQ

        PYNQ是Python + ZYNQ,用Python進行FPGA開發(fā),首先強調(diào)一點,Python近幾年非?;?,雖然很強大,但是他開發(fā)硬件不是真的就做硬件,希望大家不要迷。
        教程:https://github.com/xupsh/Advanced-Embedded-System-Design-Flow-on-Zynq
        我們類比一下很火的MicroPython,使用Python開發(fā)硬件是得有特定的電路設(shè)計的,除非自己是大佬修改底層的固件,但是都修改底層了,是不是可以自己開發(fā)就好了。當(dāng)然這個是面向小白的,對應(yīng)的開發(fā)板如下圖。
        這個板子類似我們之前玩MicroPython,也是各種調(diào)包。實際上ZYNQ是一個雙核ARM Cortex-A9處理器和一個FPGA,使用Python的話可以通過Jupyter進行開發(fā),是不是很香,所以這個非常適合小白。
        FPGA上跑BNN(二值神經(jīng)網(wǎng)絡(luò))是非常不錯的,“PYNQ-Z1不同的機器學(xué)習(xí)數(shù)據(jù)集(dataset)的測試結(jié)果顯示:對于MNIST數(shù)據(jù)集PYNQ-Z1能實現(xiàn)每秒168000張圖片的分類,延遲102微妙,準(zhǔn)確率達98.4%;對于CIFAR-10、SVHN、GTSRB數(shù)據(jù)集PYN1-Z1能實現(xiàn)每秒1700張圖片的分類,延遲2.2毫秒,準(zhǔn)確率分別為80.1%、96.69%和97.66%,系統(tǒng)功耗均保持在2.5W左右。
        這個到底有多方便,我們看一段代碼,首先我們調(diào)用模型:
        import bnn

        hw_classifier = bnn.CnvClassifier(bnn.NETWORK_CNVW1A1,'cifar10',bnn.RUNTIME_HW)
        sw_classifier = bnn.CnvClassifier(bnn.NETWORK_CNVW1A1,'cifar10',bnn.RUNTIME_SW)
        進行測試:
        from IPython.display import display

        im = Image.open('car.png')
        im.thumbnail((6464), Image.ANTIALIAS)
        display(im) 
        car_class = hw_classifier.classify_image_details(im)
        print("{: >10}{: >13}".format("[CLASS]","[RANKING]"))
        for i in range(len(car_class)):
            print("{: >10}{: >10}".format(hw_classifier.classes[i],car_class[i]))
        同樣支持matplotlib進行數(shù)據(jù)可視化:
        %matplotlib inline
        import matplotlib.pyplot as plt

        x_pos = np.arange(len(car_class))
        fig, ax = plt.subplots()
        ax.bar(x_pos - 0.25, (car_class/100.0), 0.25)
        ax.set_xticklabels(hw_classifier.classes, rotation='vertical')
        ax.set_xticks(x_pos)
        ax.set
        plt.show()
        這不就是Python嘛,真的是非常的方便,而且圖像處理也兼容使用Pillow。文件中給出了一些圖像識別的例子,大家可以去看看。改天阿chai給大家出一個從零搭建PYNQ的教程,包括模型的量化推理等等。

        小白入門B:DPU

        DPU是一個用于卷積神經(jīng)網(wǎng)絡(luò)的可編程引擎。該單元包含寄存器配置模塊、數(shù)據(jù)控制器模塊和卷積計算模塊。當(dāng)然,強大的PYNQ也是支持使用DPU的,如果用這個直接看Python的API就可以了,開發(fā)板可以使用ZCU104。大神很多直接用ZYNQ開整的,但是那個難度真的不適合初學(xué)者去看,等忙完了項目阿chai給小伙伴們整個這個的教程。
        我們首先clone下來項目并且編譯:
        git clone https://github.com/Xilinx/DPU-PYNQ.git
        cd DPU-PYNQ/upgrade
        make
        安裝pynq-dpu:
        pip install pynq-dpu
        啟動jupyter-notebook:
        pynq get-notebooks pynq-dpu -p .
        模型庫在如下鏈接中。
        模型庫:https://github.com/Xilinx/Vitis-AI/tree/v1.3
        對于DPU的設(shè)計,我們需要在自己的電腦上進行,在添加模塊后,我們使用如下命令進行編譯:
        make BOARD=<Board>
        對于ZYNQ+DPU的開發(fā)過程阿chai會單獨出一期,因為涉及的東西太多了。。。

        支持國產(chǎn)框架:Paddle-Lite

        既然python都可以,那肯定Paddle-Lite這種推理框架也是可行的,百度也有專門的部署開發(fā)套件 EdgeBoard。EdgeBoard是基于Xilinx Zynq UltraScale+ MPSoC系列芯片打造的計算卡,芯片內(nèi)部集成ARM處理器+GPU+FPGA的架構(gòu),既具有多核處理能力、也有視頻流硬解碼處理能力,還具有FPGA的可編程的特點。

        其實部署的思路小伙伴們應(yīng)該有一些眉目了,就是將自己訓(xùn)練的深度學(xué)習(xí)模型轉(zhuǎn)換成Paddle Lite模型,然后移植到EdgeBoard開發(fā)板上進行測試。接下來我們簡單看看是怎樣操作的。
        EdgeBoard中模型的測試由json文件做管理:
        {
         "model":"測試的模型"
         "combined_model":true
         "input_width":224,
         "input_height":224,
         "image":"測試的路徑",
         "mean":[104,117,124],
         "scale":1,
         "format":"BGR"
            "threshold":0.5
        }
        詳細的操作請前往Paddle Lite的GitHub,這里只做簡單的流程介紹。
        GitHub: https://github.com/PaddlePaddle/Paddle-Lite
        如果不想編譯,直接在如下網(wǎng)址中下載編譯好的文件即可。
        編譯后的文件:https://ai.baidu.com/ai-doc/HWCE/Yk3b95s8o

        1.安裝測試

        我們首先在有在開發(fā)板上編譯Paddle Lite,編譯的時候需要設(shè)置cmake的參數(shù),設(shè)置LITE_WITH_FPGA=ONLITE_WITH_ARM=ON,問就是我們都用到。對應(yīng)的FPGA的編譯腳本是lite/tools/build_FPGA.sh,我們執(zhí)行即可。
        sh ./lite/tools/build_fpga.sh
        make publish_inference -j2
        接下來我們編譯示例demo,demo也在剛才的下載鏈接中。
        板子的使用過程請參考百度官方的文檔,文檔介紹的非常的清楚,阿chai這里就不花時間去講解使用過程了。
        然后進入demo中進行編譯:
        # classification
        cd /home/root/workspace/sample/classification/    
        mkdir build
        cd build
        cmake ..
        make
        build目錄下會出現(xiàn)image_classify和video_classify兩個可執(zhí)行文件,圖片預(yù)測運行image_classify文件。
        使用FPGA 進行resnet50進行測試:
        ./image_classify_fpga_preprocess ../configs/resnet50/drink.json  
        可以看到對應(yīng)的輸出結(jié)果,同樣detection的模型測試方式也這樣操作。

        2.可調(diào)用的接口

        C++

        C++的主要包括預(yù)處理以及預(yù)測庫的接口。
        • 預(yù)處理接口主要是使用FPGA完成圖片的縮放、顏色空間轉(zhuǎn)換和mean/std操作。
        • 預(yù)測庫接口主要完成模型的初始化、輸入?yún)?shù)構(gòu)造、預(yù)測和結(jié)果獲取。
        預(yù)處理接口示例:
        /**
          * 判斷輸入圖像是否是wc 16對齊
          * width 輸入圖像寬度
          * channel 輸入圖像高度
          **/

         bool img_is_align(int width, int channel);

         /**
          * 對齊后的大小
          * width 輸入圖像寬度
          * channel 輸入圖像高度
          **/

         int align_size(int width, int channel);

         /**
          * 分配存放圖片的內(nèi)存,析構(gòu)函數(shù)會自動釋放 (目前支持BGR->RGB RGB->BGR YUV422->BGR YUV->RGB) 圖像最大分辨率支持1080p
          * height 輸入圖像的框
          * width 輸入圖像寬度
          * in_format 輸入圖像格式 參考image_format
          * return uint8_t*  opencv Mat CV_8UC3
          **/

         uint8_tmem_alloc(int img_height, int img_width, image_format in_format);
        預(yù)測庫使用步驟
        1、模型初始化,構(gòu)建預(yù)測對象
         std::unique_ptr<paddle_mobile::PaddlePredictor> g_predictor;
            PaddleMobileConfig config;
            std::string model_dir = j["model"];
            config.precision = PaddleMobileConfig::FP32;
            config.device = PaddleMobileConfig::kFPGA;
            config.prog_file = model_dir + "/model";
            config.param_file = model_dir + "/params";
            config.thread_num = 4;
            g_predictor = CreatePaddlePredictor<PaddleMobileConfig,
                            PaddleEngineKind::kPaddleMobile>(config);
        2、輸入輸出參數(shù)
            std::vector<PaddleTensor> paddle_tensor_feeds;
            PaddleTensor tensor;
            tensor.shape = std::vector<int>({13, input_height, input_width});
            tensor.data = PaddleBuf(input, sizeof(input));
            tensor.dtype = PaddleDType::FLOAT32;
            paddle_tensor_feeds.push_back(tensor);

            PaddleTensor tensor_imageshape;
            tensor_imageshape.shape = std::vector<int>({12});
            tensor_imageshape.data = PaddleBuf(image_shape, 1 * 2 * sizeof(float));
            tensor_imageshape.dtype = PaddleDType::FLOAT32;
            paddle_tensor_feeds.push_back(tensor_imageshape);

            PaddleTensor tensor_out;
            tensor_out.shape = std::vector<int>({});
            tensor_out.data = PaddleBuf();
            tensor_out.dtype = PaddleDType::FLOAT32;
            std::vector<PaddleTensor> outputs(1, tensor_out);
        3、預(yù)測
         g_predictor->Run(paddle_tensor_feeds, &outputs);
        4、獲取結(jié)果
         float *data = static_cast<float *>(outputs[0].data.data());
            int size = outputs[0].shape[0];

        Python

        EdgeBoard系統(tǒng)已經(jīng)安裝了python環(huán)境,用戶可直接使用即可,同時python接口為用戶提供了paddlemobile的python安裝包以及示例工程。
        文件名稱
        說明


        paddlemobile-0.0.1.linux-aarch64-py2.tar.gz
        paddlemobile的python2安裝包
        edgeboard.py
        基于python的模型預(yù)測示例
        api.py
        edgeboard.py的api示例
        configs.classification
        分類模型的配置文件目錄,同C++示例的配置文件
        configs.detection
        檢測模型的配置文件目錄,同C++示例的配置文件
        models.classification
        分類模型的模型文件目錄,同C++示例的模型文件
        models.detection
        檢測模型的模型文件目錄,同C++示例的模型文件
        安裝paddlemobile-python SDK,在根目錄中解壓
        tar -xzvf  home/root/workspace/paddlemobile-0.0.1.linux-aarch64-py2.tar.gz
        例如使用分類模型的測試如下:
        python api.py -j 你測試的json文件
        詳細的使用說明請關(guān)注Paddle-Lite的GitHub。
        介紹了這幾種,其實大家可以看出來,入門使用并不難,難的是底層的硬件設(shè)計與算法加速量化等等,這些都是打包好的東西,我們真的開發(fā)還是得慢慢的扣底層的。在這里借用一位大神說的話,現(xiàn)在人工智能算法工程師和十年前的嵌入式工程師差不多,從需求到硬件、軟件、算法、應(yīng)用等等都能做,貌似真的是這樣,太卷了,不多學(xué)點真的要涼。工具是越來越好用,難的是輪子怎么造,一起加油。


         End 


        聲明:部分內(nèi)容來源于網(wǎng)絡(luò),僅供讀者學(xué)術(shù)交流之目的。文章版權(quán)歸原作者所有。如有不妥,請聯(lián)系刪除。


        瀏覽 105
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 三上悠亚精品一区 | 久久9久久| 美女撒尿无遮挡免费 | 日韩无码啪啪啪 | 巨肉黄暴辣文高h公主 |