MSVC-Backend-Updates in Visual Studio 2019 Vorschau 2: Neue Optimierungen, OpenMP- und Build-Durchsatzverbesserungen


In Visual Studio 2019 Preview 2 haben wir das C ++ - Backend mit neuen Funktionen, neuen und verbesserten Optimierungen, Verbesserungen des Build-Durchsatzes und Änderungen der Lebensqualität weiter verbessert.


Original im Blog

Neue Funktionen


  • Ein neuer Inlining-Befehlszeilenschalter wurde hinzugefügt: -Ob3. -Ob3 ist eine aggressivere Version von -Ob2. -O2 (die Binärdatei für die Geschwindigkeit optimieren) impliziert standardmäßig weiterhin -Ob2, dies kann sich jedoch in Zukunft ändern. Wenn Sie feststellen, dass der Compiler nicht ausreichend inline ist, sollten Sie -O2 -Ob3 übergeben.
  • Grundlegende Unterstützung für die OpenMP-SIMD-Vektorisierung hinzugefügt, die die am häufigsten verwendete OpenMP-Funktion in ML-Bibliotheken (Machine Learning) ist. Unsere Fallstudie ist die Intel MKL-DNN-Bibliothek, die als Baustein für andere bekannte Open-Source-ML-Bibliotheken einschließlich Tensor Flow verwendet wird. Dies kann mit einem neuen CL-Schalter -openmp: experimentell aktiviert werden. Dadurch können mit "#pragma omp simd" annotierte Schleifen möglicherweise vektorisiert werden. Die Vektorisierung ist nicht garantiert, und kommentierte, aber nicht vektorisierte Schleifen erhalten eine Warnung. Es werden keine SIMD-Klauseln unterstützt. Sie werden einfach ignoriert, wenn eine Warnung gemeldet wird.
  • Es wurde ein neuer C ++ - Ausnahmebehandler __CxxFrameHandler4 hinzugefügt, der den Metadatenaufwand für die Ausnahmebehandlung um 66% reduziert. Dies bietet eine Verbesserung der Binärgröße um bis zu 15% gegenüber Binärdateien, die große Mengen an C ++ - Ausnahmebehandlung verwenden. Probieren Sie es aus, indem Sie beim Kompilieren mit cl.exe "/ d2FH4" übergeben. Beachten Sie, dass / d2FH4 ansonsten nicht dokumentiert ist und langfristig nicht unterstützt wird. Dies wird derzeit in UWP-Apps nicht unterstützt, da die UWP-Laufzeit noch nicht über diese Funktion verfügt.
  • Um die Handvektorisierung von Schleifen zu unterstützen, die Aufrufe von Funktionen der Mathematikbibliothek und bestimmte andere Operationen wie die Ganzzahldivision enthalten, unterstützt MSVC jetzt die intrinsischen Funktionen der Short Vector Math Library (SVML), die die Vektoräquivalente berechnen. Die meisten Funktionen werden von 128-Bit-, 256-Bit- und 512-Bit-Vektoren unterstützt, mit den unten aufgeführten Ausnahmen. Beachten Sie, dass diese Funktionen errno nicht setzen. Definitionen der unterstützten Funktionen finden Sie im Intel Intrinsic Guide.
    Ausnahmen sind:
    • Die kombinierte Division und der Rest von Vektor-Ganzzahlen sind nur für 32-Bit-Elemente und 128-Bit- und 256-Bit-Vektorlängen verfügbar. Verwenden Sie separate Teilungs- und Restfunktionen für andere Elementgrößen und Vektorlängen.
    • Die SVML-Quadratwurzel ist nur in 128-Bit- und 256-Bit-Vektorlängen verfügbar. Sie können die Funktionen _mm512_sqrt_pd oder _mm512_sqrt_ps für 512-Bit-Vektoren verwenden.
    • Es sind nur 512-Bit-Vektorversionen von Rint- und Nearintintint- Funktionen verfügbar. In vielen Fällen können Sie stattdessen runde Funktionen verwenden, z. B. _mm256_round_ps (x, _MM_FROUND_CUR_DIRECTION) als 256-Bit-Vektorversion von rint oder _mm256_round_ps (x, _MM_FROUND_TO_NEAREST_INT) für nearint .
    • Es wird nur ein 512-Bit-Kehrwert bereitgestellt. Sie können das Äquivalent mit den Funktionen set1 und div berechnen, z. B. könnte der 256-Bit-Kehrwert als _mm256_div_ps (_mm256_set1_ps (1.0f), (x)) berechnet werden.
    • Es gibt SVML-Funktionen für komplexe Quadratwurzel, Logarithmus und Exponentiation mit einfacher Genauigkeit nur in 128-Bit- und 256-Bit-Vektorlängen.

