DirectML 执行提供程序
DirectML 执行提供程序是 ONNX Runtime 的一个组件,它使用 DirectML 来加速 ONNX 模型的推理。DirectML 执行提供程序能够极大地改善使用商用 GPU 硬件的模型评估时间,同时不牺牲广泛的硬件支持或要求安装供应商特定的扩展。
DirectML 是一个高性能、硬件加速的 DirectX 12 库,用于在 Windows 上进行机器学习。DirectML 为广泛支持的硬件和驱动程序上的常见机器学习任务提供 GPU 加速。
独立使用时,DirectML API 是一个低级 DirectX 12 库,适用于高性能、低延迟的应用程序,例如框架、游戏和其他实时应用程序。DirectML 与 Direct3D 12 的无缝互操作性以及其低开销和跨硬件的一致性,使得 DirectML 成为在需要高性能以及跨硬件的结果可靠性和可预测性至关重要时加速机器学习的理想选择。
DirectML 执行提供程序当前使用 DirectML 版本 1.15.2,支持高达 ONNX opset 20(ONNX v1.15),但 Gridsample 20: 5d 和 DeformConv 除外,这些尚不支持。评估需要更高 opset 版本的模型不受支持,并且会导致性能不佳。注意:DirectML 的 ONNX opset 支持可能与 ONNX Runtime 的不同,ONNX Runtime 的支持可以在此处找到。
目录
安装
带有 DirectML EP 的 ORT 预构建软件包已发布在 Nuget.org 上。请参阅:安装 ONNX Runtime。
要求
DirectML 执行提供程序需要一个支持 DirectX 12 的设备。过去几年发布的几乎所有商用显卡都支持 DirectX 12。以下是一些兼容硬件的示例:
- NVIDIA Kepler(GTX 600 系列)及更高版本
- AMD GCN 第一代(Radeon HD 7000 系列)及更高版本
- Intel Haswell(第四代酷睿)HD 集成显卡及更高版本
- Qualcomm Adreno 600 及更高版本
DirectML 在 Windows 10 版本 1903 及相应的 Windows SDK 版本中引入。
构建
构建 DirectML 执行提供程序的要求:
- Visual Studio 2017 工具链
- 适用于 Windows 10 版本 1903 的 Windows 10 SDK (10.0.18362.0)(或更高版本)
要构建包含 DML EP 的 onnxruntime,请向 build.bat
提供 --use_dml
标志。例如:
build.bat --config RelWithDebInfo --build_shared_lib --parallel --use_dml
DirectML 执行提供程序支持为 x64(默认)和 x86 架构构建。
请注意,您可以使用 DirectML 构建 ONNX Runtime。这将允许在构建过程中自动下载 DirectML 可再发行软件包。更多许可证信息请参阅 NuGet 文档。
用法
在使用支持 DML 的 onnxruntime 构建版本时,通过 include/onnxruntime/core/providers/dml/dml_provider_factory.h
中包含的两个工厂函数之一,可以启用 DirectML 执行提供程序。
OrtSessionOptionsAppendExecutionProvider_DML
函数
创建一个 DirectML 执行提供程序,该提供程序在具有给定 device_id
(也称为适配器索引)的硬件适配器上执行。设备 ID 对应于 IDXGIFactory::EnumAdapters 给定的硬件适配器的枚举顺序。 device_id
为 0 始终对应于默认适配器,这通常是系统上安装的主显示 GPU。请注意,在具有多个 GPU 的系统中,主显示器(GPU 0)通常不是性能最优的,尤其是在具有双适配器且电池寿命优先于性能的笔记本电脑上。因此,您可以在任务管理器的性能选项卡中仔细检查哪个 GPU 是哪个。负数 device_id
无效。
C API 示例
OrtStatus* OrtSessionOptionsAppendExecutionProvider_DML(
_In_ OrtSessionOptions* options,
int device_id
);
C# API 示例
安装 Nuget 包 Microsoft.ML.OnnxRuntime.DirectML 并使用以下代码启用 DirectML EP:
SessionOptions sessionOptions = newSessionOptions();
sessionOptions.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_ALL;
sessionOptions.AppendExecutionProvider_DML(0);
SessionOptionsAppendExecutionProvider_DML1
函数
使用给定的 DirectML 设备创建 DirectML 执行提供程序,该提供程序在提供的 D3D12 命令队列上执行工作。DirectML 设备和 D3D12 命令队列必须具有相同的父级 ID3D12Device,否则将返回错误。D3D12 命令队列的类型必须是 DIRECT
或 COMPUTE
(参见 D3D12_COMMAND_LIST_TYPE)。如果此函数成功,创建的推理会话将对 dml_device
和 command_queue
对象保持强引用。
OrtStatus* SessionOptionsAppendExecutionProvider_DML1(
_In_ OrtSessionOptions* options,
_In_ IDMLDevice* dml_device,
_In_ ID3D12CommandQueue* cmd_queue
);
配置选项
DirectML 执行提供程序不支持使用 onnxruntime 中的内存模式优化或并行执行。在创建 InferenceSession 时提供会话选项时,必须禁用这些选项,否则将返回错误。
如果使用 onnxruntime C API,您必须调用 DisableMemPattern
和 SetSessionExecutionMode
函数来设置 DirectML 执行提供程序所需的选项。
请参阅 onnxruntime\include\onnxruntime\core\session\onnxruntime_c_api.h。
OrtStatus*(ORT_API_CALL* DisableMemPattern)(_Inout_ OrtSessionOptions* options)NO_EXCEPTION;
OrtStatus*(ORT_API_CALL* SetSessionExecutionMode)(_Inout_ OrtSessionOptions* options, ExecutionMode execution_mode)NO_EXCEPTION;
如果直接创建 onnxruntime InferenceSession 对象,您必须在 onnxruntime::SessionOptions
结构上设置相应的字段。具体来说,execution_mode
必须设置为 ExecutionMode::ORT_SEQUENTIAL
,并且 enable_mem_pattern
必须为 false
。
此外,由于 DirectML 执行提供程序不支持并行执行,它不支持对同一推理会话进行多线程调用 Run
。也就是说,如果使用 DirectML 执行提供程序的推理会话,一次只能有一个线程调用 Run
。如果多个线程操作不同的推理会话对象,则允许同时调用 Run
。
性能调优
DirectML 执行提供程序在会话创建时已知张量形状时工作效率最高。以下是一些性能优势:
- 常数折叠(Constant folding)可以更频繁地发生,减少评估期间的 CPU / GPU 拷贝和停顿。
- 更多初始化工作在会话创建时发生,而不是在首次评估期间发生。
- 权重可以在 DirectML 内部预处理,从而启用更高效的算法。
- 图优化在 DirectML 内部发生。例如,Concat 算子可能被移除,并为算子的输入和输出使用更优化的张量布局。
通常,当模型输入的形状在会话创建期间已知时,onnxruntime 会在该会话创建时推断模型其余部分的形状。
但是,如果模型输入包含自由维度(例如批量大小),则必须采取额外步骤以保留上述性能优势。这些步骤包括:
- 编辑模型,用固定大小(通过 ONNX 使用“dim_value”指定)替换输入的自由维度(通过 ONNX 使用“dim_param”指定)。
- 在创建会话时,使用 OnnxRuntime AddFreeDimensionOverrideByName ABI 指定模型输入中命名维度的值。
- 编辑模型,确保输入的自由维度具有标注(例如“DATA_BATCH”或自定义标注)。然后,在创建会话时,为每个标注指定维度大小。这可以使用 OnnxRuntime AddFreeDimensionOverride ABI 完成。
示例
使用 DirectML 执行提供程序的 onnxruntime 的完整示例可在 samples/c_cxx/fns_candy_style_transfer 下找到