【嵌入式-TensorRT】TensorPriv代码解读
纵览
- cfgs //保存yaml - data //保存数据 - docs //说明文档 - tasks //各任务 |- cls |- f-track |- fairmot |- fcos |- yolov5 - tensorrt // 工具包和接口 main.cpp CMakeLists.txt
CMakeLists.txt
几个命令:
cmake_minimum_required() // 检查cmake的版本 project(tensor_priv) // 设置工程名 include() set() // 用于设定变量 variable 的值为 value file() // 把路径保存在变量中 message() // 输出信息 check_language() add_executable(<name> source1 source2 … sourceN) // 指定从一组源文件 source1 source2 … sourceN 使用gcc编译出一个可执行文件且命名为 name cuda_add_executable() // 类似,不过是用cuda编译器编译 find_package(<VAR> name1 [path1 path2 …]) find_library(<VAR> name1 [path1 path2 …]) find_path(<VAR> name1 [path1 path2 …]) // 用于查找包含包/库/文件 name1 的路径放入VAR include_directories($PATH) // 将PATH加入包含目录列表 link_directories($PATH) // 将PATH加入编译器链接阶段的搜索目录列表 target_link_libraries() // 将若干库文件链接到目标tensor_priv中,target_link_libraries里的库文件的顺序符合gcc/g++链接顺序的规则,即被依赖的库放在依赖它的库的后面,如果顺序有错,链接时会报错。
- Set variable for different ENV
- Package
- Set architecture and CUDA
- TensorRT
- Project source(Common sources/Tasks sources)
- Library and Executable(CUDA Compile/G++ Compile)
main.cpp
分块
分为三个代码块:初始化、不同任务开关设置参数、跑模型代码解读
2.1 初始化
// 在yaml-cpp包中的YAML命名空间的Node类型 namespace YAML { Node Clone(const Node& node) { NodeEvents events(node); NodeBuilder builder; events.Emit(builder); return builder.Root(); } } // namespace YAML YAML::Node main_cfg = YAML::LoadFile("../cfgs/tasks.yaml"); YAML::Node task = main_cfg["tasks"]; YAML::Node f_track_cfg, fcos_cfg, fairmot_cfg, cls_cfg, yolo_cfg; 类似python的: main_cfg = cfgNode("../cfgs/tasks.yaml") task = cfgNode(main_cfg["tasks"]) f_track_cfg, ... = cfgNode(), ... // 为各任务指派一个指针 F_track* f_track = nullptr; Fcos* fcos = nullptr; FairMOT* fairmot = nullptr; CLS* cls = nullptr; YOLOV5* yolo = nullptr;
工程越大,名称互相冲突性的可能性越大。另外使用多个厂商的类库时,也可能导致名称冲突。为了避免,在大规模程序的设计中,以及在程序员使用各种各样的C++库时,这些标识符的命名发生冲突,标准C++引入关键字namespace,可以更好地控制标识符的作用域。类比python不同类的同名成员变量/函数/子类。
2.2 不同任务参数设置
if (task["fcos"] && task["fcos"].as<bool>()){ // 提取对应main cfg的关键字cfg_file string cfg_file = main_cfg["fcos"]["cfg_file"].as<string>(); fcos_cfg = YAML::LoadFile(cfg_file); // 加载后建立Fcos类型的对象 fcos = new Fcos(fcos_cfg); }
2.3 跑模型
if(main_cfg["misc"]["multithreading"].as<bool>()) //是否开启多线程 auto thread_func_0 = [&](){ cv::Mat frame = imread(fairmot_cfg["inputs"]["img_path"].as<string>()); // 读取图片 int im_w = fairmot_cfg["inputs"]["width"].as<int>(); int im_h = fairmot_cfg["inputs"]["height"].as<int>(); cv::resize(frame, frame, cv::Size(im_w, im_h)); // 根据设置resize int batch_size = fairmot_cfg["engine"]["bchw"].as<vector<int>>()[0]; vector<cv::Mat> imgs; // 创造一个装图的vector for(int i = 0; i < batch_size; i++){ imgs.emplace_back(frame); // 按batchsize插入 } auto fairmot_results = fairmot->run(imgs); // 调用任务类对象的内部函数 }; TrackRes FairMOT::run(const vector<Mat>& imgs){ data_timer->start(); if (!prepareInputs(imgs)){ mLogger.logger("Prepare Input Data Failed!", logger::LEVEL::ERROR); } // 使用tasks预定义的函数处理 data_timer->click(); infer_timer->start(); mNet->ForwardAsync(mStream); // 调用RTengine跑前项 infer_timer->click(); post_timer->start(); auto results = processOutputs(); // 收集结果 post_timer->click(); mLogger.logger("Data time: ", data_timer->getTime(), logger::LEVEL::INFO); mLogger.logger("Infer time: ", infer_timer->getTime(), logger::LEVEL::INFO); mLogger.logger("Post time: ", post_timer->getTime(), logger::LEVEL::INFO); return results; }