Partager via


Modèles courants pour des applications multithread au comportement médiocre

Le visualiseur concurrentiel permet aux développeurs de visualiser le comportement d'une application multithread.Cet outil inclut une galerie de modèles courants pour des applications multithread qui se comportent de façon médiocre.La galerie comporte les modèles visuels standard et reconnaissables exposés via l'outil, une explication du comportement que représente chaque modèle, le résultat probable de ce comportement et l'approche la plus courante pour l'améliorer.

Contention de verrouillage et exécution sérialisée

Contention de verrouillage entraînant une exécution sérialisée

Parfois, une application parallélisée continue obstinément à s'exécuter de façon sérielle bien qu'elle ait plusieurs threads et que l'ordinateur ait un nombre suffisant de cœurs logiques.De faibles performances multithread, voire même une implémentation en série un peu plus lente, constituent le premier symptôme.Dans la vue Threads, vous ne voyez pas plusieurs threads fonctionnant en parallèle ; vous voyez plutôt qu'un seul thread s'exécute à un moment donné.À ce stade, si vous cliquez sur un segment de synchronisation dans un thread, vous pouvez voir une pile des appels pour le thread bloqué (pile des appels de blocage) et le thread qui a supprimé la condition de blocage (pile des appels de déblocage).De plus, si la pile des appels de déblocage se forme dans le processus que vous analysez, un connecteur de thread prêt s'affiche.De là, vous pouvez naviguer jusqu'à votre code à partir des piles des appels de blocage et de déblocage afin de rechercher de manière plus approfondie la cause de la sérialisation.

Comme indiqué dans l'illustration suivante, le visualiseur concurrentiel peut également faire état de ce symptôme dans la vue Utilisation de l'UC, où, en dépit de la présence de plusieurs threads, l'application consomme un seul cœur logique.

Pour plus d'informations, consultez le document intitulé « Performance Pattern 1: Identifying Lock Contention » du blog de Hazim Shafi Parallel Performance Tools For Windows sur le site Web des blogs MSDN.

Contention de verrouillage

Répartition inégale de la charge de travail

Charge de travail irrégulière

Lorsque la charge de travail est répartie de façon inégale sur plusieurs threads parallèles dans une application, elles forment un escalier à mesure que chaque thread accomplit son travail, comme indiqué dans l'illustration précédente .Le visualiseur concurrentiel présente souvent des heures de début très proches pour chaque thread simultané.Toutefois, ces threads se terminent généralement à des moments très différents au lieu de se terminer en même temps.Ce modèle indique une distribution irrégulière du travail parmi un groupe de threads parallèles, ce qui peut mener à des performances réduites.Face à un tel problème, la meilleure approche consiste à réévaluer l'algorithme avec lequel le travail a été réparti entre les threads parallèles.

Comme indiqué dans l'illustration suivante, le visualiseur concurrentiel peut également faire état de ce symptôme dans la vue Utilisation de l'UC, comme une baisse progressive de l'utilisation de l'UC.

Charge de travail irrégulière

Surabonnement

Surabonnement

Dans le cas d'un surabonnement, le nombre de threads actifs dans un processus est supérieur à celui des cœurs logiques disponibles sur le système.L'illustration précédente montre les résultats du surabonnement, avec une importante préemption pour tous les threads actifs.En outre, la légende montre un pourcentage considérable de temps passé en préemption (84 % dans cet exemple).Cela peut indiquer que le processus demande au système d'exécuter davantage de threads simultanés qu'il n'y a de cœurs logiques.Toutefois, cela peut également signifier que d'autres processus sur le système utilisent des ressources censées être disponibles pour ce processus.

Lorsque vous analysez les causes du problème, tenez compte des facteurs suivants :

  • Le système entier présente peut-être un surabonnement.Pensez à la possibilité que d'autres processus sur le système peuvent préempter vos threads.Si vous pointez la souris sur un segment de préemption dans la vue Threads, une info-bulle identifie le thread et le processus qui a préempté le thread.Ce processus n'est pas nécessairement celui qui a été exécuté pendant que votre processus était préempté, mais il peut permettre de déterminer l'origine de la pression de préemption auquel votre processus est soumis.

  • Évaluez la façon dont votre processus détermine le nombre approprié de threads pour l'exécution pendant cette phase de travail.Si votre processus calcule directement le nombre de threads parallèles actifs, envisagez de modifier cet algorithme pour dénombrer, au plus exact, les cœurs logiques disponibles sur le système.Si vous utilisez le runtime d'accès concurrentiel, la bibliothèque parallèle de tâches ou PLINQ, ces bibliothèques exécutent le travail du calcul du nombre de threads.

E/S inefficace

E/S inefficace

L'emploi excessif ou inapproprié d'E/S est communément à l'origine de problèmes d'inefficacité des applications.Observez l'illustration précédente.Le profil de chronologie visible montre que 42 % du temps de thread visible sont consommés par des E/S.La chronologie fait état d'un nombre considérable d'E/S, ce qui indique que l'application profilée est souvent bloquée par des E/S.Pour plus d'informations sur les genres d'E/S et pour déterminer l'endroit où votre programme se bloque, zoomez sur les zones à problème, examinez le profil de chronologie visible, puis cliquez sur un bloc d'E/S spécifique pour consulter les piles d'appels actuelles.

Convois de verrouillage

Convois de verrouillage

Les convois de verrouillage se produisent lorsque l'application acquiert des verrous dans un ordre premier arrivé, premier servi, et lorsque le taux d'arrivée au niveau du verrou est supérieur au taux d'acquisition.La combinaison de ces deux conditions provoque la sauvegarde des demandes de verrou.Pour résoudre ce problème, vous pouvez utiliser des verrous « unfair » qui donnent accès au premier thread qu'ils trouvent à l'état déverrouillé.L'illustration précédente décrit comment fonctionne le convoi.Pour remédier au problème, essayez de réduire la contention pour les objets de synchronisation et de recourir à des verrous « unfair ».

Voir aussi

Concepts

Affichage Threads (niveau de performance parallèle)