Neue und verbesserte Optimierungen


  • Abgerollte Memsets und Blockinitialisierungen verwenden jetzt SSE2-Anweisungen (oder AVX-Anweisungen, falls zulässig). Der Größenschwellenwert für das, was abgewickelt wird, hat sich entsprechend erhöht (Kompilieren für Größe mit SSE2: Schwellenwert für Abrollen von 31 auf 63 Byte, Kompilieren für Geschwindigkeit mit SSE2: Schwellenwert von 79 auf 159 Byte).
  • Das Code-Gen wurde für kleine Memsets optimiert, die hauptsächlich auf initial geschützte Funktionen abzielen .
  • Verbesserungen bei der Beseitigung redundanter Speicher durch den SSA Optimizer : Bessere Escape-Analyse und Handhabung von Schleifen
  • Der Compiler erkennt memmove () als intrinsische Funktion und optimiert entsprechend. Dies verbessert die Codegenerierung für Operationen, die auf memmove () basieren, einschließlich std :: copy () und anderem übergeordneten Bibliothekscode wie std :: vector und std :: string
  • Der Optimierer kann kurze memmove () -, memcpy () - und memcmp () -Operationen mit fester Länge besser optimieren.
  • Implementierung der Optimierung der Switch-Duplizierung für eine bessere Leistung der Switches in Hot Loops. Wir haben die Switch-Jumps dupliziert, um die Genauigkeit der Verzweigungsvorhersage und damit die Laufzeitleistung zu verbessern.
  • Konstante Faltung und arithmetische Vereinfachungen für Ausdrücke unter Verwendung von SIMD (Vektor) intrinsisch hinzugefügt, sowohl für Float- als auch für Integer-Formen. Die meisten der üblichen Ausdrucksoptimierungen verarbeiten jetzt SSE2- und AVX2-Eigenheiten, entweder aus Benutzercode oder als Ergebnis einer automatischen Vektorisierung.
  • Mehrere neue FMA-Muster (Scalar Fused Multiply Add) sind mit / arch: AVX2 / fp: fast gekennzeichnet. Dazu gehören die folgenden allgemeinen Ausdrücke: (x + 1.0) * y; (x – 1.0) * y; (1.0 – x) * y; (-1.0 – x) * y (x + 1.0) * y; (x – 1.0) * y; (1.0 – x) * y; (-1.0 – x) * y
  • Codesequenzen, die einen __m128 SIMD (Vektor) -Wert Element für Element initialisieren, werden identifiziert und durch ein intrinsisches _mm_set_ps ersetzt . Dadurch können die neuen SIMD-Optimierungen den Wert als Teil von Ausdrücken betrachten. Dies ist insbesondere dann nützlich, wenn der Wert nur konstante Elemente enthält. Ein zukünftiges Update wird mehr Werttypen unterstützen.
  • Common Sub-Expression Elimination (CSE) ist effektiver, wenn Variablen vorhanden sind, die auf indirekte Weise geändert werden können, weil ihre Adresse übernommen wurde.
  • In mehreren weiteren Fällen werden nutzlose Struktur- / Klassenkopien entfernt, einschließlich Kopien für Ausgabeparameter und Funktionen, die ein Objekt zurückgeben. Diese Optimierung ist besonders effektiv in C ++ - Programmen, die Objekte nach Wert übergeben.
  • Es wurde eine leistungsfähigere Analyse zum Extrahieren von Informationen über Variablen aus dem Kontrollfluss (if / else / switch-Anweisungen) hinzugefügt, mit der Verzweigungen entfernt werden, die sich als immer wahr oder falsch erweisen können, und um die Schätzung des Variablenbereichs zu verbessern. Code, der gsl :: span verwendet, weist Verbesserungen auf. Einige unnötige Bereichsprüfungen werden jetzt entfernt.
  • Die Optimierung der Devirtualisierung bietet jetzt zusätzliche Möglichkeiten, z. B. wenn Klassen in anonymen Namespaces definiert werden.

