Lorsque vous démarrez plusieurs threads sur un processeur multicœur, sont-ils garantis pour être traités par des cœurs différents?

24

J'ai un processeur Pentium core i5, qui a 4 cœurs. Si je fais cela dans un programme de console C #

var t1 = new Thread(Thread1);
var t2 = new Thread(Thread2);
t1.Start();
t2.Start();

les threads t1 et t2 sont-ils garantis pour fonctionner sur des cœurs séparés?

developer747
la source
1
En supposant que le runtime C # utilise des appels système natifs équivalents pour générer un autre thread (et est donc vraiment parallèle; ce n'est pas le cas pour tout, comme le fameux Global Interpreter Lock de CPython ), cela dépendrait uniquement du planificateur de processus / tâche du système d'exploitation . En général cependant, le code est vraiment thread-safe si vous supposez cela t1et t2est exécuté à différents moments dans un ordre arbitraire (par exemple, il est possible de t2démarrer avant t1 dans certains modèles).
Percée du
2
Je ne savais pas qu'il y avait des processeurs Pentium i5. Peut-être que vous vouliez dire Core i5? Picky. Je sais: D
JosephGarrone

Réponses:

18

Vous ne pouvez pas garantir dans .Net que deux Threads s'exécutent sur deux cœurs distincts. En fait, vous ne pouvez pas non plus garantir que l'un Threadfonctionnera sur un seul cœur (!) .

Cela est dû au fait que les threads gérés ne sont pas identiques aux threads du système d'exploitation - un seul thread géré peut utiliser plusieurs threads du système d'exploitation pour le prendre en charge. En C #, vous ne traitez que directement avec les Threads gérés (au moins, sans recourir à p / invoke pour appeler les fonctions de threading WinAPI, ce que vous ne devriez jamais faire) .

Cependant, les planificateurs de threads .Net et Windows sont très bons dans ce qu'ils font - ils n'exécuteraient pas deux threads sur un seul cœur tandis qu'un deuxième cœur est complètement inactif. Donc, en général, vous n'avez pas à vous en préoccuper.

BlueRaja - Danny Pflughoeft
la source
Dans la pratique, .Net Threads sont des fils OS. Mais ce n'est pas pourquoi il n'y a aucune garantie qu'un seul thread s'exécutera toujours sur le même noyau.
svick
2
@svick: En pratique, sur x86 , c'est vrai. Cependant, la norme indique explicitement que vous ne pouvez pas vous fier à ce comportement, il pourrait donc changer à l'avenir. En fait, ce n'est pas vrai sur d'autres versions du .Net CLR, comme la XBox 360.
BlueRaja - Danny Pflughoeft
@BlueRaja - La question est spécifique de quelle version du CLR nous parlons. Vous pouvez garantir que quelque chose existera sur deux cœurs séparés en utilisant des threads asynchrones, car cela signifierait qu'ils se produiraient asynchrones l'un de l'autre. L'exemple de code actuel est techniquement un appel de synchronisation. Bien sûr, le système d'exploitation décide quels cœurs seront utilisés.
Ramhound
@Ramhound "Vous pouvez garantir que quelque chose existera sur deux cœurs séparés en utilisant des threads asynchrones" - c'est faux. Le asyncmot-clé (qui est ce dont je suppose que vous parlez, car les "threads asynchrones" est redondant) est juste du sucre syntaxique pour utiliser un BackgroundWorkerthread, qui est comme n'importe quel autre thread .Net - vous ne pouvez pas garantir qu'il fonctionnera sur un noyau séparé ou non.
BlueRaja - Danny Pflughoeft
@BlueRaja - Si deux threads asynchrones étaient démarrés, ils s'exécuteraient tous les deux en même temps à condition qu'il y ait 2 cœurs de processeur. S'il n'y en avait qu'un, le système d'exploitation planifierait le moment où chaque thread serait prioritaire et s'exécuterait et votre situation de thrashing à thread unique typique se produirait. C'est ainsi que l'on m'a appris comment un processeur traite des multi-threads.
Ramhound
15

Non, le système d'exploitation et le processeur décideront quoi exécuter et quand. dans l'exemple simple que vous avez montré, à l'exclusion d'autres tâches, oui, celles-ci s'exécuteraient très probablement en parallèle sur des cœurs séparés, mais il est rarement garanti que ce sera le cas.

Vous pouvez utiliser l' affinité de thread pour tenter de prendre un certain contrôle sur l'allocation d'un noyau à un thread donné.

Pensez également à planifier les priorités pour empiler le jeu en fonction des threads qui doivent être entièrement parallèles et de ceux qui peuvent attendre.

Frank Thomas
la source
1
Je veux également ajouter qu'avec les technologies de virtualisation, il existe une autre couche entre votre programme et le matériel. Ce que le système d'exploitation présente à l'application peut ne pas être physiquement précis.
Keltari
1
Ce sont des fonctions WinAPI pour les threads du système d'exploitation, pas pour les threads gérés. Ils ne doivent jamais être appelés à partir de C #, car ils pourraient gravement interférer avec le planificateur de threads .Net.
BlueRaja - Danny Pflughoeft