0#01 解析mobile_ssd樣例代碼

1.預(yù)備知識
2.樣例程序介紹
3.運行代碼
3.1.能在筆記本上成功運行 mobilenet_ssd 樣例代碼。
3.2.理解 Tengine 的工作方式。
3.3.能在 RK3399 上運行該程序。
3.4.能在 RK3399 上運行該程序并使用 GPU 加速

1.預(yù)備知識

? ? ? ?CLion:一款優(yōu)秀的C語言開發(fā)工具砍的。主要是有免費的社區(qū)版本,并且能支持cmake文件的編譯。最大的福利就是支持Ubuntu安裝意鲸。
? ? ? ?環(huán)境安裝:0#00 Tengine 的安裝

2.樣例程序介紹

? ? ? ?樣例程序位于tengine目錄下," tengine安裝路徑/examples/mobilenet_ssd/"
? ? ? ?我們使用 CLion 打開該項目尽爆。
1.選中mobilenet_ssd文件夾
2.右鍵->open with(打開方式)->Other Applications->View All Applications->CLion(使用CLion打開該文件夾怎顾。)
? ? ? ?打開該文件的目的:
1.能在筆記本上成功運行 mobilenet_ssd 樣例代碼。
2.理解 Tengine 的工作方式漱贱。
3.能在 RK3399 上運行該程序槐雾。
4.能在 RK3399 上運行該程序并使用 GPU 加速
注:當(dāng)前階段并不去理解 SSD 的工作方式,因為官方已經(jīng)為我們提供訓(xùn)練好的 caffe 模型( prototxt + caffemodel )


從百度云中下載 caffe 模型 Tengine model zoo (密碼: 57vb)
找到:

  • MobileNetSSD_deploy.caffemodel
  • MobileNetSSD_deploy.prototxt
    將其存放在 tengine路徑下/models/

3.運行代碼

TODO:1.能在筆記本上成功運行 mobilenet_ssd 樣例代碼饱亿。

? ? ? ?如果直接使用 CLion 對該程序進(jìn)行編譯蚜退,會產(chǎn)生報錯信息闰靴,類似缺少(找不到)頭文件。

/usr/bin/cmake --build /home/lee/Documents/tengine/examples/mobilenet_ssd/cmake-build-debug --target MSSD -- -j4
......(省略)
/common.cpp:4:27: fatal error: tengine_c_api.h: 沒有那個文件或目錄
compilation terminated.
CMakeFiles/MSSD.dir/build.make:86: recipe for target 'CMakeFiles/MSSD.dir/home/lee/Documents/tengine/examples/common/common.cpp.o' failed
make[3]: *** [CMakeFiles/MSSD.dir/home/lee/Documents/tengine/examples/common/common.cpp.o] Error 1
make[3]: *** Waiting for unfinished jobs....
/home/lee/Documents/tengine/examples/mobilenet_ssd/mssd.cpp:32:27: fatal error: tengine_c_api.h: 沒有那個文件或目錄
compilation terminated.
CMakeFiles/MSSD.dir/build.make:62: recipe for target 'CMakeFiles/MSSD.dir/mssd.cpp.o' failed
......(省略)

原因在官方給的 gpu_cpu_mssd.md 中提到:

cd example/mobilenet_ssd
cmake -DTENGINE_DIR=/home/firefly/tengine .
make 

所以問題出在 -DTENGINE_DIR 指定 Tengine 的安裝路徑钻注。
解決辦法:
在 CMAKE 文件中加入該行蚂且。

cmake_minimum_required (VERSION 2.8)
project(MSSD)
add_definitions(-std=c++11)
# TODO:設(shè)置 TENGINE_DIR 的路徑
set( TENGINE_DIR /home/lee/Documents/tengine )
set( INSTALL_DIR ${TENGINE_DIR}/install/)
set( TENGINE_LIBS tengine)

