现在越来越多的人选择Mxnet作为深度学习框架,相应的中文社区非常活跃,而且后面推出的gluon以及gluoncv非常适合上手和实验,特别是gluoncv中提供了非常多、非常新的预训练model zoo,比如像yolov3这种~~不过网上(包括Mxnet社区、gluon论坛等等)大多是关于Python版本的话题,关于C++版本的资料却非常少,最近在用C++版本的mxnet,进行人脸检测和识别,踩到不少的坑,在这里总结一下。

1.C++版本的Mxnet需要进行手动编译,里面有不同的数学计算加速方式,比如MKL,MKLDNN或者openblas(前者主要针对Intel的cpu架构,后者是一个比较通用的线性代数优化库,MKLDNN针对神经网络进行优化)等等,编译完成之后可以使用里面的c_api,即#include <mxnet/c_predict_api.h>或者使用提供的cpp的api:#include "mxnet-cpp/MxNetCpp.h"。

2.如果手动编译过Mxnet会发现Mxnet实际上是好几个项目的集合,比如NNVM,mshadow,dmlc等等,后端引擎负责真正的计算部分,前端实现接口调用,而且作者花了大部分精力围绕在Python接口的编写上,所以关于Python方面的接口非常多,而像C、C++的接口真的很少,不过Mxnet是一个经常进行更新的项目,所以以后是否会完善这些拭目以待。

3.性能时间度量。以下:

(1)一定要注意mxnet前端语言可能会异步调用后端的计算结果,以Python为例,当你使用CPU对比较深的resnet模型进行一次预测,有时发现耗仅仅数毫秒,而在后面的asnumpy时却使用了上百毫秒。避免这种情况出现的最好方式就是使用mxnet.ndarray.waitall(),强制等待前面的操作执行完成;

(2)很多操作第一次都会比较耗时,比如load参数到内存,甚至像opencv中的resize有时第一次也会比较耗时,所以如果想公平的统计某一时段的时间开销,最好是先手动执行一次,然后跑多个loop取平均值进行比较。有些同学拿imread一次预测然后统计时间,这样的话相当于把load参数等相关开销都计算在内了,这是不适合的;

(3)关于batch操作。不止训练阶段有batch操作,预测(predict或者inference)也有,比如做人脸识别,需要把检测出来的多个人脸的bounding box的图像分别抠出来然后组成一个batch,这时候识别网络的输入就是batch_num x channel x high x width。为什么需要进行batch操作?假如我们使用GPU,很明显可以进行cuda并行计算大大加快处理速度;如果使用CPU的话某些数学优化库也会让这个速度有一定提升,不过相比较而言不是非常明显;使用batch操作非常需要注意的是一定要考虑内存是否足够,实际处理的时候要评估一下最大的batch数目,否则很容易out of memory;

4.关于Mxnet C/C++的预测,一般用MXPredCreate创建识别引擎PredictorHandle,然后使用MXPredSetInput设置输入,用MXPredForward进行预测,一定要注意的是创建的PredictorHandle在使用完之后一定别忘调用MXPredFree释放,否则跑多次内存会泄漏的非常快。另外要注意C/C++提供的api中,预测的时候MXPredSetInput设置的参数维度是固定的,比如当你的batch数变化的时候PredictorHandle也需要改变,为了feed不同的输入,可以用MXPredReshape重新改变batch_num x channel x high x width的输入形状,而不需要每次重新load参数再调MXPredCreate,因为MXPredCreate的开销非常大,相比较而言MXPredReshape的开销小一些。但MXPredReshape也并不是一点开销没有,当你需要识别的人脸数的batch一直在变,频繁的reshape形状毫无疑问开销就会显得比较大,这样就有一个问题:怎么在使用loop进行识别(也就是对于每个人脸都丢进网络里,输入是1 x channel x high x width识别完一个再接着下一个)和batch方式(输入是batch_num x channel x high x width)之间进行权衡?我觉得一方面要考虑使用的网络在使用batch时到底能提升多大,一方面也需要考虑MXPredReshape本身的开销,比如我们可以设置一个batch数的阈值,当大于这个值的时候进行MXPredReshape,否则直接循环进行预测。

