ONNX 实时graph优化方法
ONNX实时提供了各种图形优化来提高模型性能。图优化本质上是图级别的转换,从小型图简化和节点消除,到更复杂的节点融合和布局优化。
图形优化根据其复杂性和功能分为几个类别(或级别)。可以在线或离线执行。在联机模式下,优化在执行推断之前完成,而在脱机模式下,实时将优化的图形保存到磁盘。ONNX实时提供Python、C++、C++和C API,启用不同的优化级别,并在脱机与在线模式之间进行选择。
下面将详细介绍优化级别、在线/离线模式以及控制它们的各种API。
图优化级别Graph Optimization Levels
图形优化分为三个级别:
•基本
•扩展
•布局优化
属于一个级别的优化,在应用前一级别的优化之后执行(例如,在应用基本优化之后,应用扩展优化)。
默认情况下启用所有优化。
Basic图优化 Basic Graph Optimizations
- 这些都是保留语义的图重写,去除了冗余节点和冗余计算。在图形分区之前运行,适用于所有执行提供程序。可用的基本图形优化如下:
•常量折叠:静态计算仅依赖常量初始值设定项的图形部分。这样就不需要在实时计算它们。
•冗余节点消除:在不改变图形结构的情况下删除所有冗余节点。目前支持以下此类优化:
• Identity Elimination
• Slice Elimination
• Unsqueeze Elimination
• Dropout Elimination
• Semantics-preserving node fusions
•语义保留节点融合:将多个节点融合/折叠为单个节点。例如,Conv Add fusion将Add操作符,折叠为Conv操作符的偏移。目前支持以下此类优化::
- Conv Add Fusion
- Conv Mul Fusion
- Conv BatchNorm Fusion
- Relu Clip Fusion
- Reshape Fusion
Extended图优化 Extended Graph Optimizations
这些优化包括复杂的节点融合。它们在图形分区之后运行,并且仅应用于分配给CPU或CUDA执行提供程序的节点。可用的扩展图优化如下所示:
Optimization |
Execution Provider |
Comment |
GEMM Activation Fusion |
cpu |
|
Matmul Add Fusion |
cpu |
|
Conv Activation Fusion |
cpu |
|
GELU Fusion |
cpu or cuda |
|
Layer Normalization Fusion |
cpu or cuda |
|
BERT Embedding Layer Fusion |
cpu or cuda |
Fuse BERT embedding layer, layer normalization and attention mask length |
Attention Fusion |
cpu or cuda |
Attention mask has approximation in cuda execution provider |
Skip Layer Normalization Fusion |
cpu or cuda |
Fuse bias of fully connected layer, skip connection and layer normalization |
Bias GELU Fusion |
cpu or cuda |
Fuse bias of fully connected layer and GELU activation |
GELU Approximation |
cuda |
Erf is approximated by a formula using tanh function |
为了优化BERT模型的推理性能,GELU逼近和cuda执行支持provider,注意融合中使用了近似。结果可能略有不同。根据评估,对准确度的影响可以忽略不计:F1 score for a BERT model on SQuAD v1.1 is almost same (87.05 vs 87.03)。
Layout优化 Layout Optimizations
这些优化更改了适用节点的数据布局,以实现更高的性能改进。在图形分区之后运行,并且仅应用于分配给CPU执行提供程序的节点。可用的布局优化如下:
- NCHWc Optimizer: Optimizes the graph by using NCHWc layout instead of NCHW layout.
在线/离线模式选择 Online/Offline Mode
所有优化都可以在线或离线执行。在联机模式下,在初始化推理会话时,还将在执行模型推理之前,应用所有启用的图优化。每次启动会话时,应用所有优化,都会增加模型启动时间的开销(特别是对于复杂模型),这在输出场景中非常关键。这就是离线模式可以带来很多好处的地方。在脱机模式下,在执行图形优化之后,ONNX实时将生成的模型序列化到磁盘。随后,当为该模型创建新的推理会话时,可以使用已经优化的模型,来减少启动时间。
注意:
•在脱机模式下运行时,确保使用与模型推理,将在其上运行的目标计算机,完全相同的选项(例如,执行提供程序、优化级别)和硬件(例如,不能在仅配备CPU的计算机上,运行为GPU执行提供程序预优化的模型)。
•启用布局优化时,脱机模式只能在保存脱机模型时在与环境兼容的硬件上使用。例如,如果模型为AVX2优化了布局,那么离线模型将需要支持AVX2的cpu。
使用说明 Usage
通用方法说明 General Note
Levels:
ONNX运行时定义GraphOptimizationLevel枚举,以确定将启用上述哪些优化级别。选择一个级别可以实现该级别的优化,也可以实现前面所有级别的优化。例如,启用扩展优化,也会启用基本优化。这些级别到枚举的映射如下:
- GraphOptimizationLevel::ORT_DISABLE_ALL -> Disables all optimizations
- GraphOptimizationLevel::ORT_ENABLE_BASIC -> Enables basic optimizations
- GraphOptimizationLevel::ORT_ENABLE_EXTENDED -> Enables basic and extended optimizations
- GraphOptimizationLevel::ORT_ENABLE_ALL -> Enables all available optimizations including layout optimizations
Online/Offline Mode:
要将优化模型序列化到磁盘,请将SessionOptions选项optimized_model_path
,
设置为存储优化模型的所需路径。
Python API Usage
importonnxruntime
asrt
sess_options
=rt
.SessionOptions
()
# Set graph optimization level
sess_options
.graph_optimization_level
=rt
.GraphOptimizationLevel
.ORT_ENABLE_EXTENDED
# To enable model serialization after graph optimization set this
sess_options
.optimized_model_filepath
="<model_output_pathoptimized_model.onnx>"
session
=rt
.InferenceSession
("<model_path>",sess_options
)
C API Example:
const
OrtApi
*Ort
::g_api
=OrtGetApi(
ORT_API_VERSION
);
OrtEnv
*env
;
g_ort
->CreateEnv(ORT_LOGGING_LEVEL_WARNING
,"test",
&
env
);
OrtSessionOptions
*session_options
;
g_ort
->CreateSessionOptions(&session_options
)
// Set graph optimization level
g_ort
->SetSessionGraphOptimizationLevel(session_options
,ORT_ENABLE_EXTENDED
);
// To enable model serialization after graph optimization set this
const
wchar_t
*optimized_model_path
=L
"optimized_model_path";
g_ort
->SetOptimizedModelFilePath(session_options
,optimized_model_path
);
OrtSession
*session
;
const
wchar_t
*model_path
=L
"model_path";
g_ort
->CreateSession(env
,model_path
,session_option
,&
session
);
C# API Example:
SessionOptions so = new SessionOptions();
// Set graph optimization level
so.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_EXTENDED;
// To enable model serialization after graph optimization set this
so.OptimizedModelFilePath = "model_output_pathoptimized_model.onnx"
var session = new InferenceSession(modelPath, so);
C++ API Example:
Ort::SessionOptions session_options;
// Set graph optimization level
session_options.SetGraphOptimizationLevel(GraphOptimizationLevel::ORT_ENABLE_EXTENDED);
// To enable model serialization after graph optimization set this
session_options.SetOptimizedModelFilePath("optimized_file_path");
auto session_ = Ort::Session(env, "model_file_path", session_options);