Question

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 PROCESSEUR quad core, chiffres de 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 Processeurs physiques?Comme dans, si j'avais une machine avec deux Processeurs quadricœurs sur elle, existe-il des considérations particulières ou sont les huit cœurs à travers les deux matrices considérées comme égales dans Windows?

Était-ce utile?

La solution

Ne pas la peine de le faire.

Au lieu d'utiliser l' Le Pool De Thread.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 outre, comme il a déjà été mentionné, le système d'exploitation est chargé de la distribution des threads entre les différents Processeurs.

Autres conseils

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 CPU.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.

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é thread thread natif de natif des threads comme il l'entend.La fonction Fil de discussion.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 n'est la documentation ce qui 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 les Système.Diagnostics.Processus 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 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.

Même si je suis d'accord avec la plupart des réponses ici, je pense que ça vaut le coup d'ajouter un nouveau compte:La technologie Speedstep.

Lors de l'exécution d'un CPU intensive, mono-thread de travail sur un système multi-core, dans mon cas, un Xeon E5-2430 avec 6 de véritables noyaux (12 HT) sous windows server 2012, l'emploi a obtenu réparti entre tous les 12 cœurs, à l'aide autour de 8,33% de chaque cœur et de ne jamais déclencher une augmentation de la vitesse.Le CPU est resté à 1.2 GHz.

Lorsque j'ai mis le fil d'affinité pour une base spécifique, il a utilisé ~100% de la carotte, provoquant le CPU au maximum à 2,5 GHz, de plus que doubler le rendement.

C'est le programme que j'ai utilisé, qui vient de boucles de l'augmentation d'une variable.Lorsqu'il est appelé avec un, il va définir l'affinité de base 1.L'affinité de la partie a été basée sur ce post.

using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;

namespace Esquenta
{
    class Program
    {
        private static int numThreads = 1;
        static bool affinity = false;
        static void Main(string[] args)
        {
            if (args.Contains("-a"))
            {
                affinity = true;
            }
            if (args.Length < 1 || !int.TryParse(args[0], out numThreads))
            {
                numThreads = 1;
            }
            Console.WriteLine("numThreads:" + numThreads);
            for (int j = 0; j < numThreads; j++)
            {
                var param = new ParameterizedThreadStart(EsquentaP);
                var thread = new Thread(param);
                thread.Start(j);
            }

        }

        static void EsquentaP(object numero_obj)
        {
            int i = 0;
            DateTime ultimo = DateTime.Now;
            if(affinity)
            {
                Thread.BeginThreadAffinity();
                CurrentThread.ProcessorAffinity = new IntPtr(1);
            }
            try
            {
                while (true)
                {
                    i++;
                    if (i == int.MaxValue)
                    {
                        i = 0;
                        var lps = int.MaxValue / (DateTime.Now - ultimo).TotalSeconds / 1000000;
                        Console.WriteLine("Thread " + numero_obj + " " + lps.ToString("0.000") + " M loops/s");
                        ultimo = DateTime.Now;
                    }
                }
            }
            finally
            {
                Thread.EndThreadAffinity();
            }
        }

        [DllImport("kernel32.dll")]
        public static extern int GetCurrentThreadId();

        [DllImport("kernel32.dll")]
        public static extern int GetCurrentProcessorNumber();
        private static ProcessThread CurrentThread
        {
            get
            {
                int id = GetCurrentThreadId();
                return Process.GetCurrentProcess().Threads.Cast<ProcessThread>().Single(x => x.Id == id);
            }
        }
    }
}

Et les résultats:

results

La vitesse du processeur, comme indiqué par le gestionnaire de Tâches, semblables à ce que CPU-Z les rapports:

enter image description here

Vous ne devriez pas avoir à vous soucier de faire vous-même.J'ai multithread .NET applications en cours d'exécution sur le dual-quad machines, et peu importe comment les threads sont lancés, que ce soit via le pool de threads ou manuellement, je vois un joli même la répartition du travail dans tous les cœurs.

Vous pouvez certainement le faire par écrit la routine à l'intérieur de votre programme.

Cependant, vous ne devriez pas essayer de le faire, car le Système d'Exploitation est le meilleur candidat pour gérer ces trucs.Je veux dire en mode utilisateur programme ne devrait pas essayer de le faire.

Cependant, parfois, il peut être fait (pour vraiment de l'utilisateur avancé) pour réaliser l'équilibrage de la charge et de trouver un vrai multi thread multi core problème (données de course/cohérence de cache...) que les différents threads serait vraiment de l'exécution sur le processeur différent.

Cela dit, si vous souhaitez réaliser, nous pouvons le faire de la manière suivante.Je vous fournis le code de pseudo pour(Windows OS), mais il pourrait facilement être fait sur Linux.

#define MAX_CORE 256
processor_mask[MAX_CORE] = {0};
core_number = 0;

Call GetLogicalProcessorInformation();
// From Here we calculate the core_number and also we populate the process_mask[] array
// which would be used later on to set to run different threads on different CORES.


for(j = 0; j < THREAD_POOL_SIZE; j++)
Call SetThreadAffinityMask(hThread[j],processor_mask[j]);
//hThread is the array of handles of thread.
//Now if your number of threads are higher than the actual number of cores,
// you can use reset the counters(j) once you reach to the "core_number".

Après les au-dessus de routine est appelée, le fils serait toujours en cours d'exécution dans la manière suivante:

Thread1-> Core1
Thread2-> Core2
Thread3-> Core3
Thread4-> Core4
Thread5-> Core5
Thread6-> Core6
Thread7-> Core7
Thread8-> Core8

Thread9-> Core1
Thread10-> Core2
...............

Pour plus d'informations, veuillez vous référer au manuel/MSDN pour en savoir plus sur ces concepts.

Où chaque thread va, c'est généralement gérés par l'OS lui-même...afin de générer de 4 threads sur un 4 cœur du système, et le système d'exploitation doit décider qui de noyaux d'exécution de chaque sur le, qui sera généralement en 1 fil sur chaque cœur.

C'est le système d'exploitation de split fils à travers les différents cœurs, et il en sera ainsi lorsque automatiquement lors de vos discussions sont en utilisant beaucoup de temps CPU.Ne vous inquiétez pas à ce sujet.Que pour trouver le nombre de cœurs de votre utilisateur, essayez Environment.ProcessorCount en C#.

vous ne pouvez pas faire cela, comme seul système d'exploitation qui a les privilèges de le faire.Si vous le décidez.....ensuite, il sera difficile pour les applications de code.Parce qu'alors, vous avez également besoin de prendre soin de l'inter-processeur de communication.les sections critiques.pour chaque application, vous devez créer vous-même des sémaphores ou d'un mutex......pour le système d'exploitation qui donne une solution commune par le faire lui-même.......

L'une des raisons pour lesquelles vous ne devriez pas (comme cela a été dit), essayez attribué ce genre de choses vous-même, c'est que vous n'avez tout simplement pas assez d'informations pour le faire correctement, en particulier dans le futur avec NUMA, etc.

Si vous avez un thread de lecture à exécuter, et il y a un noyau de l'inactivité, le noyau va exécutez votre fil, ne vous inquiétez pas.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top