在iOS或Android中集成Caffe2
以下内容翻译自 Integrating Caffe2 on iOS/Android
Caffe2针对移动集成进行了优化,灵活,易于更新,并且能够运行在低功耗设备上。 本文将介绍如何在移动项目中实现Caffe2。
相机演示项目
如果您希望在移动端看到可行的Caffe2实施(仅限目前的Android),请查看此演示项目。
AI Camera Demo
摘要
- 将模型分配给设备(Asset Pipeline,移动端配置等)。
- 实例化caffe2::Predictor实例(iOS)或Caffe2实例(Android)以将模型展示给您的代码。
- 将输入传递给模型,返回输出。
关键类
- caffe2::NetDef ——(通常是二进制序列化的)Google Protobuf实例,封装了计算图和预训练权重。
- caffe2::Predictor——通过一个“初始化”NetDef和一个“预测”NetDef实例化的有状态类,并使用输入执行“预测”NetDef并返回输出。
库架构
Caffe2由以下组成:
- 核心库,由Workspace、Blob、Net和Operator类组成。
- 运算符库,一系列运算符实现(如卷积等)
它是纯C++的,唯一的非可选依赖关系是:
- Google Protobuf(精简版,〜300kb)
- Eigen是某些原语所需要的BLAS库(在Android上),一个向量化的向量/矩阵操作库,Eigen是ARM中最快的基准。
对于某些用例,您还可以塞入NNPACK,这特别优化了ARM上的卷积。它是可选的(但推荐)。
错误处理是通过抛出异常,通常是caffe2::EnforceNotMet,它继承自std::exception。
直观概述
模型由两部分组成:代表学习参数(训练期间更新)的一组权重(通常为浮点数),以及一组构成计算图的“操作”,表示如何将输入数据(随每个图通过而变化)与学习参数(不随每个图通过变化)组合起来。参数(和计算图中的中间状态存在于Workspace中,它基本上是一个std::unordered_map<string,Blob>
,其中Blob
表示任意类型的指针,通常是TensorCPU
,它是一个n维数组(一个Python的numpy ndarray
,Torch的Tensor
等)。
核心类是caffe2::Predictor,它展示了构造函数:
Predictor(const NetDef& init_net, const NetDef& predict_net)
其中两个NetDef输入是表示上述两个计算图的Google协议缓冲区对象—— init_net
通常运行一组将权重反序列化到Workspace中的操作,而predict_net
指定如何为每个输入执行计算图。
使用注意事项
Predictor是一个有状态的类——通常,流程将实例化该类一次,并在多次请求中重用。 根据用例,安装开销可能是微不足道的或不容忽视的。构造函数执行以下操作:
- 构造工作区对象
- 执行
init_net
,分配内存并设置参数的值。 - 构造
predict_net
(将caffe2::NetDef 映射到caffe2::NetBase实例(通常为caffe2::SimpleNet)。
一个关键点是,所有的初始化在某种意义上是“静态”可验证的——如果构造函数在一台机器上失败(通过抛出异常),那么它在每台机器上总是会失败。在导出NetDef实例之前,请验证Net构造是否可以正确执行。
性能考虑
目前,Caffe2针对具有NEON的ARM CPU(自2012年起基本为任何ARM CPU)进行了优化。 也许令人惊讶的是,ARM CPU的性能优于板载GPU(在老于iPhone 6的设备上我们的NNPACK ARM CPU实现优于苹果的MPSCNNConvolution)。将计算卸载到GPU/DSP上还有其他优势,并且我们正在积极开展Caffe2中的这些工作。
对于卷积实现,建议使用NNPACK,因为它比大多数框架中使用的标准im2col/sgemm
实现要快得多(约2x3x)。 建议将OperatorDef::engine
设置为NNPACK。 例:
def pick_engines(net):net = copy.deepcopy(net)for op in net.op:if op.type == "Conv":op.engine = "NNPACK"if op.type == "ConvTranspose":op.engine = "BLOCK"return net
对于非卷积(例如排序)工作负载,关键计算基元通常是全连接层(例如Caffe2中的FullyConnectedOp,Caffe中的InnerProductLayer,Torch中的nn.Linear)。对于这些用例,您可以切回到BLAS库,特别是加速iOS上的Accelerate和Android上的Eigen。
内存考虑
实例化和运行Predictor模型的内存使用量是它的权重和激活的总和。没有分配“静态”内存,所有分配都与Predictor拥有的Workspace实例相关联,所以在删除所有Predictor实例后,应该不会再占用内存。
在导出运行之前,推荐使用以下命令:
def optimize_net(net):optimization = memonger.optimize_interference(net,[b for b in net.external_input] +[b for b in net.external_output])try:# This can fail if the blobs aren't in the workspace.'stats = memonger.compute_statistics(optimization.assignments)print("Memory saving: {:.2f}%".format(float(stats.optimized_nbytes) / stats.baseline_nbytes * 100))except Exception as e:print(e)return pick_engines(share_conv_buffers(rename_blobs(optimization.net)))
这将自动共享在图的拓扑顺序中有效的激活(有关更详细的讨论,请参阅Predictor)。
iOS上的启动注意事项
Caffe2使用注册表模式来注册运算符类。宏位于核心运算符operator.h的运算符注册表部分:
// The operator registry. Since we are not expecting a great number of devices,
// we will simply have an if-then type command and allocate the actual
// generation to device-specific registerers.
// Note that although we have CUDA and CUDNN here, the registerers themselves do
// not depend on specific cuda or cudnn libraries. This means that we will be
// able to compile it even when there is no cuda available - we simply do not
// link any cuda or cudnn operators.
CAFFE_DECLARE_REGISTRY(CPUOperatorRegistry,OperatorBase,const OperatorDef&,Workspace*);
#define REGISTER_CPU_OPERATOR_CREATOR(key, ...) \CAFFE_REGISTER_CREATOR(CPUOperatorRegistry, key, __VA_ARGS__)
#define REGISTER_CPU_OPERATOR(name, ...) \CAFFE_REGISTER_CLASS(CPUOperatorRegistry, name, __VA_ARGS__)
#define REGISTER_CPU_OPERATOR_STR(str_name, ...) \CAFFE_REGISTER_TYPED_CLASS(CPUOperatorRegistry, str_name, __VA_ARGS__)#define REGISTER_CPU_OPERATOR_WITH_ENGINE(name, engine, ...) \CAFFE_REGISTER_CLASS(CPUOperatorRegistry, name##_ENGINE_##engine, __VA_ARGS__)
并使用,例如conv_op.cc:
REGISTER_CPU_OPERATOR(Conv, ConvOp<float, CPUContext>);
REGISTER_CPU_OPERATOR(ConvGradient, ConvGradientOp<float, CPUContext>);
在iOS或Android中集成Caffe2相关推荐
- Android中集成Jpush实现推送消息通知与根据别名指定推送附示例代码下载
场景 经常会有后台服务向Android推送消息通知的情况. 实现 首先在Android Studio中新建一个Android应用 在Project根目录的build.gradle中配置了jcenter ...
- [html] 怎样去除iOS和Android中的输入URL地址的控件条呢?
[html] 怎样去除iOS和Android中的输入URL地址的控件条呢? setTimeout(scrollTo,0,0,0); 个人简介 我是歌谣,欢迎和大家一起交流前后端知识.放弃很容易, 但坚 ...
- Android中集成第三方库的方法和问题
Android中集成第三方库的方法和问题 声明: 1. 本文參考了网上同学们的现有成果,在此表示感谢,參考资料在文后有链接. 2. 本文的重点在第三部分,是在开发中遇到的问题及解决的方法.第一,第二部 ...
- Android中集成高德地图SDK实现地图定位和导航功能(二)
我们接着上一篇文章开始继续实现android中集成高德地图的SDK实现地图 定位,搜索,导航的功能 如何让地图在手机上实现呢? 1.配置AndroidManifest 中的权限申请 可以参考官方文档 ...
- Android中集成高德地图SDK实现地图定位和导航功能(一)
一.前期准备工作 1.在高德地图开发者平创建一个自己的项目 名称和应用类型随便填 2.添加Key 1.添加key 2.获取SHA1值 2.1.使用windwos+R 输入cmd 打开控制窗口 输入 w ...
- aes c android ios,AES加密在iOS和Android中产生不同的结果
尝试使用AES128算法加密样本数据,在 Android和iOS中使用CBC和PKCS7填充,但结果不同:( Android代码: private static final byte[] KEY = ...
- Android中集成支付宝
手机的在线支付,被认为是2012年最看好的功能,我个人认为这也是移动互联网较传统互联网将会大放光彩的一个功能. 人人有手机,人人携带手机,花钱买东西,不再需要取钱付现,不再需要回家上网银,想买什么,扫 ...
- ios 跨域_如何在iOS和Android中建立跨域通信桥
ios 跨域 I was working on a certain project at work, in which I needed to connect several varying comp ...
- android中集成阿里云金融级实人认证
上个项目中有用到过这个,现在又要用到,每次都是到官网去看文档去集成,特此记录一下集成的步骤 第一步:打开官网文档阿里云金融级实人认证Android接入文档 去下载最新的sdk,集成到项目中 第二步在需 ...
最新文章
- DOS批处理的字符串功能
- 图像旋转的MATLAB和OpenCV源码
- 文本分类--情感分析
- oracle表重命名 索引,CSS_在Oracle数据库中按用户名重建索引的方法,如果你管理的Oracle数据库下某 - phpStudy...
- 剑指offer面试题[4]-空格替换
- 事务的acid属性是指_Mysql事务的性质 为什么要用事务?
- 7.软件架构设计:大型网站技术架构与业务架构融合之道 --- 框架、软件与中间件
- Unity基础——碰撞体
- sony媒体服务器文件不对,索尼Z280断电MXF变成RSV文件完美修复
- 发动机冒黑烟_发动机冒黑烟常见的24个原因和解决方法
- 关于Oppen Live Writer中插入可折叠着色代码的插件
- 此windows副本不是正版_阳光单职业传奇正版-阳光单职业传奇正版官网版v2.0
- 2021西湖论剑网络安全大赛部分WP
- 2022年最新的Detectron 2 (0.6) 安装流程(联想笔记本Y9000K+Anaconda+Win 11 +RTX3070)
- XV6实验-Lab1 Syscalls
- 电子邮箱哪个好用又安全?
- windows 批量 jpg 转 bmp 方法
- pytorch distiller Weights Pruning Algorithms
- 离群值(异常值)处理
- 做外贸有没有好的软件?