Durchsatzverbesserungen erstellen


  • Filtern Sie Debug-Informationen während der Kompilierung anhand der Symbole und Typen, auf die verwiesen wird, um die Größe des Debug-Abschnitts zu verringern und den Linker-Durchsatz zu verbessern. Durch das Aktualisieren von 15.9 auf 16.0 kann die Eingabegröße für den Linker um bis zu 40% reduziert werden.
  • Verbesserungen der Verbindungszeit beim Zusammenführen und Erstellen von PDB-Typen.
  • Durch die Aktualisierung von 15.9 auf 16.0 können die Verbindungszeiten um das Zweifache beschleunigt werden. Das Verknüpfen von Chrome führte beispielsweise bei Verwendung von / DEBUG: full zu einer 1,75-fachen Beschleunigung der Verbindungszeit und bei Verwendung von / DEBUG: fastlink zu einer 1,4-fachen Beschleunigung der Verbindungszeit.

Verbesserung der Lebensqualität


  • Der Compiler zeigt Dateinamen und Pfade unter Verwendung eines vom Benutzer bereitgestellten Gehäuses an, wobei der Compiler zuvor Dateinamen und Pfade in Kleinbuchstaben angezeigt hat.
  • Der neue Linker meldet nun potenziell übereinstimmende Symbole für nicht aufgelöste Symbole, wie z.

 main.obj : error LNK2019: unresolved external symbol _foo referenced in function _main Hint on symbols that are defined and could potentially match: "int __cdecl foo(int)" (?foo@@YAHH@Z) "bool __cdecl foo(double)" (?foo@@YA_NN@Z) @foo@0 foo@@4 main.exe : fatal error LNK1120: 1 unresolved externals 
  • Beim Generieren einer statischen Bibliothek muss das Flag / LTCG nicht mehr an LIB.exe übergeben werden.
  • Linker-Option / LINKREPROTARGET: [Binärname] hinzugefügt, um nur einen Link-Repro für die angegebene Binärdatei zu generieren. Dadurch können% LINK_REPRO% oder / LINKREPRO: [Verzeichnisname] in einem großen Build mit mehreren Verknüpfungen festgelegt werden, und der Linker generiert nur den Repro für die in / linkreprotarget angegebene Binärdatei.

Wir würden uns freuen, wenn Sie Visual Studio 2019 herunterladen und ausprobieren. Wie immer freuen wir uns über Ihr Feedback. Sie erreichen uns über die folgenden Kommentare oder per E-Mail ( visualcpp@microsoft.com ). Wenn Sie Probleme mit Visual Studio oder MSVC haben oder einen Vorschlag für uns haben, teilen Sie uns dies bitte über Hilfe> Feedback senden> Problem melden / Vorschlag im Produkt oder über die Entwickler-Community mit . Sie finden uns auch auf Twitter ( @VisualC ) und Facebook (msftvisualcpp).

Source: https://habr.com/ru/post/de437670/


All Articles