2016-10-26 1 views
1

dans un seul programme de fil, comment sont les modifications apportées par filetage dans le noyau 1 rendu visible à l'autre du noyau 2, de sorte qu'après un changement de contexte du fil (maintenant en cours d'exécution sur le noyau 2) aura une valeur mise à jour?visibilité des données sur le processeur à plusieurs noyaux par fil unique

Prenons l'exemple suivant:

  1. La valeur dans la mémoire principale pour la variable x est 10.

  2. Le fil passe sur le noyau 1 et les changements x à 5, qui est toujours dans la mémoire cache et pas encore vidé à la mémoire principale car nous n'utilisons aucune barrière de mémoire.

  3. Un interrupteur contexte se produit et le fil se déplace de noyau 1 à noyau 2.

  4. Le fil lit la valeur du x.

Quelle serait la valeur de x si fil reprend l'exécution dans le noyau 2 après le changement de contexte? Si la «cohérence du cache» gère la cohérence pour gérer un cas comme ci-dessus, pourquoi avons-nous besoin d'un verrouillage explicite (ou d'une barrière de lecture/écriture) dans un programme multithread?

Répondre

2

Compte tenu de votre première question, le contexte commutateurs conserve également le contenu du registre. Par conséquent, les threads voient la dernière valeur, même s'ils sont déplacés vers un autre core (ou CPU).

Cependant, pour un programme multi-thread, CPU registres sont distincts pour différents threads (quel que soit le nombre de noyaux les fils sont exécutés), et les registres ne font pas partie de la cohérence du cache.

Par conséquent, je pense, un programme multi-thread n'a pas besoin d'assurer que les valeurs des registres sont mis à jour avec les valeurs de la mémoire principale. (La cohérence du cache permet uniquement de s'assurer que le cache de l'UC est à jour avec la mémoire). Par conséquent, je suppose, vous avez besoin d'une barrière pour synchroniser le registre avec la mémoire.

Vous pouvez comprendre que cela: le programme fonctionne essentiellement uniquement sur la mémoire principale. Cependant, les compilateurs optimiser l'accès à la mémoire principale et d'utiliser registres pour les opérations intermédiaires. Ainsi, le programme n'accède qu'à la mémoire et aux registres. Cependant, l'unité centrale de traitement introduit également son propre cache de la mémoire. Les lectures et les écritures depuis/vers la mémoire sont internes (par la CPU) optimisées par le cache. La cohérence du cache assure que dans le CPU, que le cache est mise à jour (et, par conséquent, un programme accès mémoire obtient la valeur correcte.)

Pour résumer:

  • Cache cohérence assure cache et mémoire sont à jour, il est hors du contrôle du programme, car il est interne à la CPU.
  • Les commutateurs de contexte sont gérés par le système d'exploitation, ce qui garantit les valeurs correctes des registres lors du déplacement de threads vers différents cœurs.
  • barrières mémoire veillent à ce que les registres et mémoire sont à jour, c'est ce que le programme doit assurer.
+0

J'avais d'abord manqué que les valeurs des registres sont copiées pendant le changement de contexte. Les liens suivants l'illustrent bien. http://stackoverflow.com/questions/3920284/how-are-registers-shared-among-threads http://stackoverflow.com/questions/10371842/how-each-thread-can-have-cpu-registers https://www.quora.com/Do-the-threads-within-a-process-have-their-own-registers-but-use-the-same-code-global-data-and-stack – javaq