Mehr Spielspaß mit Burst 1.7

Die neueste Version des Burst-Pakets enthält einige großartige Verbesserungen sowohl bei der Iterationszeit als auch beim Burst Inspector. In diesem Beitrag werden wir uns ansehen, was sich geändert hat und wie unsere High Performance C# (HPC#) Compiler-Technologie Ihnen jetzt helfen kann, die Leistung auf allen Plattformen noch einfacher zu verbessern.
Während unser DOTS-Technologie-Stack Burst nutzt, um hochoptimierten Code zu liefern, ist Burst ein eigenständiges Paket, das im Package Manager für Unity 2019.4 oder neuer verfügbar ist. Tausende Ihrer Projekte auf allen wichtigen Desktop-, Konsolen- und mobilen Plattformen nutzen bereits die Vorteile von Burst.
In früheren Burst-Versionen haben wir erhebliche Fortschritte bei der Verbesserung der täglichen Arbeit mit Burst gemacht. In Burst 1.7 haben wir diesen Trend fortgesetzt und uns auf die Verbesserung der Iterationszeit konzentriert. Was verstehen wir unter Iterationszeit? Wir meinen die "innere Schleife" der Entwicklung - Sie nehmen eine Änderung an einem C#-Skript vor, wechseln zurück zum Editor, warten auf die Beendigung der Skriptkompilierung, warten auf die Beendigung der Burst-Kompilierung und gehen dann in den Play-Modus, um Ihre Änderung zu testen.
In Burst 1.7 haben wir die Zeit, die Sie auf Burst warten müssen, drastisch verkürzt, wenn Sie ein paar Änderungen an Ihrem Spielcode vornehmen und diesen im Spielmodus testen. Die Burst-Kompilierung findet jetzt früher in der Pipeline statt (unmittelbar nachdem die Skriptkompilierungs-Pipeline die Kompilierung von .NET-Assemblies abgeschlossen hat), so dass sie in vielen Fällen zu dem Zeitpunkt abgeschlossen ist, an dem der resultierende Code ausgeführt werden muss. Anstatt jeden Burst-Einstiegspunkt separat zu kompilieren, wie es in früheren Versionen von Burst der Fall war, werden Burst-Einstiegspunkte (z.B. ein Job oder ein Funktionszeiger) nun zusammengefasst, um den Compiler-Durchsatz zu verbessern und die Anzahl der Bibliotheken zu reduzieren, die der Editor laden muss.
Burst 1.7 enthält auch eine wesentliche Verbesserung der Leistung von Direktanrufen. Direct Call ist eine Funktion, die wir in Burst 1.5 hinzugefügt haben und die es verwaltetem C#-Code erlaubt, eine von Burst kompilierte Methode direkt aufzurufen, ohne den Weg über BurstCompiler.CompileFunctionPointer zu nehmen. Während des Neuladens einer Domäne müssen einige Initialisierungsarbeiten durchgeführt werden, um Methoden für Direktaufrufe zu verdrahten, und in Burst 1.7 haben wir diese Initialisierung bis zu 33 Mal schneller gemacht.
Als letzte Anmerkung zum Thema Iterationszeit haben wir uns die Kosten für die Initialisierung von SharedStatic angesehen. SharedStatic ist ein Mechanismus, der die gemeinsame Nutzung von Daten zwischen verwaltetem C# und HPC# ermöglicht. In Burst 1.7 haben wir die Initialisierung von SharedStatic bis zu 13 Mal schneller gemacht.
Die folgenden Diagramme zeigen die Leistungsverbesserungen in Burst 1.7 im Vergleich zu Burst 1.6. Die Messungen wurden bei einem großen Kundenprojekt durchgeführt. Das erste Diagramm unten zeigt Zeitmessungen mit einer Stoppuhr (einer echten Stoppuhr, nicht System.Diagnostics.Stopwatch), die den Editor beobachtet, so dass sie die Art von Verbesserungen widerspiegeln, die Sie im täglichen Gebrauch erwarten können.

