58 votes

Comment créer des threads sur différents cœurs de processeur?

Disons que j'avais un programme en C# qui fait quelque chose de gourmand en ressources, comme l'encodage d'une liste de fichiers WAV en MP3. Normalement, je voudrais encoder les fichiers un à un moment, mais disons que je voulais le programme pour trouver le nombre de cœurs du PROCESSEUR, j'ai eu et faire tourner l'encodage d'un fil sur chaque cœur. Donc, quand je lance le programme sur un PROCESSEUR quad core, le programme des chiffres, c'est un quad core CPU, les chiffres il y a quatre cœurs à travailler, puis génère quatre threads pour le codage, chaque de ce qui est en cours d'exécution sur son propre PROCESSEUR. Comment puis-je faire?

Et cela serait-il différent si les carottes sont étalés sur plusieurs CPU physique? Comme dans, si j'avais une machine avec deux CPU quad core sur celle-ci, existe-il des considérations particulières ou sont les huit cœurs à travers les deux matrices considérées comme égales dans Windows?

59voto

Jorge Córdoba Points 18919

Ne pas la peine de le faire.

Au lieu d'utiliser le Pool de Threads. Le pool de threads est un mécanisme (en fait une classe) de la cadre que vous pouvez faire une requête pour un nouveau thread.

Lorsque vous demandez un nouveau thread, il va vous donner une nouvelle ou mise en file d'attente le travail jusqu'à ce qu'un thread d'être libéré. De cette manière, le cadre est en charge de décider si elle devrait créer plus de threads ou pas en fonction du nombre de Processeurs présents.

Edit: En plus, comme il a déjà été mentionné, le système d'exploitation est chargé de la distribution des threads entre les différents Processeurs.

16voto

Joe Erickson Points 4571

Il n'est pas nécessairement aussi simple que d'utiliser le pool de threads.

Par défaut, le pool de threads alloue plusieurs threads pour chaque PROCESSEUR. Étant donné que chaque thread qui s'implique dans le travail que vous faites a un coût (les tâches de commutation de la surcharge, utilisation de la CPU est très limitée L1, L2 et peut-être de cache L3, etc...), le nombre optimal de threads à utiliser est <= le nombre de CPU - à moins que chaque thread est une demande de services à partir d'autres machines - comme un très évolutif de service web. Dans certains cas, particulièrement ceux qui impliquent plus de disque dur, la lecture et l'écriture de l'activité de l'UC, vous pouvez effectivement être mieux avec 1 fil de plusieurs threads.

Pour la plupart des applications, et certainement pour les fichiers WAV et MP3 encodage, vous devez limiter le nombre de threads de travail pour le nombre de processeurs disponibles. Voici un code C# pour trouver le nombre de processeurs:

int processors = 1;
string processorsStr = System.Environment.GetEnvironmentVariable("NUMBER_OF_PROCESSORS");
if (processorsStr != null)
    processors = int.Parse(processorsStr);

Malheureusement, il n'est pas aussi simple que vous vous limitez le nombre de processeurs. Vous devez également prendre en compte la performance du contrôleur de disque dur(s) et disque(s).

La seule façon que vous pouvez vraiment trouver le nombre optimal de threads est l'essai une erreur. Cela est particulièrement vrai lorsque vous utilisez des disques durs, des services web et autres. Avec les disques durs, vous pourriez être mieux de ne pas utiliser tous les quatre transformateurs sur vous processeur quad CPU. D'autre part, certains services web, vous pourriez être mieux de faire 10 ou même 100 demandes par UC.

8voto

Peter Meyer Points 11163

Dans le cas de la gestion des threads, la complexité de la faire, c'est d'un degré supérieur à celui de threads natifs. C'est parce que CLR les threads ne sont pas directement liés à un système d'exploitation natif fil. En d'autres termes, le CLR peut faire basculer un gérés thread thread natif de natif des threads comme il l'entend. La fonction Thread.BeginThreadAffinity est prévu pour un thread géré de concert avec un système d'exploitation natif fil. À ce stade, vous pourriez expérimenter avec l'aide des API natives de donner de la sous-jacentes thread natif de l'affinité du processeur. Comme tout le monde le suggère ici, ce n'est pas une très bonne idée. En fait, il existe de la documentation suggère que les threads peuvent recevoir moins de temps si elles sont limitées à un seul processeur ou de base.

Vous pouvez également explorer le Système.Diagnostics.Processus de la classe. De là, vous pouvez trouver une fonction pour énumérer un processus, threads comme une collection de ProcessThread objets. Cette classe possède des méthodes pour définir ProcessorAffinity ou même choisir un préféré processeur -- vous ne savez pas ce que c'est.

Avertissement: j'ai connu un problème similaire où je pensais que le CPU(s) ont été sous-utilisés et des recherches sur beaucoup de ce genre de choses; cependant, d'après tout ce que j'ai lu, il semble que se n'était pas une très bonne idée, comme en témoignent les commentaires postés ici. Cependant, il est toujours intéressant et une expérience d'apprentissage à l'expérimentation.

3voto

Eric Z Beard Points 18473

Vous ne devriez pas avoir à vous soucier de le faire vous-même. J'ai des applications .NET multithreads s'exécutant sur des machines à double quad, et quelle que soit la façon dont les threads sont démarrés, que ce soit via le ThreadPool ou manuellement, je vois une belle répartition des tâches dans tous les cœurs.

2voto

Adam Haile Points 12576

La gestion de chaque thread est généralement gérée par le système d'exploitation lui-même ... alors générez 4 threads sur un système à 4 cœurs et le système d'exploitation décidera des cœurs à exécuter, qui correspond généralement à 1 thread sur chaque cœur.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X