oneDNN 执行提供程序
前身为“DNNL”
使用 Intel oneDNN 执行提供程序,利用英特尔® 深度神经网络数学核心库 (Intel® DNNL) 优化的原语,加速 ONNX Runtime 的性能。
英特尔® oneAPI 深度神经网络库是面向深度学习应用的开源性能库。该库在英特尔® 架构和英特尔® 处理器显卡架构上加速深度学习应用和框架。Intel DNNL 包含矢量化和线程化的构建块,您可以使用 C 和 C++ 接口来实现深度神经网络 (DNN)。
ONNX Runtime 的 oneDNN 执行提供程序 (EP) 由英特尔和微软合作开发。
目录
构建
有关构建说明,请参阅构建页面。
用法
C/C++
DNNLExecutionProvider 执行提供程序需要在 ONNX Runtime 中注册,才能在推理会话中启用。
Ort::Env env = Ort::Env{ORT_LOGGING_LEVEL_ERROR, "Default"};
Ort::SessionOptions sf;
bool enable_cpu_mem_arena = true;
Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_Dnnl(sf, enable_cpu_mem_arena));
C API 详细信息请参阅此处。
Python
当使用通过 DNNL 执行提供程序构建的 ONNX Runtime 中的 python wheel 时,它将自动优先于 CPU 执行提供程序。Python API 详细信息请参阅此处。
子图优化
DNNL 使用分块布局(例如:nhwc,通道按 16 分块 - nChw16c)以利用使用 AVX512 的向量运算。为了获得最佳性能,我们避免重新排序(例如,Nchw16c 到 nchw)并将分块布局传播到下一个原语。
子图优化通过以下步骤实现此目的。
- 解析 ONNX Runtime 图并创建子图的内部表示。
- 子图运算符 (DnnlFunKernel) 迭代 DNNL 节点并创建向量 DNNL Kernels
- DnnlFunKernel 的计算函数迭代并将数据绑定到向量中的 DNNL 原语,并提交向量以供执行。
子图 (IR) 内部表示
DnnlExecutionProvider::GetCapability() 解析 ONNX 模型图并创建 DNNL 运算符子图的 IR(内部表示)。每个子图都包含一个向量 DnnlNodes、输入、输出及其所有 DnnlNodes 的属性。可能存在同名的属性。因此,我们在属性名称前加上节点名称及其索引。子图的唯一 ID 设置为属性。
DnnlNode 具有指向其输入和输出的索引以及指向其父节点的指针。DnnlNode 直接从其父级读取分块内存,以避免数据重新排序。
子图类
DnnlConv、DnnlPool 等原语派生自 DnnlKernel 基类。
以下 UML 图捕获了子图类。
子图执行
DnnlExecutionProvicer::Compute() 函数创建 DnnlFuncKernel 并调用其计算函数。
DnnlFuncKernel::Compute 函数创建 SubgraphPrimitve 池并将对象添加到映射。
SubgraphPrimitve 构造函数调用以下成员函数
SubgraphPrimitve::CreatePrimitives()
for (auto& mklnode : mklnodes) {
if (mklnode.name == "Conv") {
kernel.reset(new DnnlConv());
kernels.push_back(kernel);
} else if (mklnode.name == "BatchNormalization-Relu") {
kernel.reset(new DnnlBatchNorm());
context_.kernels.push_back(kernel);
} else if (mklnode.name == "MaxPool") {
kernel.reset(new DnnlPool());
context_.kernels.push_back(kernel);
}
.
.
.
在 CreatePrimitives 方法中,我们迭代 DnnlNodes 并创建 DnnlKernel 对象,并将 DNNL 原语添加到向量中。它还会读取属性。这仅在第一次迭代时完成一次。
SubgraphPrimitve::Compute()
for (auto& kernel : kernels) {
kernel->Bind(input_tensors, output_tensors);
}
stream->submit(net);
在 SubgraphPrimitve::Compute() 方法中,我们遍历 Dnnl Kernels 并绑定输入数据。然后,我们将原语向量提交到 DNNL 流。
支持范围
支持的操作系统
- Ubuntu 16.04
- Windows 10
- Mac OS X
支持的后端
- CPU