? ? ? ?那為什么不使用官方的方法,在CMAKE中加入一個選項呢?
這是我的一些嘗試得到的經(jīng)驗:
1.不方便幅恋,每次 CMAKE 加入該行杏死,有時我們使用的 tengine 路徑和官方不一樣,CMAKE 不會報錯捆交,修改的時候淑翼,要刪除一些 CAMKE 產(chǎn)生的內(nèi)容,才能重新 CMAKE品追。
2.無法利用 CLion 提供的優(yōu)勢玄括,CLion 每次 CMAKE 會產(chǎn)生一個類似 build 的文件夾,方便管理肉瓦,不需要再手動刪除了遭京。
3.直接編寫,能為后續(xù)報錯信息提供一些思路泞莉,有時候使用 ”-DTENGINE_DIR“ 進(jìn)行指定路徑 啟動的減號是有中/英文字符區(qū)別的哪雕,會產(chǎn)生莫名奇妙的錯誤。
? ? ? ?再次編譯cmake文件就會沒有報錯信息了鲫趁,注意:使用的 Tengine 路徑需要修改為適合自己環(huán)境特征的斯嚎。

clion.png

? ? ? ?運行該程序:

image.png

? ? ? ?所以我們已經(jīng)完全能夠 運行 該 樣例 了。
任務(wù)1:完成挨厚。

TODO:2.理解 Tengine 的工作方式堡僻。

? ? ? ?任務(wù)1:只是單純的運行程序,測試結(jié)果幽崩,和 example 差不多苦始,類似于 我們安裝的 Tengine 是否能夠正常工作。
? ? ? ?任務(wù)2:已知 MobileNet_SSD 能正常工作的前提下慌申,進(jìn)行代碼的分析陌选。
? ? ? ?如果對于 Tengine 一無所知的話,可以利用 "MobileNet_SSD"進(jìn)行理解蹄溉,并且可以充分的利用 CLion 這個工具咨油,進(jìn)行函數(shù)查找,OAID 為 Tengine 編寫的 "tengine_c_api.h" 文件提供了豐富的注釋信息柒爵,我們可以將其改為中文役电,以便確認(rèn)我們使用了哪些函數(shù)。
? ? ? ?我的經(jīng)歷總結(jié)如下:

TODO:1. 調(diào)用 init_tengine() 對 tengine進(jìn)行初始化
TODO:2. 調(diào)用 create_graph 將 訓(xùn)練好的模型 導(dǎo)入到 圖(網(wǎng)絡(luò))中
TODO:3.1通過 get_graph_input_tensor 獲取輸入的 tensor
TODO:3.2用 set_tensor_shape 設(shè)置輸入Tensor的shape
TODO: 4. 調(diào)用 prerun_graph 函數(shù)預(yù)啟動圖(類似 malloc,申請資源)
TODO: 5.1.向 input_data 寫入輸入的數(shù)據(jù),
TODO: 5.2.并調(diào)用 set_tensor_buffer 把數(shù)據(jù)轉(zhuǎn)移到輸入Tensor上
TODO: 6. 調(diào)用 run_graph 運行圖(做一次前向傳播)
TODO: 7.1 向 input_data 寫入輸入的數(shù)據(jù)
TODO: 8. 調(diào)用 run_graph 運行圖(做一次前向傳播)
TODO: 9.1.調(diào)用 get_graph_output_tensor 獲取輸出Tensor
TODO: 9.2.并用 get_tensor_shape 取得 tensor 的shape
TODO: 9.3 利用get_tensor_buffer 取得輸出 tensor 的內(nèi)容

最后在退出程序前依次釋放各個申請的動態(tài)空間

TODO: 9.4 釋放 out_tensor 所占空間
TODO: 3.3 釋放 input_tensor 所占空間
TODO: 2.2 調(diào)用 destroy_graph() 來釋放資源
TODO: 1.1 釋放 tengine

? ? ? ?很明顯棉胀,我們使用 tengine 只是用來進(jìn)行前向計算(forward)法瑟,并不需要后向反饋(backward)冀膝。
? ? ? ?所以程序很有模板的感覺,這也為使用 tengine 降低了難度霎挟。
? ? ? ?一些總結(jié):tengine 和我常常使用的 PyTorch 進(jìn)行前向推導(dǎo)并不太相同窝剖,

假設(shè) 模型為 Net,輸入為 input酥夭,輸出為 output赐纱。
PyTorch:output = Net(input)
tengine:
1. 導(dǎo)入模型:
load_model(Net,,"caffe", proto文件路徑, model_file文件路徑)
2.給模型輸入:
get_graph_input_tensor()
3.獲取模型輸出
get_graph_output_tensor()
有點面向?qū)ο蟮牟僮鳌?