使用C++版本Mxnett进行预测的注意事项的更多相关文章

  1. IOS中多版本,多设备类型支持注意事项

    IOS系统从07年出来,到现在也有6年了,每年发布一次到两次新的设备,从iPhone1,iPhone2 ... iPhone4s再到最新的iPhone5.硬件在升级的过程中CPU的架构也可能发生变化, ...

  2. 基于vs2005以上版本Qt程序发布的注意事项(讲了manifest的问题)

    最近发现了一个非常恼人的程序deployment的问题,估计大家有可能也会遇到,特此memo. 问题的出现我觉得主要还是微软搞的花头太多, 一个不知所谓的manifest文件让本来简单的程序发布变得困 ...

  3. spark1.2.0版本SparkSQL使用parquet类型注意事项

    在Spark1.2.0版本中是用parquet存储类型时注意事项: sql语句: select * from order_created_dynamic_partition_parquet; 在spa ...

  4. 不同OpenCV版本和不同VS版本之间进行配置的注意事项

    下面内容为不同系统和不同版本VS+不同版本OpenCV之间进行配置时的注意事项.本教程中开始提到如果VS版本和OpenCV版本相匹配的话,只要按上述步骤配置都是没有问题的.但是如果说版本不匹配的话,就 ...

  5. 绿色安装MySQL5.7版本----配置my.ini文件注意事项

    前言 由于前段时间电脑重装,虽然很多软件不在C盘,但是由于很多注册表以及关联文件被删除,很多软件还需要重新配置甚至卸载重装. 使用MySQL时就遇到了这种情况,在修改配置文件无效的情况下选择了重新安装 ...

  6. 高版本jQuery设置checkbox状态注意事项

    jQuery 1.9 以后, 使用 .attr(“checked”, true) 或  attr(“checked”, “checked”) 将无法正确设置 checkbox的状态, 同样的, 使用 ...

  7. 如何选择 SQL Server 数据库跟操作系统版本

    简介: 今天老大提需求, 需要一台 Windows 服务器, 需要安装最新版的 SQL Server 数据库.额, 上次搞 Windows 服务器还是4年前的事. 一.啥也没查, 直接下载操作系统.做 ...

  8. Erda 1.1 版本发布|3 大亮点特性最新解读

    来源|尔达 Erda 公众号 ​ Erda v1.1 Changelog: https://github.com/erda-project/erda/blob/master/CHANGELOG/CHA ...

  9. Netty未来展望

    作为<Netty权威指南(第2版)>的结尾章节,和读者朋友们一起展望下Netty的未来. 1应用范围 随着大数据.互联网和云计算的发展,传统的垂直架构逐渐将被分布式.弹性伸缩的新架构替代. ...

随机推荐

  1. dubbo知识体系

    Dubbo负载均衡 Random随机/ RoundRobin轮询/ LeastActive最少Dubbo缓存Dubbo集群容错 Dubbo回调 服务分组: group Dubbo异步调用 <du ...

  2. Tigase 发送消息的流程源码分析

    XMPP 的<message/>节是使用基本的”push”方法来从一个地方到另一个地方得到消息.因为消息通常是不告知的,它们是一种”fire-and-forget”(发射后自寻目的)的机制 ...

  3. 进军的socket

    在学socket有时候我们会遇到这种问题: 解决方法一: 在服务端中加入:severTCP.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ...

  4. 关于PHP架构师进阶的一些思考

    相信大家都有感觉,就是当程序员写业务写了几年后,就会有想进阶的想法,技术方面当然就是架构师了,然后具体从哪些方面丰富自己才能个达到目的呢?大部分人可能会很迷茫,当然也包括我, 最近和很多大牛交流了一些 ...

  5. HTML5-之workers(多线程执行)

    注:test.js 不涉及DOM元素

  6. UVA 2290 Transmitters

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  7. C# WPF 通过委托实现多窗口间的传值

    在使用WPF开发的时候就不免会遇到需要两个窗口间进行传值操作,当然多窗口间传值的方法有很多种,本文介绍的是使用委托实现多窗口间的传值. 在上代码之前呢,先简单介绍一下什么是C#中的委托(如果只想了解如 ...

  8. 通过HashSet达到对象集去重的实现(jdk1.8)

    通过HashSet达到对象集去重的实现(jdk1.8) public class Contract { private String contractId; private String contra ...

  9. 在centos7上配置jenkins

    在Linux(centos7)环境下配置jenkins,并用github作为仓库. 配置jenkins https://blog.csdn.net/wangfei0904306/article/det ...

  10. linux系统下部署DNS正向解析

    DNS服务概述: DNS(Domain Name System)域名系统,能够提供域名与IP地址的解析服务. 正向解析 正向解析是指域名到IP 地址的解析过程. 部署DNS正向解析 DNS服务的三个配 ...