Mises à jour du backend MSVC dans Visual Studio 2019 Preview 2: nouvelles optimisations, améliorations OpenMP et Build Throughput


Dans Visual Studio 2019 Preview 2, nous avons continué d'améliorer le backend C ++ avec de nouvelles fonctionnalités, des optimisations nouvelles et améliorées, des améliorations de débit de construction et des changements de qualité de vie.


Original dans le blog

De nouvelles fonctionnalités


  • Ajout d'un nouveau commutateur de ligne de commande en ligne: -Ob3. -Ob3 est une version plus agressive de -Ob2. -O2 (optimiser le binaire pour la vitesse) implique toujours -Ob2 par défaut, mais cela pourrait changer à l'avenir. Si vous trouvez que le compilateur est insignifiant, pensez à passer -O2 -Ob3.
  • Ajout de la prise en charge de base de la vectorisation OpenMP SIMD, qui est la fonctionnalité OpenMP la plus utilisée dans les bibliothèques d'apprentissage automatique (ML). Notre étude de cas est la bibliothèque Intel MKL-DNN, qui est utilisée comme bloc de construction pour d'autres bibliothèques ML open source bien connues, y compris Tensor Flow. Cela peut être activé avec un nouveau commutateur CL -openmp: experimental. Cela permet aux boucles annotées avec «#pragma omp simd» d'être potentiellement vectorisées. La vectorisation n'est pas garantie et les boucles annotées mais non vectorisées recevront un avertissement. Aucune clause SIMD n'est prise en charge, elles seront simplement ignorées avec un avertissement signalé.
  • Ajout d'un nouveau gestionnaire d'exceptions C ++ __CxxFrameHandler4 qui réduit de 66% la surcharge des métadonnées de gestion des exceptions. Cela fournit jusqu'à 15% d'amélioration de la taille binaire totale sur les binaires qui utilisent de grandes quantités de gestion des exceptions C ++. Actuellement désactivé par défaut, essayez-le en passant «/ d2FH4» lors de la compilation avec cl.exe. Notez que / d2FH4 est autrement non documenté et non pris en charge à long terme. Ce n'est pas actuellement pris en charge sur les applications UWP car le runtime UWP n'a pas encore cette fonctionnalité.
  • Pour prendre en charge la vectorisation manuelle des boucles contenant des appels aux fonctions de bibliothèque mathématique et certaines autres opérations telles que la division entière, MSVC prend désormais en charge les fonctions intrinsèques SVML (Short Vector Math Library) qui calculent les équivalents vectoriels. La prise en charge des vecteurs 128 bits, 256 bits et 512 bits est disponible pour la plupart des fonctions, avec les exceptions répertoriées ci-dessous. Notez que ces fonctions ne définissent pas errno. Voir le Guide Intel Intrinsic pour les définitions des fonctions prises en charge.
    Les exceptions comprennent:
    • La division et le reste combinés des entiers vectoriels ne sont disponibles que pour les éléments 32 bits et les longueurs vectorielles 128 bits et 256 bits. Utilisez des fonctions de division et de reste distinctes pour d'autres tailles d'éléments et longueurs de vecteur.
    • La racine carrée SVML n'est disponible qu'en longueurs vectorielles 128 bits et 256 bits. Vous pouvez utiliser les fonctions _mm512_sqrt_pd ou _mm512_sqrt_ps pour les vecteurs 512 bits.
    • Seules les versions vectorielles 512 bits des fonctions rint et à proximitéint sont disponibles. Dans de nombreux cas, vous pouvez utiliser des fonctions rondes à la place, par exemple, utilisez _mm256_round_ps (x, _MM_FROUND_CUR_DIRECTION) en tant que version vectorielle 256 bits de rint , ou _mm256_round_ps (x, _MM_FROUND_TO_NEAREST_INT) pour la valeur à proximité .
    • Seule la réciproque de 512 bits est fournie. Vous pouvez calculer l'équivalent en utilisant les fonctions set1 et div, par exemple la réciproque 256 bits peut être calculée comme _mm256_div_ps (_mm256_set1_ps (1.0f), (x)) .
    • Il existe des fonctions SVML pour la racine carrée complexe simple précision, le logarithme et l'exponentiation uniquement dans les longueurs vectorielles de 128 bits et 256 bits.

