Graph-Optimierungen in ONNX Runtime
ONNX Runtime bietet verschiedene Graph-Optimierungen zur Leistungssteigerung. Graph-Optimierungen sind im Wesentlichen Transformationen auf Graphen-Ebene, die von einfachen Graph-Vereinfachungen und Knoteneliminationen bis hin zu komplexeren Knotenfusionen und Layout-Optimierungen reichen.
Graph-Optimierungen sind nach Komplexität und Funktionalität in mehrere Kategorien (oder Levels) unterteilt. Sie können entweder online oder offline durchgeführt werden. Im Online-Modus werden die Optimierungen vor der Inferenz durchgeführt, während im Offline-Modus die Laufzeitumgebung den optimierten Graphen auf die Festplatte speichert. ONNX Runtime bietet Python-, C#-, C++- und C-APIs, um verschiedene Optimierungsstufen zu ermöglichen und zwischen Offline- und Online-Modus zu wählen.
Im Folgenden finden Sie Details zu den Optimierungsstufen, dem Online/Offline-Modus und den verschiedenen APIs zur Steuerung.
Inhalt
Graph-Optimierungsstufen
Graph-Optimierungen sind in drei Stufen unterteilt:
- Basic
- Extended
- Layout-Optimierungen
Die Optimierungen einer Stufe werden nach Anwendung der Optimierungen der vorherigen Stufe durchgeführt (z. B. werden Extended-Optimierungen nach Anwendung der Basic-Optimierungen angewendet).
Alle Optimierungen sind standardmäßig aktiviert.
Basis-Graph-Optimierungen
Dies sind semantik-erhaltende Graph-Neuschreibungen, die redundante Knoten und redundante Berechnungen entfernen. Sie werden vor der Graph-Partitionierung ausgeführt und gelten daher für alle Ausführungsanbieter. Verfügbare Basis-Graph-Optimierungen sind:
-
Constant Folding: Berechnet statisch Teile des Graphen, die nur von konstanten Initialisierern abhängen. Dies eliminiert die Notwendigkeit, diese zur Laufzeit zu berechnen.
- Entfernung redundanter Knoten: Entfernt alle redundanten Knoten, ohne die Graph-Struktur zu verändern. Folgende solche Optimierungen werden derzeit unterstützt:
- Identitätseliminierung
- Slice-Eliminierung
- Unsqueeze-Eliminierung
- Dropout-Eliminierung
- Semantik-erhaltende Knoten-Fusionen: Fusioniert/Faltet mehrere Knoten zu einem einzigen Knoten. Beispielsweise fusioniert Conv Add Fusion den Add-Operator als Bias des Conv-Operators. Folgende solche Optimierungen werden derzeit unterstützt:
- Conv Add Fusion
- Conv Mul Fusion
- Conv BatchNorm Fusion
- Relu Clip Fusion
- Reshape Fusion
Erweiterte Graph-Optimierungen
Diese Optimierungen umfassen komplexe Knoten-Fusionen. Sie werden nach der Graph-Partitionierung ausgeführt und gelten nur für Knoten, die dem CPU-, CUDA- oder ROCm-Ausführungsanbieter zugewiesen sind. Verfügbare erweiterte Graph-Optimierungen sind:
| Optimierung | Ausführungsanbieter | Kommentar |
|---|---|---|
| GEMM Activation Fusion | CPU | |
| Matmul Add Fusion | CPU | |
| Conv Activation Fusion | CPU | |
| GELU Fusion | CPU, CUDA, ROCm | |
| Layer Normalization Fusion | CPU, CUDA, ROCm | |
| BERT Embedding Layer Fusion | CPU, CUDA, ROCm | BERT-Embedding-Layer, Layer-Normalisierung und Aufmerksamkeitsmaskenlänge fusionieren |
| Attention Fusion* | CPU, CUDA, ROCm | |
| Skip Layer Normalization Fusion | CPU, CUDA, ROCm | Bias einer vollständig verbundenen Schicht, Skip-Verbindung und Layer-Normalisierung fusionieren |
| Bias GELU Fusion | CPU, CUDA, ROCm | Bias einer vollständig verbundenen Schicht und GELU-Aktivierung fusionieren |
| GELU Approximation* | CUDA, ROCm | Standardmäßig deaktiviert. Aktivieren mit kOrtSessionOptionsEnableGeluApproximation |
Approximations (click to expand)
Approximations (click to expand)
Zur Optimierung der Leistung von BERT wird bei GELU Approximation und Attention Fusion für CUDA- und ROCm-Ausführungsanbieter eine Approximation verwendet. Die Auswirkung auf die Genauigkeit ist nach unserer Einschätzung vernachlässigbar: Der F1-Score für ein BERT-Modell auf SQuAD v1.1 ist nahezu gleich (87,05 vs. 87,03).
Layout-Optimierungen
Diese Optimierungen ändern das Datenlayout für anwendbare Knoten, um höhere Leistungssteigerungen zu erzielen. Sie werden nach der Graph-Partitionierung ausgeführt und gelten nur für Knoten, die dem CPU-Ausführungsanbieter zugewiesen sind. Verfügbare Layout-Optimierungen sind:
- NCHWc Optimizer: Optimiert den Graphen durch Verwendung des NCHWc-Layouts anstelle des NCHW-Layouts.
Online/Offline-Modus
Alle Optimierungen können entweder online oder offline durchgeführt werden. Im Online-Modus wenden wir beim Initialisieren einer Inferenzsitzung auch alle aktivierten Graph-Optimierungen an, bevor wir die Modellinferenz durchführen. Das Anwenden aller Optimierungen jedes Mal, wenn wir eine Sitzung starten, kann den Zeitaufwand für den Modellstart erhöhen (insbesondere bei komplexen Modellen), was in Produktionsszenarien entscheidend sein kann. Hier kann der Offline-Modus einen großen Vorteil bringen. Im Offline-Modus serialisiert ONNX Runtime nach Durchführung der Graph-Optimierungen das resultierende Modell auf die Festplatte. Anschließend können wir die Startzeit reduzieren, indem wir das bereits optimierte Modell verwenden und alle Optimierungen deaktivieren.
Hinweise:
- Stellen Sie bei der Ausführung im Offline-Modus sicher, dass Sie genau dieselben Optionen (z. B. Ausführungsanbieter, Optimierungsstufe) und dieselbe Hardware wie auf der Zielmaschine verwenden, auf der die Modellinferenz ausgeführt werden soll (z. B. können Sie kein Modell ausführen, das für einen GPU-Ausführungsanbieter voroptimiert wurde, auf einer Maschine, die nur mit einer CPU ausgestattet ist).
- Wenn Layout-Optimierungen aktiviert sind, kann der Offline-Modus nur auf kompatibler Hardware zu der Umgebung verwendet werden, in der das Offline-Modell gespeichert wird. Wenn ein Modell beispielsweise für AVX2 mit Layout-Optimierung versehen wurde, benötigt das Offline-Modell CPUs, die AVX2 unterstützen.
Verwendung
Stufen
ONNX Runtime definiert die Enum GraphOptimizationLevel, um zu bestimmen, welche der oben genannten Optimierungsstufen aktiviert werden. Die Wahl einer Stufe aktiviert die Optimierungen dieser Stufe sowie die Optimierungen aller vorherigen Stufen. Beispielsweise aktiviert die Aktivierung von Extended-Optimierungen auch Basic-Optimierungen. Die Zuordnung dieser Stufen zur Enum ist wie folgt:
- GraphOptimizationLevel::ORT_DISABLE_ALL -> Deaktiviert alle Optimierungen
- GraphOptimizationLevel::ORT_ENABLE_BASIC -> Aktiviert Basis-Optimierungen
- GraphOptimizationLevel::ORT_ENABLE_EXTENDED -> Aktiviert Basis- und erweiterte Optimierungen
- GraphOptimizationLevel::ORT_ENABLE_ALL -> Aktiviert alle verfügbaren Optimierungen einschließlich Layout-Optimierungen
Offline-Modus
Um die Serialisierung des optimierten Modells auf die Festplatte zu aktivieren, setzen Sie die SessionOptions-Option optimized_model_filepath.
Python API-Beispiel
import onnxruntime as rt
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_path\optimized_model.onnx>"
session = rt.InferenceSession("<model_path>", sess_options)
C API-Beispiel
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 ORTCHAR_T* optimized_model_path = ORT_TSTR("optimized_model_path");
g_ort->SetOptimizedModelFilePath(session_options, optimized_model_path);
OrtSession* session;
const ORTCHAR_T* model_path = ORT_TSTR("model_path");
g_ort->CreateSession(env, model_path, session_options, &session);
C#-API-Beispiel
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_path\optimized_model.onnx"
var session = new InferenceSession(modelPath, so);
C++ API-Beispiel
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);