Fehlerbehebung bei Leistungsproblemen

Inhalt

Hier ist eine Liste von Dingen, die Sie bei der Beurteilung von Leistungsproblemen überprüfen sollten

  • Haben Sie alle Graph-Optimierungen aktiviert? Die offiziell veröffentlichten Pakete aktivieren standardmäßig alle, aber beim Kompilieren aus dem Quellcode überprüfen Sie, ob diese bei Ihrer Erstellung aktiviert sind.
  • Haben Sie die bereits eingereichten GitHub-Probleme durchsucht, um zu sehen, ob Ihr Problem bereits diskutiert wurde? Bitte tun Sie dies, bevor Sie neue Probleme melden.
  • Wenn Sie CUDA oder TensorRT verwenden, haben Sie die richtigen Versionen der abhängigen Bibliotheken installiert? CUDA EP / TensorRT EP

Warum wird der Modellgraph auch bei gesetztem graph_optimization_level auf ORT_ENABLE_ALL nicht optimiert?

Das ONNX-Modell ab IR_VERSION 4 behandelt Initialisierer, die in den Graph-Inputs erscheinen, nur als nicht-konstant. Dies kann einige Graph-Optimierungen wie Constant Folding, Operator Fusion usw. verhindern. Verschieben Sie Initialisierer aus den Graph-Inputs, wenn keine Notwendigkeit besteht, sie zu überschreiben, indem Sie entweder das Modell mit dem neuesten Exporter/Konverter oder mit dem Tool remove_initializer_from_input.py neu generieren.

Warum läuft mein Modell auf der GPU langsamer als auf der CPU?

Abhängig von dem von Ihnen verwendeten Ausführungsanbieter hat dieser möglicherweise keine vollständige Unterstützung für alle Operatoren in Ihrem Modell. Ein Zurückfallen auf CPU-Operationen kann zu Leistungseinbußen führen. Selbst wenn eine Operation vom CUDA-Ausführungsanbieter implementiert wird, wird sie aus Leistungsgründen möglicherweise nicht unbedingt dem CUDA-EP zugewiesen/platziert. Um die von ORT getroffene Platzierungsentscheidung zu sehen, aktivieren Sie die ausführliche Protokollierung und schauen Sie sich die Konsolenausgabe an.

Mein konvertiertes TensorFlow-Modell ist langsam - warum?

NCHW und NHWC sind zwei verschiedene Speicherlayouts für 4D-Tensoren.

Die meisten TensorFlow-Operationen, die von einer CNN verwendet werden, unterstützen sowohl das NHWC- als auch das NCHW-Datenformat. Das TensorFlow-Team schlägt vor, dass NCHW auf GPUs schneller ist, aber auf CPUs ist NHWC in TensorFlow manchmal schneller. ONNX unterstützt jedoch nur NCHW. Infolgedessen werden, wenn das ursprüngliche Modell im NHWC-Format vorliegt, zusätzliche Transponierungen hinzugefügt, wenn das Modell konvertiert wird. Der tensorflow-onnx-Konverter entfernt viele dieser Transponierungen, aber wenn dies nicht ausreichend hilft, erwägen Sie das erneute Trainieren des Modells im NCHW-Format.

Ich beobachte eine hohe Latenzvarianz.

Auf einigen Plattformen kann ONNX Runtime während der Inferenz eine hohe Latenzvarianz aufweisen. Dies wird durch das konstante Kostenmodell verursacht, das ONNX Runtime zur Parallelisierung von Aufgaben im Thread-Pool verwendet. Für jede Aufgabe berechnet das konstante Kostenmodell eine Granularität für die Parallelisierung unter den Threads, die bis zum Ende der Aufgabenausführung konstant bleibt. Dieser Ansatz kann manchmal zu einer unausgewogenen Last führen, was eine hohe Latenzvarianz verursacht. Um dies zu mildern, bietet ONNX Runtime ein dynamisches Kostenmodell, das als Sitzungsoption aktiviert werden kann.

sess_options.add_session_config_entry('session.dynamic_block_base', '4')

Wenn der ONNX Runtime-Thread-Pool mit einem positiven Wert gesetzt ist, parallelisiert er interne Aufgaben mit abnehmender Granularität. Speziell unter der Annahme, dass es eine Funktion gibt, die vom Thread-Pool N Mal ausgeführt werden soll, beansprucht bei aktiviertem dynamischem Kostenmodell jeder Thread im Pool

residual_of_N / (dynamic_block_base * num_of_threads)

jederzeit, wenn er bereit ist, zu laufen. Über einen Zeitraum hinweg sind die Threads im Pool wahrscheinlich besser ausgelastet und senken dadurch die Latenzvarianz.

Aus demselben Grund kann das dynamische Kostenmodell auch die Leistung für Fälle verbessern, in denen Threads eher präemptiert werden. Nach unseren Tests ist die mit Abstand beste Konfiguration für dynamic_block_base 4, die die Varianz reduziert und gleichzeitig eine gute Leistung beibehält.

Ich beobachte eine hohe CPU-Auslastung unter Windows

Es wurde beobachtet, dass bei Maschinen mit mehr als 64 logischen Kernen die CPU-Auslastung spürbar gesenkt werden kann, indem der Thread-Pool eine lock-freie Task-Warteschlange verwendet, die Spinlocks anstelle von Mutexes zur Synchronisation nutzt. Die lock-freie Task-Warteschlange kann durch das Kompilieren von ONNX Runtime aus dem Quellcode mit dem folgenden Flag aktiviert werden

--use_lock_free_queue