Optimisations nouvelles et améliorées


  • Les memsets non déroulés et les initialisations de bloc utiliseront désormais les instructions SSE2 (ou les instructions AVX si elles sont autorisées). Le seuil de taille pour ce qui sera déroulé a augmenté en conséquence (compilation pour la taille avec SSE2: le seuil de déroulement passe de 31 à 63 octets, compilation pour la vitesse avec SSE2: le seuil passe de 79 à 159 octets).
  • Optimisation du code-gen pour les petits ensembles de mems, principalement destinés aux fonctions protégées par initall .
  • Améliorations apportées à l'élimination des magasins redondants de l' optimiseur SSA : meilleure analyse des échappements et meilleure gestion des boucles
  • Le compilateur reconnaît memmove () comme une fonction intrinsèque et optimise en conséquence. Cela améliore la génération de code pour les opérations basées sur memmove (), y compris std :: copy () et d'autres codes de bibliothèque de niveau supérieur tels que std :: vector et std :: string construction
  • L'optimiseur optimise les opérations memmove (), memcpy () et memcmp () courtes et de longueur fixe.
  • Optimisation de la duplication des commutateurs implémentée pour de meilleures performances des commutateurs dans les boucles chaudes. Nous avons dupliqué les sauts de commutateur pour améliorer la précision de la prédiction de branche et, par conséquent, les performances d'exécution.
  • Ajout de simplifications à pliage constant et arithmétiques pour les expressions utilisant SIMD (vector) intrinsèque, pour les formes flottantes et entières. La plupart des optimisations d'expression habituelles gèrent désormais les intrinsèques SSE2 et AVX2, soit à partir du code utilisateur, soit à la suite d'une vectorisation automatique.
  • Plusieurs nouveaux modèles scalaires fusionnés à multiplication-addition (FMA) sont identifiés avec / arch: AVX2 / fp: fast. Il s'agit notamment des expressions courantes suivantes: (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
  • Les séquences de code qui initialisent une valeur __m128 SIMD (vecteur) élément par élément sont identifiées et remplacées par un intrinsèque _mm_set_ps . Cela permet aux nouvelles optimisations SIMD de considérer la valeur comme faisant partie des expressions, particulièrement utile si la valeur n'a que des éléments constants. Une future mise à jour prendra en charge plus de types de valeur.
  • L'élimination de la sous-expression commune (ESC) est plus efficace en présence de variables qui peuvent être modifiées de manière indirecte car elles ont leur adresse prise.
  • Des copies de structure / classe inutiles sont supprimées dans plusieurs autres cas, y compris des copies de paramètres de sortie et de fonctions renvoyant un objet. Cette optimisation est particulièrement efficace dans les programmes C ++ qui transmettent des objets par valeur.
  • Ajout d'une analyse plus puissante pour extraire des informations sur les variables du flux de contrôle (instructions if / else / switch), utilisée pour supprimer les branches dont on peut prouver qu'elles sont toujours vraies ou fausses et pour améliorer l'estimation de la plage de variables. Le code utilisant gsl :: span voit des améliorations, certaines vérifications de plage inutiles étant maintenant supprimées.
  • L'optimisation de la dévirtualisation aura désormais des opportunités supplémentaires, comme lorsque les classes sont définies dans des espaces de noms anonymes.

Améliorations du débit de génération


  • Filtrez les informations de débogage pendant la compilation en fonction des symboles et types référencés pour réduire la taille de la section de débogage et améliorer le débit de l'éditeur de liens. La mise à jour de 15,9 à 16,0 peut réduire la taille d'entrée de l'éditeur de liens jusqu'à 40%.
  • Amélioration du temps de liaison dans la fusion et la création de type PDB.
  • La mise à jour vers 16.0 à partir de 15.9 peut améliorer les temps de liaison jusqu'à une accélération 2X. Par exemple, la liaison de Chrome a entraîné une accélération de la liaison de 1,75 X lors de l'utilisation de / DEBUG: complet et une accélération de la liaison de 1,4 X lors de l'utilisation de / DEBUG: fastlink.

Améliorations de la qualité de vie


  • Le compilateur affiche les noms et les chemins d'accès aux fichiers à l'aide de la casse fournie par l'utilisateur, où auparavant le compilateur affichait les noms et les chemins d'accès aux fichiers inférieurs.
  • Le nouvel éditeur de liens signalera désormais les symboles potentiellement correspondants pour les symboles non résolus, comme:

 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 
  • Lors de la génération d'une bibliothèque statique, il n'est plus nécessaire de passer l'indicateur / LTCG à LIB.exe.
  • Ajout d'une option de l'éditeur de liens / LINKREPROTARGET: [nom_binaire] pour générer uniquement une reproduction de lien pour le binaire spécifié. Cela permet à% LINK_REPRO% ou / LINKREPRO: [nom_répertoire] d'être défini dans une grande construction avec plusieurs liaisons, et l'éditeur de liens ne générera que la repro pour le binaire spécifié dans / linkreprotarget.

Nous aimerions que vous téléchargiez Visual Studio 2019 et que vous l'essayiez. Comme toujours, nous apprécions vos commentaires. Nous pouvons être contactés via les commentaires ci-dessous ou par e-mail ( visualcpp@microsoft.com ). Si vous rencontrez des problèmes avec Visual Studio ou MSVC, ou si vous avez une suggestion à nous faire, veuillez nous en informer via Aide> Envoyer des commentaires> Signaler un problème / Fournir une suggestion dans le produit ou via la communauté des développeurs . Vous pouvez également nous trouver sur Twitter ( @VisualC ) et Facebook (msftvisualcpp).

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


All Articles