接下來開始閱讀示例代碼(main函數(shù)):

1.定義默認(rèn)參數(shù)變量名稱

    // root_path 為 Tengine 的文件路徑
    const std::string root_path = get_root_path();
    // proto_file 為我們設(shè)置的 prototxt 文件路徑
    std::string proto_file;
    // model_file 為我們設(shè)置的 model 文件路徑
    std::string model_file;
    // image_file 為我們設(shè)置的 image 文件路徑
    std::string image_file;
    // 設(shè)置保存的 生成圖片 路徑名稱
    std::string save_name="save.jpg";
    // device 使用設(shè)備默認(rèn)為空(用于graph)
    const char * device=nullptr;

2.處理命令行的輸入處理

    int res;
    // 與命令行輸入相關(guān), 指定可輸入?yún)?shù)(-p -m -i -hd)
/*
*   -p      prototxt 文件路徑       默認(rèn):"models/MobileNetSSD_deploy.prototxt"
*   -m      model 文件路徑          默認(rèn):"models/MobileNetSSD_deploy.caffemodel"
*   -i      image 文件路徑          默認(rèn):"tests/images/ssd_dog.jpg"
*   -h      help 信息
*   -d      device 設(shè)置            默認(rèn):為空
*/

    while( ( res=getopt(argc,argv,"p:m:i:hd:"))!= -1)
    {
        switch(res)
        {
            case 'p':
                proto_file=optarg;
                break;
            case 'm':
                model_file=optarg;
                break;
            case 'i':
                image_file=optarg;
                break;
            case 'd':
                device=optarg;
                break;
            case 'h':
                std::cout << "[Usage]: " << argv[0] << " [-h]\n"
                          << "   [-p proto_file] [-m model_file] [-i image_file]\n";
                return 0;
            default:
                break;
        }
    }

3.設(shè)置 命令行參數(shù)默認(rèn)信息

    // prototxt 默認(rèn)路徑
    if(proto_file.empty())
    {
        proto_file = root_path + DEF_PROTO;
        std::cout << "proto file not specified,using " << proto_file << " by default\n";
    }
    // caffemodel 默認(rèn)路徑
    if(model_file.empty())
    {
        model_file = root_path + DEF_MODEL;
        std::cout << "model file not specified,using " << model_file << " by default\n";
    }
    // 使用圖片的  默認(rèn)路徑
    if(image_file.empty())
    {
        image_file = root_path + DEF_IMAGE;
        std::cout << "image file not specified,using " << image_file << " by default\n";
    }

開始使用 OAID 提供的 tengine_c_api.h。(建議配合 ctrl+鼠標(biāo)點開對應(yīng)的函數(shù)名稱熬北,進(jìn)行查看作用)
4.完成TODO1疙描,2

    // TODO:1. 調(diào)用 init_tengine() 對 tengine進(jìn)行初始化
    if(init_tengine() < 0)
    {
        std::cout << " init tengine failed\n";
        return 1;
    }
    // 檢查庫文件是否高于0.9
    if(request_tengine_version("0.9") != 1)
    {
        std::cout << " request tengine version failed\n";
        return 1;
    }
    // 確認(rèn) 模型文件存在
    if(!check_file_exist(proto_file) or (!check_file_exist(model_file) or !check_file_exist(image_file)))
    {
        return 1;
    }
    // TODO:2. 調(diào)用 create_graph 將 訓(xùn)練好的模型 導(dǎo)入到 圖(網(wǎng)絡(luò))中
    graph_t graph = create_graph(nullptr, "caffe", proto_file.c_str(), model_file.c_str());

    // 判斷是否創(chuàng)建 graph 成功
    if(graph == nullptr)
    {
        std::cout << "Create graph failed\n";
        std::cout << " ,errno: " << get_tengine_errno() << "\n";
        return 1;
    }
    // 設(shè)置 運行 的設(shè)備
    if(device != nullptr)
    {
        set_graph_device(graph, device);
    }

