CoreML 执行提供程序
Core ML 是 Apple 推出的一种机器学习框架。它旨在无缝高效地利用强大的硬件技术,包括 CPU、GPU 和神经网络引擎,以最大限度地提高性能,同时最大限度地减少内存和功耗。
目录
要求
CoreML 执行提供程序 (EP) 需要运行 iOS 13 或更高版本的 iOS 设备,或运行 macOS 10.15 或更高版本的 Mac 电脑。
建议使用配备 Apple 神经网络引擎的 Apple 设备以获得最佳性能。
安装
ONNX Runtime 针对 iOS 的 CoreML EP 预构建二进制文件已发布到 CocoaPods。
请参阅此处获取安装说明。
构建
有关 iOS 设备的构建说明,请参阅构建 iOS 版。
用法
ONNX Runtime API 详情请见此处。
CoreML EP 可通过 C、C++、Objective-C、C# 和 Java API 使用。
创建推理会话时必须显式注册 CoreML EP。例如
Ort::Env env = Ort::Env{ORT_LOGGING_LEVEL_ERROR, "Default"};
Ort::SessionOptions so;
std::unordered_map<std::string, std::string> provider_options;
provider_options["ModelFormat"] = std::to_string("MLProgram");
so.AppendExecutionProvider("CoreML", provider_options);
Ort::Session session(env, model_path, so);
在 ONNX Runtime 1.20.0 中,API OrtSessionOptionsAppendExecutionProvider_CoreML
已弃用。请改用 OrtSessionOptionsAppendExecutionProvider
。
Ort::Env env = Ort::Env{ORT_LOGGING_LEVEL_ERROR, "Default"};
Ort::SessionOptions so;
uint32_t coreml_flags = 0;
Ort::ThrowOnError(OrtSessionOptionsAppendExecutionProvider_CoreML(so, coreml_flags));
Ort::Session session(env, model_path, so);
配置选项(新 API)
CoreML EP 有几个运行时选项可用。
要使用 CoreML EP 运行时选项,请创建一个表示这些选项的无符号整数,并通过使用按位或运算符来设置每个单独的选项。
可通过将字符串传递给 AppendExecutionProvider
方法来设置 ProviderOptions。
Ort::Env env = Ort::Env{ORT_LOGGING_LEVEL_ERROR, "Default"};
Ort::SessionOptions so;
std::string model_path = "/a/b/c/model.onnx";
std::unordered_map<std::string, std::string> provider_options;
provider_options["ModelFormat"] = "MLProgram";
provider_options["MLComputeUnits"] = "ALL";
provider_options["RequireStaticInputShapes"] = "0";
provider_options["EnableOnSubgraphs"] = "0";
so.AppendExecutionProvider("CoreML", provider_options);
Ort::Session session(env, model_path, so);
使用 CoreML EP 运行时选项的 Python 推理示例代码
import onnxruntime as ort
model_path = "model.onnx"
providers = [
('CoreMLExecutionProvider', {
"ModelFormat": "MLProgram", "MLComputeUnits": "ALL",
"RequireStaticInputShapes": "0", "EnableOnSubgraphs": "0"
}),
]
session = ort.InferenceSession(model_path, providers=providers)
outputs = ort_sess.run(None, input_feed)
可用选项(新 API)
ModelFormat
可以是以下值之一:(默认为 NeuralNetwork
)
MLProgram
:创建 MLProgram 格式模型。需要 Core ML 5 或更高版本 (iOS 15+ 或 macOS 12+)。NeuralNetwork
:创建 NeuralNetwork 格式模型。需要 Core ML 3 或更高版本 (iOS 13+ 或 macOS 10.15+)。
MLComputeUnits
可以是以下值之一:(默认为 ALL
)
CPUOnly
:限制 CoreML 仅在 CPU 上运行。CPUAndNeuralEngine
:为配备兼容 Apple 神经网络引擎 (ANE) 的 Apple 设备启用 CoreML EP。CPUAndGPU
:为配备兼容 GPU 的 Apple 设备启用 CoreML EP。ALL
:为所有兼容的 Apple 设备启用 CoreML EP。
RequireStaticInputShapes
可以是以下值之一:(默认为 0
)
仅允许 CoreML EP 接受输入具有静态形状的节点。默认情况下,CoreML EP 也将允许输入具有动态形状,但动态形状的输入可能会对性能产生负面影响。
0
:允许 CoreML EP 接受输入具有动态形状的节点。1
:仅允许 CoreML EP 接受输入具有静态形状的节点。
EnableOnSubgraphs
可以是以下值之一:(默认为 0
)
启用 CoreML EP 在控制流操作符(即 Loop、Scan 或 If 操作符)主体中的子图上运行。
0
:禁用 CoreML EP 在控制流操作符主体中的子图上运行。1
:启用 CoreML EP 在控制流操作符主体中的子图上运行。
SpecializationStrategy
:此功能自 macOS>=10.15 或 iOS>=18.0 开始可用。此过程可能会影响模型加载时间和预测延迟。使用此选项可为您的模型定制专门化策略。导航至 Apple 文档了解更多信息。可以是以下值之一:(默认为 Default
)
默认
:快速预测
:
ProfileComputePlan
:分析 Core ML MLComputePlan。这将记录每个操作符被分派到哪个硬件以及估计的执行时间。旨在供开发人员使用,但如果性能不符合预期,则提供有用的诊断信息。可以是以下值之一:(默认为 0
)
0
:禁用配置文件。1
:启用配置文件。
AllowLowPrecisionAccumulationOnGPU
:请参阅 Apple 文档。可以是以下值之一:(默认为 0
)
0
:使用 float32 数据类型累积数据。1
:使用低精度数据 (float16) 累积数据。
ModelCacheDirectory
:存储 Core ML 模型缓存的目录路径。CoreML EP 会将捕获的子图编译成 CoreML 格式图并保存到磁盘。对于给定模型,如果未启用缓存,CoreML EP 每次都会编译并保存到磁盘,这对于复杂模型可能会花费大量时间(甚至几分钟)。通过提供缓存路径,可以重用 CoreML 格式的模型。(默认禁用缓存)。
""
:禁用缓存。(默认为空字符串)"/path/to/cache"
:启用缓存。(缓存目录路径,如果不存在将创建)
模型的缓存信息存储在缓存目录中模型哈希下。计算哈希的方式有三种,按优先级排序。
- 从模型 metadata_props 读取。这为用户提供了直接控制哈希的方式,也是推荐的用法。缓存键应满足以下条件:(1)值必须只包含字母数字字符。(2)len(value) < 64。EP 将重新哈希缓存键以满足这些条件。
- 创建推理会话时使用的模型 URL 的哈希值。
- 如果推理会话是使用内存中的字节创建的(即没有模型路径),则为图输入和节点输出的哈希值。
至关重要的是,如果模型发生更改,则哈希值必须更改,或者您必须清除之前的缓存信息。例如,如果模型 URL 用于哈希(上述选项 2),则必须从不同的路径加载更新的模型以更改哈希值。
ONNX Runtime 没有跟踪模型更改并删除缓存条目的机制。
以下是如何在模型元数据中填充模型哈希的示例
import onnx
import hashlib
# You can use any other hash algorithms to ensure the model and its hash-value is a one-one mapping.
def hash_file(file_path, algorithm='sha256', chunk_size=8192):
hash_func = hashlib.new(algorithm)
with open(file_path, 'rb') as file:
while chunk := file.read(chunk_size):
hash_func.update(chunk)
return hash_func.hexdigest()
CACHE_KEY_NAME = "CACHE_KEY"
model_path = "/a/b/c/model.onnx"
m = onnx.load(model_path)
cache_key = m.metadata_props.add()
cache_key.key = CACHE_KEY_NAME
cache_key.value = str(hash_file(model_path))
onnx.save_model(m, model_path)
配置选项(旧 API)
uint32_t coreml_flags = 0;
coreml_flags |= COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE;
可用选项(已弃用 API)
COREML_FLAG_USE_CPU_ONLY
限制 CoreML 仅在 CPU 上运行。
这会降低性能,但提供没有精度损失的参考输出值,这对于验证很有用。
仅供开发人员使用。
COREML_FLAG_ENABLE_ON_SUBGRAPH
启用 CoreML EP 在控制流操作符(即 Loop、Scan 或 If 操作符)主体中的子图上运行。
COREML_FLAG_ONLY_ENABLE_DEVICE_WITH_ANE
默认情况下,CoreML EP 将对所有兼容的 Apple 设备启用。
设置此选项将仅对配备兼容 Apple 神经网络引擎 (ANE) 的 Apple 设备启用 CoreML EP。请注意,启用此选项并不能保证整个模型仅使用 ANE 执行。
有关更多信息,请参阅哪些设备有 ANE?
COREML_FLAG_ONLY_ALLOW_STATIC_INPUT_SHAPES
仅允许 CoreML EP 接受输入具有静态形状的节点。默认情况下,CoreML EP 也将允许输入具有动态形状,但动态形状的输入可能会对性能产生负面影响。
COREML_FLAG_CREATE_MLPROGRAM
创建 MLProgram 格式模型。需要 Core ML 5 或更高版本 (iOS 15+ 或 macOS 12+)。默认情况下会创建 NeuralNetwork 模型,因为该模型需要 Core ML 3 或更高版本 (iOS 13+ 或 macOS 10.15+)。
支持的操作符
NeuralNetwork
创建 NeuralNetwork 模型(默认)时 CoreML 执行提供程序支持的操作符
操作符 | 注意 |
---|---|
ai.onnx:Add | |
ai.onnx:ArgMax | |
ai.onnx:AveragePool | 仅支持 2D 池化。 |
ai.onnx:BatchNormalization | |
ai.onnx:Cast | |
ai.onnx:Clip | |
ai.onnx:Concat | |
ai.onnx:Conv | 仅支持 1D/2D 卷积。 权重和偏差应为常数。 |
ai.onnx:DepthToSpace | 仅支持 DCR 模式的 DepthToSpace。 |
ai.onnx:Div | |
ai.onnx:Flatten | |
ai.onnx:Gather | 不支持标量值的输入 indices 。 |
ai.onnx:Gemm | 输入 B 应为常数。 |
ai.onnx:GlobalAveragePool | 仅支持 2D 池化。 |
ai.onnx:GlobalMaxPool | 仅支持 2D 池化。 |
ai.onnx:LeakyRelu | |
ai.onnx:LRN | |
ai.onnx:MatMul | 输入 B 应为常数。 |
ai.onnx:MaxPool | 仅支持 2D 池化。 |
ai.onnx:Mul | |
ai.onnx:Pad | 仅支持常量模式和最后两个维度的填充。 输入 pads 和 constant_value 应为常数。 如果提供,axes 应为常数。 |
ai.onnx:Pow | 仅支持两个输入均为 fp32 的情况。 |
ai.onnx:PRelu | 输入斜率应为常数。 输入斜率的形状应为 [C, 1, 1] 或只有一个元素。 |
ai.onnx:Reciprocal | |
ai.onnx.ReduceSum | |
ai.onnx:Relu | |
ai.onnx:Reshape | |
ai.onnx:Resize | 4D 输入。coordinate_transformation_mode == asymmetric 。mode == linear 或 nearest 。nearest_mode == floor 。exclude_outside == falsescales 或 sizes 必须是常数。 |
ai.onnx:Shape | 不支持带有非默认值的属性 start 。不支持属性 end 。 |
ai.onnx:Sigmoid | |
ai.onnx:Slice | 输入 starts 、ends 、axes 和 steps 应为常数。不支持空切片。 |
ai.onnx:Softmax | |
ai.onnx:Split | 如果提供,splits 必须是常数。 |
ai.onnx:Squeeze | |
ai.onnx:Sqrt | |
ai.onnx:Sub | |
ai.onnx:Tanh | |
ai.onnx:Transpose |
MLProgram
当创建 MLProgram 模型(设置 COREML_FLAG_CREATE_MLPROGRAM 标志时)CoreML 执行提供程序支持的操作符
操作符 | 注意 |
---|---|
ai.onnx:Add | |
ai.onnx:Argmax | |
ai.onnx:AveragePool | 目前仅支持 2D 池化。如果需要,可以添加 3D 和 5D 支持。 |
ai.onnx:Cast | |
ai.onnx:Clip | |
ai.onnx:Concat | |
ai.onnx:Conv | 仅支持 1D/2D 卷积。 如果提供,偏差必须是常数。 |
ai.onnx:ConvTranspose | 权重和偏差必须是常数。 不支持 SAME_UPPER/SAME_LOWER 的 padding_type。 kernel_shape 必须有默认值。 不支持 output_shape。 output_padding 必须有默认值。 |
ai.onnx:DepthToSpace | 如果“mode”为“CRD”,则输入必须具有固定形状。 |
ai.onnx:Div | |
ai.onnx:Erf | |
ai.onnx:Gemm | 输入 B 必须是常数。 |
ai.onnx:Gelu | |
ai.onnx:GlobalAveragePool | 目前仅支持 2D 池化。如果需要,可以添加 3D 和 5D 支持。 |
ai.onnx:GlobalMaxPool | 目前仅支持 2D 池化。如果需要,可以添加 3D 和 5D 支持。 |
ai.onnx:GridSample | 4D 输入。 “mode”为“linear”或“zeros”。 不支持 (mode==linear && padding_mode==reflection && align_corners==0)。 |
ai.onnx:GroupNormalization | |
ai.onnx:InstanceNormalization | |
ai.onnx:LayerNormalization | |
ai.onnx:LeakyRelu | |
ai.onnx:MatMul | 目前仅支持 transA == 0、alpha == 1.0 和 beta == 1.0 的情况。 |
ai.onnx:MaxPool | 目前仅支持 2D 池化。如果需要,可以添加 3D 和 5D 支持。 |
ai.onnx:Max | |
ai.onnx:Mul | |
ai.onnx:Pow | 仅支持两个输入均为 fp32 的情况。 |
ai.onnx:PRelu | |
ai.onnx:Reciprocal | 这需要一个 epislon (默认 1e-4),而 onnx 没有提供 |
ai.onnx:ReduceSum | |
ai.onnx:ReduceMean | |
ai.onnx:ReduceMax | |
ai.onnx:Relu | |
ai.onnx:Reshape | |
ai.onnx:Resize | 请参阅 resize_op_builder.cc 实现。组合情况太多,无法一一描述所有有效组合。 |
ai.onnx:Round | |
ai.onnx:Shape | |
ai.onnx:Slice | starts/ends/axes/steps 必须是常量初始化器。 |
ai.onnx:Split | 如果提供,splits 必须是常数。 |
ai.onnx:Sub | |
ai.onnx:Sigmoid | |
ai.onnx:Softmax | |
ai.onnx:Sqrt | |
ai.onnx:Squeeze | |
ai.onnx:Tanh | |
ai.onnx:Transpose | |
ai.onnx:Unsqueeze |