首先先一目了然看一下其目录结构(这些个源码可以在github上下载到,只要在GitHub搜索mace即可):
介绍
MACE(Mobile AI Compute Engine)是一个针对移动异构计算平台优化的深度学习推理框架。MACE提供工具和文档,帮助用户将深度学习模型部署到移动电话、平板电脑、个人电脑和物联网设备上。
架构
下图显示了整个体系结构
MACE模型
MACE定义了与Caffe2类似的自定义模型格式。MACE模型能够转换TensorFlow、Caffe或ONNX的导出模型。
MACE解释器
Mace解释器主要对NN图进行解析,并对图中的张量进行管理。
运行时
CPU/GPU/DSP运行时对应于不同设备的操作。
工作流程
下图显示了MACE的基本工作流程。
- 配置模型部署文件
模型部署配置文件(.yml)描述了模型和库的信息,MACE将基于该文件构建库。
- 生成库
建立MACE动态或静态库。
- 转换模型
将TensorFlow、Caffe或ONNX模型转换为MACE模型。
- 部署
将MACE库集成到应用程序中,并使用MACE API运行。
- 运行(CLI)
MACE提供了MACE_run命令行工具,可用于运行模型,并根据最初的TensorFlow或Caffe结果验证模型的正确性。
- 基准
MACE提供了基准测试工具来获取模型的操作级分析结果。
浏览一下源码
docker
文件夹是几个与docker
安装相关的文件。docs
文件夹是一些文档,与代码关系不大。third_party
和tools
文件夹是需要用到的一些第三方模块和代码构建、测试所用到的相关脚本。其中tools/converter.py
是构建代码的顶层脚本。
mace/public/mace.h
enum DeviceType { CPU = 0, GPU = 2, HEXAGON = 3, HTA = 4, APU = 5 };
enum class DataFormat {
NONE = 0, NHWC = 1, NCHW = 2,
HWOI = 100, OIHW = 101, HWIO = 102, OHWI = 103,
AUTO = 1000,
};
enum GPUPerfHint {
PERF_DEFAULT = 0,
PERF_LOW = 1,
PERF_NORMAL = 2,
PERF_HIGH = 3
};
enum GPUPriorityHint {
PRIORITY_DEFAULT = 0,
PRIORITY_LOW = 1,
PRIORITY_NORMAL = 2,
PRIORITY_HIGH = 3
};
mace.h
文件中定义了三个主要类:RunMetadata
、MaceTensor
和 MaceEngine.
RunMetadata:定义了一个public类型的变量 op_stats,类型为vector <OperatorStats>
MaceTensor: 定义了 MACE 输入输出 tensor,有几个不同形式的构造函数
MaceEngine: 作为 MACE 框架引擎,根据构造函数传入的DeviceType执行相应的功能代码
// MACE input/output tensor
class MACE_API MaceTensor {
friend class MaceEngine;
public:
// shape - the shape of the tensor, with size n, if shape is unknown
// in advance, it should be specified large enough to hold tensor of all
// possible size.
// data - the buffer of the tensor, must not be null with size equals
// shape[0] * shape[1] * ... * shape[n-1].
// If you want to pass a buffer which is unsuitable to use the default
// shared_ptr deleter (for example, the buffer is not dynamically
// allocated by C++, e.g. a C buffer), you can set customized deleter
// of shared_ptr and manage the life cycle of the buffer by yourself.
// For example, std::shared_ptr<float>(raw_buffer, [](float *){});
MaceTensor(const std::vector<int64_t> &shape,
std::shared_ptr<void> data,
const DataFormat format = DataFormat::NHWC);
MaceTensor();
MaceTensor(const MaceTensor &other);
MaceTensor(const MaceTensor &&other);
MaceTensor &operator=(const MaceTensor &other);
MaceTensor &operator=(const MaceTensor &&other);
~MaceTensor();
// shape will be updated to the actual output shape after running.
const std::vector<int64_t> &shape() const;
const std::shared_ptr<float> data() const;
std::shared_ptr<float> data();
template <typename T>
const std::shared_ptr<T> data() const {
return std::static_pointer_cast<T>(raw_data());
}
template <typename T>
std::shared_ptr<T> data() {
return std::static_pointer_cast<T>(raw_mutable_data());
}
DataFormat data_format() const;
private:
std::shared_ptr<void> raw_data() const;
std::shared_ptr<void> raw_mutable_data();
private:
class Impl;
std::unique_ptr<Impl> impl_;
};
class MACE_API MaceEngine {
public:
explicit MaceEngine(const MaceEngineConfig &config);
~MaceEngine();
MaceStatus Init(const NetDef *net_def,
const std::vector<std::string> &input_nodes,
const std::vector<std::string> &output_nodes,
const unsigned char *model_data);
MaceStatus Init(const NetDef *net_def,
const std::vector<std::string> &input_nodes,
const std::vector<std::string> &output_nodes,
const std::string &model_data_file);
MaceStatus Run(const std::map<std::string, MaceTensor> &inputs,
std::map<std::string, MaceTensor> *outputs);
MaceStatus Run(const std::map<std::string, MaceTensor> &inputs,
std::map<std::string, MaceTensor> *outputs,
RunMetadata *run_metadata);
private:
class Impl;
std::unique_ptr<Impl> impl_;
MaceEngine(const MaceEngine &) = delete;
MaceEngine &operator=(const MaceEngine &) = delete;
};