5.設(shè)置我們處理圖片的信息
? ? ? ?在 SSD 論文中,對于圖形的輸入需要先進(jìn)行 reshape讶隐。

    // 輸入圖片信息
    // img 的高(height)
    int img_h = 300;
    // img 的寬(width)
    int img_w = 300;
    // img 的大小(size)
    int img_size = img_h * img_w * 3;
    // 為輸入圖片申請空間,有mallloc,所以需要釋放(free)
    float *input_data = (float *)malloc(sizeof(float) * img_size);

    int node_idx=0;
    int tensor_idx=0;

6.對于模型輸入的預(yù)處理起胰,為了得到輸入的入口

    // TODO:1. 調(diào)用 init_tengine() 對 tengine進(jìn)行初始化
    if(init_tengine() < 0)
    {
        std::cout << " init tengine failed\n";
        return 1;
    }
    // 檢查庫文件是否高于0.9
    if(request_tengine_version("0.9") != 1)
    {
        std::cout << " request tengine version failed\n";
        return 1;
    }
    // 確認(rèn) 模型文件存在
    if(!check_file_exist(proto_file) or (!check_file_exist(model_file) or !check_file_exist(image_file)))
    {
        return 1;
    }
    // TODO:2. 調(diào)用 create_graph 將 訓(xùn)練好的模型 導(dǎo)入到 圖(網(wǎng)絡(luò))中
    graph_t graph = create_graph(nullptr, "caffe", proto_file.c_str(), model_file.c_str());

    // 判斷是否創(chuàng)建 graph 成功
    if(graph == nullptr)
    {
        std::cout << "Create graph failed\n";
        std::cout << " ,errno: " << get_tengine_errno() << "\n";
        return 1;
    }
    // 設(shè)置 運行 的設(shè)備
    if(device != nullptr)
    {
        set_graph_device(graph, device);
    }

7.多次重復(fù),獲取平均值(設(shè)置重復(fù)屬性)

    // 設(shè)置重復(fù)次數(shù),求平均值
    int repeat_count = 1;
    // getenv 獲取環(huán)境變量
    const char* repeat = std::getenv("REPEAT_COUNT");

    if(repeat)
        /* strtoul: (str to ul)將字符類型轉(zhuǎn)為unsigned long類型,
         * 10:十進(jìn)制   NULL:結(jié)束符
         */
        repeat_count = std::strtoul(repeat, NULL, 10);

8.實際輸入屬性

    //TODO: 5.1.向 input_data 寫入輸入的數(shù)據(jù),
    // 將 圖片 的路徑名轉(zhuǎn)化為 圖片內(nèi)容的矩陣,并賦值給 input_data
    get_input_data_ssd(image_file, input_data, img_h, img_w);
    //TODO: 5.2.并調(diào)用 set_tensor_buffer 把數(shù)據(jù)轉(zhuǎn)移到輸入Tensor上
    set_tensor_buffer(input_tensor, input_data, img_size * 4);

9.實際運行

    //TODO: 6. 調(diào)用 run_graph 運行圖(做一次前向傳播)
    ret = run_graph(graph, 1);
    if(ret != 0)
    {
        std::cout << "Run graph failed, errno: " << get_tengine_errno() << "\n";
        return 1;
    }

10.利用重復(fù)獲取平均運行時間

    struct timeval t0, t1;
    float total_time = 0.f;
    for(int i = 0; i < repeat_count; i++)
    {
        //TODO: 7.1 向 input_data 寫入輸入的數(shù)據(jù),
        get_input_data_ssd(image_file, input_data, img_h, img_w);
        // 獲取當(dāng)前值,并賦值給 t0(開始值)
        gettimeofday(&t0, NULL);
        //TODO: 8. 調(diào)用 run_graph 運行圖(做一次前向傳播)
        run_graph(graph, 1);
        gettimeofday(&t1, NULL);
        float mytime = ( float )((t1.tv_sec * 1000000 + t1.tv_usec) - (t0.tv_sec * 1000000 + t0.tv_usec)) / 1000;
        total_time += mytime;
    }
    std::cout << "--------------------------------------\n";
    std::cout << "repeat " << repeat_count << " times, avg time per run is " << total_time / repeat_count << " ms\n";

