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)境特征的斯嚎。
? ? ? ?運行該程序:
? ? ? ?所以我們已經(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 目錄下)
任務(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 。