openvino的使用记录
记录自己openvino的使用
ubuntu 安装 openvino
openvino在ubuntu上的安装过程
参考链接:https://docs.openvinotoolkit.org/cn/latest/openvino_docs_install_guides_installing_openvino_linux.html
安装过程
- 安装openvino安装包
./install_GUI.sh
- 安装外部依赖软件
cd /opt/intel/openvino/install_dependencies
sudo -E ./install_openvino_dependencies.sh
- 设置环境变量
虽然官方有个一键脚本设置,但这样设置会跟你系统opencv起冲突,所以我只设了openvino相关lib库路径:
修改/etc/ld.so.conf
/opt/intel/openvino/deployment_tools/ngraph/lib
/opt/intel/openvino/deployment_tools/inference_engine/lib/intel64
/opt/intel/openvino/deployment_tools/inference_engine/external/tbb/lib
/opt/intel/openvino/inference_engine/external/mkltiny_lnx/lib
最后sudo ldconfig
-
配置模型转换工具环境
因为我只用onnx转换,然后onnx转换工具的环境依赖其实就是onnx,只需要在conda环境下安装一个onnx即可 -
计算棒相关依赖
sudo usermod -a -G users "$(whoami)"
sudo cp /opt/intel/openvino/inference_engine/external/97-myriad-usbboot.rules
/etc/udev/rules.d/
sudo udevadm control --reload-rules
sudo udevadm trigger
sudo ldconfig
然后重启
通过docker来使用openvino
直接在dockerhub 搜索 openvino,获取openvino_dev的镜像
从 Tags 中选择 自己想要的 openvino版本
docker pull openvino/ubuntu18_dev:2021.2
docker run --user root --restart=always --privileged -d --name openvino -p 3333:22 --ipc=host -i -t -v /home:/home openvino/ubuntu18_dev:2021.2 /usr/sbin/sshd -D
注意
https://github.com/openvinotoolkit/model_server/blob/master/docs/docker_container.md#building-the-image
如果想要在计算棒上使用 openvino,请使用openvino2020.3及以下版本,另外 docker 运行镜像时 需要 加上 -v /dev:/dev
openvino 的模型说明
openvino模型分为 xml 和 bin 文件,xml文件是模型文件,bin文件为权重文件。
openvino模型文件xml初步解析
xml模型分3个部分:
- layers : 记录了网络所有层
- edges : 记录了层之间数据的输入和输出
- meta_data : 记录了模型转换的一些信息
layers
layer有id name type version属性,id是编号,name是网络层名字,type是网络层类型.
type="Result"的层是输出层,输出层示例:
<layer id="333" name="indexs" type="Convert" version="opset1">
<data destination_type="I64"/>
<input>
<port id="0">
<dim>200</dim>
<dim>3</dim>
</port>
</input>
<output>
<port id="1" precision="I32">
<dim>200</dim>
<dim>3</dim>
</port>
</output>
</layer>
<layer id="334" name="selected_indices/sink_port_0" type="Result" version="opset1">
<input>
<port id="0">
<dim>200</dim>
<dim>3</dim>
</port>
</input>
</layer>
注意:调用openvino接口获取模型输出的名字时得到的是indexs而并非selected_indices/sink_port_0
edges
我理解的edge是模型之间数据的传递的记录信息,举例说明:
<edge from-layer="333" from-port="1" to-layer="334" to-port="0"/>
333层的输出 port1,是334层的输入 port0
openvino模型转换的一个坑(我觉得是个坑)
openvino的模型转换其实就是记录一个图的所有流向,然后所有流向的终点就为输出(这就是一个很大的坑).举例说明:
confidences = F.softmax(confidences, dim=2)
probs0,probs1 = torch.split(confidences,1,2)
return probs1
原始模型的输出是probs1,然而openvino转换的模型会有两个输出probs0和probs1
对于转换后的IR与转换前的IR的结果不匹配问题有3种方法解决
- 修改xml文件
- 修改模型导出代码
- 修改c++ 部署代码 设置自己想要的输出
曾经遇到的问题
-
NonMaxSuppression结果异常
在 2020.04的openvino上 导出带nms的onnx然后转换成openvino的模型,推理时最多只得到了一个结果,原因未知,不确定是否是因为openvino版本不同(因为之前使用2020.01版本时 nms结果输出正常) 还是openvino的nms只支持不归一化处理的boxes 或者其他未知原因,目前靠c++实现了nms。 -
split 初始化 报错问题
在 2020.04上,如果对一个tensor 进行切片操作多次,并且正好切出的子tensor 合并起来就是原始tensor的话, openvino 会做图优化,将这些slice操作合并成split操作,然而我就遇到了初始化报错split的问题。
解决方法:使用gather或者index_select 代替 切片的操作。
openvino 动态batch
参考链接: https://docs.openvinotoolkit.org/latest/openvino_docs_IE_DG_DynamicBatching.html
动态批处理功能使您可以在预设的批处理大小限制内动态更改推理调用的批处理大小。 如果事先不知道批次大小,并且由于资源限制,不希望使用或无法使用较大的批次大小,则此功能可能很有用。 例如,具有人的年龄,性别或情绪识别的面部检测是典型的使用场景。
用法
您可以通过在加载网络时传递给插件的配置图中将KEY_DYN_BATCH_ENABLED标志设置为YES来激活动态批处理。 此配置创建一个ExecutableNetwork对象,该对象将允许使用SetBatch() 方法在其所有推断请求中动态设置批处理大小。 在传递的CNNNetwork对象中设置的批量大小将用作最大批量大小限制。
这是一个代码示例:
int dynBatchLimit = FLAGS_bl; //take dynamic batch limit from command line option
// Read network model
InferenceEngine::Core core;
InferenceEngine::CNNNetwork network = core.ReadNetwork("sample.xml");
// enable dynamic batching and prepare for setting max batch limit
const std::map<std::string, std::string> dyn_config =
{ { InferenceEngine::PluginConfigParams::KEY_DYN_BATCH_ENABLED, InferenceEngine::PluginConfigParams::YES } };
network.setBatchSize(dynBatchLimit);
// create executable network and infer request
auto executable_network = core.LoadNetwork(network, "CPU", dyn_config);
auto infer_request = executable_network.CreateInferRequest();
// ...
// process a set of images
// dynamically set batch size for subsequent Infer() calls of this request
size_t batchSize = imagesData.size();
infer_request.SetBatch(batchSize);
infer_request.Infer();
// ...
// process another set of images
batchSize = imagesData2.size();
infer_request.SetBatch(batchSize);
infer_request.Infer();
局限性
当前,存在使用动态批处理的某些限制:
- 仅对CPU和GPU插件使用动态批处理。
- 在仅包含某些层的拓扑上使用动态批处理:
Convolution Deconvolution Activation LRN Pooling FullyConnected SoftMax Split Concatenation Power Eltwise Crop BatchNormalization Copy
不要使用可能会随意改变张量形状的图层(例如Flatten,Permute,Reshape),特定于对象检测拓扑的图层(ROIPooling,ProirBox,detectionOutput)以及自定义图层。 在将网络加载到插件的过程中执行拓扑分析,如果拓扑不适用,则会生成异常。
自己测试
作动态batch 官方说不支持的层,但自己测试却没有报错
Reshape
Flatten
单独只导出一个op作 动态batch 测试,发现以下op不支持
permute (Transpose)