11.獲取輸出信息

    //TODO: 9.1.調(diào)用 get_graph_output_tensor 獲取輸出Tensor
    tensor_t out_tensor = get_graph_output_tensor(graph, 0, 0);    //"detection_out");
    /*
 * out_dim[4]中元素的含義
 * [0]:批次:1張圖
 * [1]:檢測到目標(biāo)個數(shù):3個目標(biāo)
 * [2]:outdata 的 Box 6 個信息:
 *              0. 屬于的類別(下標(biāo))
 *              1. 屬于該類別的score
 *              2. 左上角點(x)相對于寬的百分比
 *              3. 左上角點(y)相對于高的百分比
 *              4. 右上角點(x)相對于寬的百分比
 *              5. 右上角點(y)相對于高的百分比
 * [3]:1 一行
 */
    int out_dim[4];
    //TODO: 9.2.并用 get_tensor_shape 取得 tensor 的shape
    ret = get_tensor_shape(out_tensor, out_dim, 4);
    if(ret <= 0)
    {
        std::cout << "get tensor shape failed, errno: " << get_tengine_errno() << "\n";
        return 1;
    }
    //TODO:9.3 利用get_tensor_buffer 取得輸出 tensor 的內(nèi)容
    float* outdata = ( float* )get_tensor_buffer(out_tensor);

12.利用 輸出 和 OpenCV 進(jìn)行畫圖

    int num = out_dim[1];
    //設(shè)置閾值,是否為檢測目標(biāo)
    float show_threshold = 0.5;
    // 通過 outdata 對 image 進(jìn)行繪制邊框和label信息,并保存
    post_process_ssd(image_file, show_threshold, outdata, num, save_name);

12.程序結(jié)束巫延,記得釋放內(nèi)存和資源

    //TODO: 9.4 釋放 out_tensor 所占空間
    release_graph_tensor(out_tensor);
    //TODO: 3.1 釋放 input_tensor 所占空間
    release_graph_tensor(input_tensor);
    // 釋放 graph 執(zhí)行所占用的資源
    ret = postrun_graph(graph);
    if(ret != 0)
    {
        std::cout << "Postrun graph failed, errno: " << get_tengine_errno() << "\n";
        return 1;
    }
    free(input_data);
    //TODO: 2.2 調(diào)用 destroy_graph() 來釋放資源
    destroy_graph(graph);
    //TODO: 1.1 釋放 tengine
    release_tengine();

任務(wù)2:完成

TODO:3.能在 RK3399 上運行該程序待错。

? ? ? ? RK3399上 tengine 的路徑可能會與 筆記本電腦 不同。使用不同的 github 網(wǎng)址理澎,下載下來的 tengine 內(nèi)容雖然一樣塌衰,但是 文件名稱可能會不一樣。比如 tengine-master,tengine枕赵,Tengine。(這些都是小細(xì)節(jié))
? ? ? ? 并且 RK3399 上沒有 CLion驯遇,所以我們需要手動進(jìn)行 cmake焙畔。
? ? ? ? 過程如下:(建議修改前進(jìn)行 備份 )
1.修改 "CMakeLists.txt" 文件

# 設(shè)置 tengine 路徑
set( TENGINE_DIR /home/firefly/tengine )

2.創(chuàng)建 build 文件,目的是為了放置 cmake 文件設(shè)置錯誤玻熙,刪除文件的時候否彩,不確定要刪除哪些文件。

1.在 mobilenet_ssd 目錄下創(chuàng)建 build 文件
cd tengine/examples/mobilenet_ssd
mkdir build
cd build

2.進(jìn)行 cmake嗦随,前一級目錄( cmake 目的是為了生成 make文件)

cmake ..
返回信息
""
-- The C compiler identification is GNU 5.4.0
-- The CXX compiler identification is GNU 5.4.0
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Found OpenCV: /usr/local (found version "3.4.2") 
-- Configuring done
-- Generating done
-- Build files have been written to: /home/lee/Documents/tengine/examples/mobilenet_ssd/build
""

3.進(jìn)行make

make
返回信息
""
Scanning dependencies of target MSSD
[ 33%] Building CXX object CMakeFiles/MSSD.dir/mssd.cpp.o
[ 66%] Building CXX object CMakeFiles/MSSD.dir/home/lee/Documents/tengine/examples/common/common.cpp.o
[100%] Linking CXX executable MSSD
[100%] Built target MSSD
""

4.執(zhí)行可執(zhí)行文件

