2017-09-28 2 views
0

Je veux comprendre comment se passe un certain scénario de changement de contexte. Supposons que j'ai 10 cœurs de processeur exécutant un seul processus. Tout est gourmand en CPU, aucun thread ne dort (en attente d'E/S).Commutateur de contexte: que se passe-t-il dans le cas le plus défavorable?

(je suis surtout préoccupé par les architectures informatiques modernes personnels traditionnels et les systèmes, généralement x64 avec Windows, Linux ...)

-moi si je me trompe: en cours d'exécution 10 CPU/RAM threads indépendants est plus intensive souvent une situation quasi optimale. Le temps passé en changement de contexte est plutôt négligeable. Alors que le système peut parfois décider de réattribuer des threads à différents cœurs de manière circulaire en provoquant une réinitialisation des caches RAM, cela a un effet mineur et fonctionne presque comme si chaque thread était exécuté sur un seul cœur fixe.

Seul le bus RAM principal peut être une limitation puisque tous les threads le partagent, mais ce n'est pas le point qui m'intéresse ici. Réduire le nombre de threads n'augmentera pas le débit de toute façon. Maintenant, supposons que vous avez toujours 10 cœurs mais que vous exécutez 1000 threads. Le planificateur pourrait théoriquement décider de passer rarement (disons chaque seconde) à 10 threads pendant une seconde, puis à 10 autres ... et le tout serait encore proche des performances optimales (débit).

Mais cela ne semble pas être le cas et il semble que les threads soient commutés de manière intensive, ce qui entraîne une performance fortement sous-optimale (débit). Ai-je raison? Quelle est la cause principale de cette performance sous-optimale? Quelques chiffres seraient bien si vous avez une idée des ordres de grandeur de (par exemple): commutateurs par seconde, perte de performance causée par la commutation ...

+0

Un système d'exploitation tel que Windows permet à un thread de fonctionner pendant 3 ticks d'horloge avant de passer le processeur à un autre. Donc, environ 47 millisecondes. Le coût réel d'un changement de contexte dépend grandement de la façon dont il jette les données dans les caches du processeur. Ces jours-ci, le pire des cas est d'environ 15 000 cycles. Donc, sur un noyau de 3 GHz qui est d'environ 0,01% de frais généraux. Avoir un millier de threads actifs n'est bien sûr jamais bon pour le débit, les cycles de calcul sont une ressource finie. –

Répondre

0

Je vais répondre à ma propre question (après quelques recherches).

Sur les fenêtres, le nombre de changements de contexte peut être mesuré avec des compteurs de performance: https://technet.microsoft.com/en-us/library/cc938606.aspx

je l'ai mesuré sur ma machine (Core i7/Windows 10) et l'ordre de grandeur est d'environ 1000/s par coeur quand le nombre de threads en cours d'exécution est supérieur au nombre de cœurs (et ces threads sont plein CPU).

Le temps nécessaire pour un changement de contexte varie assez peu selon:

  • ce que les registres doivent être sauvegardés
  • si les registres FPU doivent être enregistrés
  • le modèle de processeur (bien sûr)

Vous pouvez lire: https://www.quora.com/How-long-does-a-context-switch-take ou http://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html

Une moyenne légèrement pessimiste. l'ordre de grandeur semble être de 1000 ns. Ainsi, le temps total pour tous les commutateurs de contexte sur chaque cœur est de 1 ms par seconde, soit 0,1%.

Cela ne dépend pas du nombre de threads: si vous exécutez 100 ou 1000 threads, le nombre de commutateurs ne change pas. En conclusion, le temps passé en changement de contexte est en quelque sorte négligeable.

Ce raisonnement est correct tant que les threads sont pure CPU avec seulement une petite mémoire en lecture/écriture comme quelques variables locales. J'ai effectué un test avec des threads CPU complets et la différence entre quelques threads et 1000 n'est pas perceptible.

Mais la situation change lorsque la RAM est impliquée et les commutateurs rendent le cache CPU (mémoire) moins efficace. Un pire cas est celui où:

    calcul
  • peut être divisé en 1000 « données » indépendantes pièces
  • chaque partie des données correspond seulement dans le cache de la mémoire (par exemple L1 ou L2) d'un noyau
  • chaque partie doit être lu plusieurs fois

Dans cette situation, en cours d'exécution 10 threads à la fin, puis dix autres ... seraient tirer le meilleur parti du cache, lors de l'exécution 1000 threads à la fois serait et la mémoire cache être utile seulement pendant 1ms. Mais si les données de plusieurs threads peuvent entrer dans le cache, ou si les threads lisent des données communes dans une certaine mesure ou si chaque thread lit les données une seule fois, il est possible que 1000 threads soient exécutés par rapport à 10 threads une centaine de fois aura un débit similaire.

Il s'agit plus d'un parallélisme d'adaptation à l'accès mémoire. Et cela dépend beaucoup de la façon dont la mémoire doit être accessible. Le temps passé en changement de contexte est négligeable, le temps perdu en raison d'une mauvaise utilisation des caches peut parfois poser problème, parfois non, selon la façon dont la mémoire est accédée et partagée.