Das zweite Diagramm unten konzentriert sich nur auf Burst, schließt also alles andere aus, was im Editor vorkommen kann. Bei diesem speziellen Projekt und der geänderten Datei ist Burst 1.7 in allen drei Zeiträumen schneller als Burst 1.6:
- Cold cache - Burst hat noch keine Kompilierungsergebnisse für den Code in Ihrem Projekt zwischengespeichert.
- Warmer Cache - Burst hat den Code in Ihrem Projekt bereits kompiliert und muss die zwischengespeicherten Kompilierungsergebnisse von der Festplatte laden.
- Eine Datei ändern - Nachdem eine Datei geändert wurde, prüft Burst, welche Einstiegspunkte neu kompiliert werden müssen und kompiliert diese. Beachten Sie, dass der Umfang der Verbesserungen in Burst 1.7 im Allgemeinen davon abhängt, welche Datei geändert wird. Wenn Sie zum Beispiel eine Methode ändern, die von allen Burst-Einstiegspunkten verwendet wird, wird der Unterschied zwischen Burst 1.6 und Burst 1.7 geringer sein. In diesem Beispiel wurde die Methode des Einstiegspunkts selbst geändert.

Der Burst Inspector (erreichbar über Jobs > Burst > Open Inspector...) ist ein unglaublich nützliches Werkzeug für Optimierungsarbeiten. Mit diesem Tool können Sie den Assemblercode anzeigen, der auf der/den Ziel-CPU(s) ausgeführt werden soll. In Burst 1.7 haben wir mehrere häufig nachgefragte Funktionen hinzugefügt. Ein Bildschirmfoto sagt mehr als tausend Worte, also ohne Umschweife:

Wie Sie sehen können, haben wir Verzweigungsmarkierungen hinzugefügt, um die Codeausführungspfade einfacher zu visualisieren. Beachten Sie, dass die Zweigmarkierungen mit dem Kontrollkästchen "Zweigfluss anzeigen" ausgeschaltet werden können, damit sie nicht im Weg sind, wenn Sie sie nicht brauchen. Ein besonders schöner Aspekt dieser Funktion ist, dass Sie auf einen Verzweigungspfeil klicken können, um zum anderen Ende des Pfeils zu springen, etwa so:
Beispiel für das Anklicken der Abzweigungsmarkierung, um zum Abzweigungsziel zu springen
Weniger wichtige Blöcke der Disassemblierung (z. B. Direktiven oder konstante Daten) werden nun automatisch eingeklappt, können aber immer noch umgeschaltet werden, wenn Sie sie sehen möchten.
Ebenfalls neu in Burst 1.7 ist die Möglichkeit, nur einen Abschnitt der Disassemblierung auszuwählen und zu kopieren.
Beispiel für das Auswählen und Kopieren eines bestimmten Abschnitts der Disassemblierung
Hier ist eine Liste kleinerer, aber nicht weniger wichtiger Verbesserungen in Burst 1.7.
- Die Arm Neon vst1* APIs werden jetzt vollständig unterstützt. Wir haben diese APIs in Burst 1.6 hinzugefügt, sie aber hinter einem experimentellen #define versteckt. In Burst 1.7 sind sie nicht mehr hinter dieser #define versteckt und werden vollständig unterstützt.
- System.Span<T> und System.ReadOnlySpan<T> werden jetzt in Bursted-Code unterstützt. Diese Typen sind als Einstiegsargumente nicht zulässig.
- Burst verwendet jetzt standardmäßig LLVM Version 12.0.0 und bringt damit die neuesten Optimierungen des LLVM-Projekts mit.
- Wir haben die LLVM-Optimierungspipeline so geändert, dass der Loop-Unroller ausschließlich nach dem Loop-Vektorisierer ausgeführt wird. Dies verbessert den Codegen in vielen Fällen.
- Wir haben fmod und den Gleitkommamodul mit einem schnelleren Algorithmus ausgestattet, um die Leistung zu verbessern.
- Burst generiert nun automatisch eine link.xml, um IL-Stripping zu vermeiden, was zu fehlenden Symbolen zur Laufzeit bei der Verwendung statischer Konstruktoren führt.
- Wir haben die Compilerleistung bei großen Strukturkopien verbessert, indem wir mehr Fälle erkannt haben, in denen ein Laden/Speichern sicher in eine Move-Memory-Operation umgewandelt werden kann.
- Wir haben eine Änderung an der Darstellung der Zeitangaben vorgenommen, wenn die Option "Zeitangaben anzeigen" im Burst-Menü aktiviert ist. Durch Bereinigung und übersichtlichere Darstellung der Informationen.
Beachten Sie, dass Burst 1.7 die letzte Version ist, die Unity 2019.4 unterstützt. Die nächste Burst-Version wird mindestens Unity 2020.3 erfordern. Wenn Sie irgendwelche Gedanken oder Fragen haben oder uns einfach nur mitteilen möchten, was Sie mit Burst machen, können Sie uns gerne eine Nachricht im Burst-Forum hinterlassen.