firefly@firefly:~/Tengine/examples/mobilenet_ssd/build$ ./MSSD 
/home/firefly/Tengine/examples/mobilenet_ssd/build/MSSD
proto file not specified,using /home/firefly/Tengine/models/MobileNetSSD_deploy.prototxt by default
model file not specified,using /home/firefly/Tengine/models/MobileNetSSD_deploy.caffemodel by default
image file not specified,using /home/firefly/Tengine/tests/images/ssd_dog.jpg by default
tensor: detection_out created by node: detection_out is not consumed
add the node: detection_out into output list
load model done!
--------------------------------------
repeat 1 times, avg time per run is 197.33 ms
detect result num: 3 
dog :100%
BOX:( 138.509 , 209.394 ),( 324.57 , 541.314 )
car :100%
BOX:( 467.315 , 72.8045 ),( 687.269 , 171.128 )
bicycle :100%
BOX:( 107.395 , 140.657 ),( 574.212 , 415.188 )
======================================
[DETECTED IMAGE SAVED]: [save.jpg](https://wx.qq.com/cgi-bin/mmwebwx-bin/webwxcheckurl?requrl=http%3A%2F%2Fsave.jpg&skey=%40crypt_f9d3b6a2_596aae6997f00ed042e8dccce68cd50a&deviceid=e183140456749306&pass_ticket=OlSyJ0Ia1IhtysLjA0CCvzP6XXavJ0bmawua8PAWQ1GErsg5SDT81873sBxClMpl&opcode=2&scene=1&username=@f7db13e1c47e0fed7e506d9d48739f7e)
======================================
Release Graph Executor for graph graph
Release workspace default resource

打開圖片進(jìn)行檢查列荔。(圖片在 mobilenet_ssd/build/save.jpg 目錄下)


save.jpg

任務(wù)3:完成

TODO:4.能在 RK3399 上運行該程序并使用 GPU 加速。

? ? ? ? 在 RK3399 上使用 GPU 枚尼,在 OAID 上有相關(guān)的教程gpu_cpu_mssd贴浙。
? ? ? ? 需要注意的是如果之前已經(jīng)編譯過 tengine ,不能直接使用GPU署恍。需要重新編譯(但是我還是失敗了)崎溃。

1.清除 make 信息
make clean
2.刪除 與 驅(qū)動相關(guān)的文件
rm -r build/driver

我使用GPU時,重新下載 tengine盯质。(即刪除原有的 tengine 目錄)
下面我從 0 開始講解如何 設(shè)置 RK3399 的 GPU 使用袁串。
1.從 github 中拷貝 ComputeLibrary

git clone https://github.com/ARM-software/ComputeLibrary.git  
git checkout v18.05

2.編譯 ComputeLibrary

apt-get install scons
scons Werror=1 -j4 debug=0 asserts=1 neon=0 opencl=1 embed_kernels=1 os=linux arch=arm64-v8a

3.修改 tengine 的 makefile.config 文件

1.使用Arm64
# Set the target arch 
CONFIG_ARCH_ARM64=y
2.使用GPU
# Enable GPU support by Arm Computing Library
CONFIG_ACL_GPU=y
3.不使用BLAS
# Use BLAS as the operator implementation
# CONFIG_ARCH_BLAS=y
4.指定ACL庫的路徑(注意路徑是否正確)
# Set the path of ACL 
ACL_ROOT=/home/firefly/ComputeLibrary
5.使用caffe模型
# Enable other serializers 
CONFIG_CAFFE_SERIALIZER=y

4.進(jìn)行 make

make

5.進(jìn)行安裝

make install

6.檢查

./build/tests/bin/bench_sqz -d acl_opencl

? ? ? ? 對我們的 樣例 進(jìn)行修改概而。
1.修改 "CMakeLists.txt" 文件

cd examples/mobilenet_ssd
leafpad CMakeLists.txt
1.加入 tengine 路徑
# 設(shè)置 tengine 路徑
set( TENGINE_DIR /home/firefly/tengine )

2.添加 build 文件

mkdir build
cd build

3.進(jìn)行 cmake 編譯

cmake ..

4.進(jìn)行 make 編譯

make

5.設(shè)置使用 GPU 參數(shù)(將GPU頻率設(shè)置為 800000000)

sudo su
echo "performance" >/sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/governor
cat /sys/devices/platform/ff9a0000.gpu/devfreq/ff9a0000.gpu/cur_freq
命令行輸入以下信息(設(shè)置臨時環(huán)境變量)
# 
export GPU_CONCAT=0
# 使能GPU fp16
export ACL_FP16=1
# 設(shè)置重復(fù)次數(shù)
export REPEAT_COUNT=5
# 運行
taskset 0x1 ./MSSD -d acl_opencl

顯示如下:

firefly@firefly:~/tengine/examples/mobilenet_ssd/build$ export GPU_CONCAT=0
firefly@firefly:~/tengine/examples/mobilenet_ssd/build$ export ACL_FP16=1
firefly@firefly:~/tengine/examples/mobilenet_ssd/build$ export REPEAT_COUNT=5
firefly@firefly:~/tengine/examples/mobilenet_ssd/build$ taskset 0x1 ./MSSD -d acl_opencl
/home/firefly/tengine/examples/mobilenet_ssd/build/MSSD
proto file not specified,using /home/firefly/tengine/models/MobileNetSSD_deploy.prototxt by default
model file not specified,using /home/firefly/tengine/models/MobileNetSSD_deploy.caffemodel by default
image file not specified,using /home/firefly/tengine/tests/images/ssd_dog.jpg by default
ACL Graph Initialized
Driver: ACLGraph probed 1 devices
tensor: detection_out created by node: detection_out is not consumed
add the node: detection_out into output list
load model done!
--------------------------------------
repeat 5 times, avg time per run is 165.676 ms
detect result num: 3 
dog :100%
BOX:( 138.419 , 209.091 ),( 324.504 , 541.568 )
car :100%
BOX:( 467.356 , 72.9224 ),( 687.269 , 171.123 )
bicycle :100%
BOX:( 107.053 , 140.221 ),( 574.472 , 415.248 )
======================================
[DETECTED IMAGE SAVED]: [save.jpg]
======================================
Release Graph Executor for graph graph
Release workspace default resource

完成任務(wù)4。


附比較 RK3399 和 筆記本 時間上的差距

1.RK3399 不使用 GPU 的情況下:

repeat 1 times, avg time per run is 197.33 ms

2.RK3399 使用 GPU的情況下:

repeat 5 times, avg time per run is 165.676 ms

3.筆記本使用 BLAS 庫的情況下

repeat 1 times, avg time per run is 133.117 ms

GPU 的使用囱修,對RK3399有明顯的加速赎瑰。
與官方給的 mssd 。


github中官方對mssd的結(jié)果
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蔚袍,一起剝皮案震驚了整個濱河市乡范,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌啤咽,老刑警劉巖晋辆,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異宇整,居然都是意外死亡瓶佳,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進(jìn)店門鳞青,熙熙樓的掌柜王于貴愁眉苦臉地迎上來霸饲,“玉大人,你說我怎么就攤上這事臂拓『衤觯” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵胶惰,是天一觀的道長傻工。 經(jīng)常有香客問我,道長孵滞,這世上最難降的妖魔是什么中捆? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮坊饶,結(jié)果婚禮上泄伪,老公的妹妹穿的比我還像新娘。我一直安慰自己匿级,他們只是感情好蟋滴,可當(dāng)我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著根蟹,像睡著了一般脓杉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上简逮,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天球散,我揣著相機(jī)與錄音,去河邊找鬼散庶。 笑死蕉堰,一個胖子當(dāng)著我的面吹牛凌净,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屋讶,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼冰寻,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了皿渗?” 一聲冷哼從身側(cè)響起斩芭,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎乐疆,沒想到半個月后划乖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡挤土,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年琴庵,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片仰美。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡迷殿,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出咖杂,到底是詐尸還是另有隱情庆寺,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布诉字,位于F島的核電站止邮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏奏窑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一屈扎、第九天 我趴在偏房一處隱蔽的房頂上張望埃唯。 院中可真熱鬧,春花似錦鹰晨、人聲如沸墨叛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽漠趁。三九已至,卻和暖如春忍疾,著一層夾襖步出監(jiān)牢的瞬間闯传,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工卤妒, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留甥绿,地道東北人字币。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像共缕,于是被迫代替她去往敵國和親洗出。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內(nèi)容