356 votes

Comment trouver le nombre de cœurs de processeur via .NET/C# ?

Y a-t-il un moyen via .NET/C# pour connaître le nombre de cœurs du processeur ?

PS : Il s'agit d'une question de code, pas d'une question sur l'utilisation du multithreading ! :-)

8 votes

Avez-vous besoin de savoir combien de cœurs il y a ou combien de processeurs logiques il y a ? Pour l'exécution de plusieurs threads, l'un ou l'autre est probablement suffisant, mais il existe des scénarios où la différence peut être importante.

0 votes

Existe-t-il une nouvelle façon de procéder ?

518voto

Kevin Kibler Points 5471

Il existe plusieurs informations différentes relatives aux processeurs que vous pouvez obtenir :

  1. Nombre de processeurs physiques
  2. Nombre de cœurs
  3. Nombre de processeurs logiques.

Tous ces éléments peuvent être différents ; dans le cas d'une machine équipée de 2 processeurs hyperthreading à double cœur, il y a 2 processeurs physiques, 4 cœurs et 8 processeurs logiques.

Le nombre de processeurs logiques est disponible par l'intermédiaire de l'interface utilisateur. Environnement mais les autres informations ne sont disponibles que par le biais de la classe WMI (et vous devrez peut-être installer des hotfixes ou service packs pour l'obtenir sur certains systèmes) :

Assurez-vous d'ajouter une référence à System.Management.dll dans votre projet. Dans .NET Core, il est disponible (pour Windows uniquement) sous la forme d'un paquet NuGet.

Processeurs physiques :

foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get())
{
    Console.WriteLine("Number Of Physical Processors: {0} ", item["NumberOfProcessors"]);
}

Cœurs :

int coreCount = 0;
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
{
    coreCount += int.Parse(item["NumberOfCores"].ToString());
}
Console.WriteLine("Number Of Cores: {0}", coreCount);

Processeurs logiques :

Console.WriteLine("Number Of Logical Processors: {0}", Environment.ProcessorCount);

OU

foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get())
{
    Console.WriteLine("Number Of Logical Processors: {0}", item["NumberOfLogicalProcessors"]);
}

Processeurs exclus de Windows :

Vous pouvez également utiliser les appels de l'API Windows dans setupapi.dll pour découvrir les processeurs qui ont été exclus de Windows (par exemple par les paramètres de démarrage) et qui ne sont pas détectables par les moyens ci-dessus. Le code ci-dessous donne le nombre total de processeurs logiques (je n'ai pas réussi à trouver comment différencier les processeurs physiques des processeurs logiques) qui existent, y compris ceux qui ont été exclus de Windows :

static void Main(string[] args)
{
    int deviceCount = 0;
    IntPtr deviceList = IntPtr.Zero;
    // GUID for processor classid
    Guid processorGuid = new Guid("{50127dc3-0f36-415e-a6cc-4cb3be910b65}");

    try
    {
        // get a list of all processor devices
        deviceList = SetupDiGetClassDevs(ref processorGuid, "ACPI", IntPtr.Zero, (int)DIGCF.PRESENT);
        // attempt to process each item in the list
        for (int deviceNumber = 0; ; deviceNumber++)
        {
            SP_DEVINFO_DATA deviceInfo = new SP_DEVINFO_DATA();
            deviceInfo.cbSize = Marshal.SizeOf(deviceInfo);

            // attempt to read the device info from the list, if this fails, we're at the end of the list
            if (!SetupDiEnumDeviceInfo(deviceList, deviceNumber, ref deviceInfo))
            {
                deviceCount = deviceNumber;
                break;
            }
        }
    }
    finally
    {
        if (deviceList != IntPtr.Zero) { SetupDiDestroyDeviceInfoList(deviceList); }
    }
    Console.WriteLine("Number of cores: {0}", deviceCount);
}

[DllImport("setupapi.dll", SetLastError = true)]
private static extern IntPtr SetupDiGetClassDevs(ref Guid ClassGuid,
    [MarshalAs(UnmanagedType.LPStr)]String enumerator,
    IntPtr hwndParent,
    Int32 Flags);

[DllImport("setupapi.dll", SetLastError = true)]
private static extern Int32 SetupDiDestroyDeviceInfoList(IntPtr DeviceInfoSet);

[DllImport("setupapi.dll", SetLastError = true)]
private static extern bool SetupDiEnumDeviceInfo(IntPtr DeviceInfoSet,
    Int32 MemberIndex,
    ref SP_DEVINFO_DATA DeviceInterfaceData);

[StructLayout(LayoutKind.Sequential)]
private struct SP_DEVINFO_DATA
{
    public int cbSize;
    public Guid ClassGuid;
    public uint DevInst;
    public IntPtr Reserved;
}

private enum DIGCF
{
    DEFAULT = 0x1,
    PRESENT = 0x2,
    ALLCLASSES = 0x4,
    PROFILE = 0x8,
    DEVICEINTERFACE = 0x10,
}

14 votes

@StingyJack : C'est vrai, mais j'aimerais que ce soit dans un format plus agréable. La découvrabilité est assez faible lorsque vous devez construire des requêtes de chaînes brutes.

5 votes

WMI Code Creator vous aidera à découvrir des valeurs et à créer des requêtes (il peut même générer des stubs en c#/vb.net).

0 votes

Je ne trouve pas ManagementObjectSearcher dans System.Managment.

233voto

280Z28 Points 49515
Environment.ProcessorCount

[Documentation]

18 votes

C'est tellement simple et beau que j'en ai presque les larmes aux yeux. Merci pour la réponse !

80 votes

Cela donne le nombre de processeurs logiques, et non le nombre de cœurs.

10 votes

@KevinKibler D'après la question, je pense que le PO ne comprend pas la différence, et si vous ne connaissez pas la différence, c'est probablement ce que vous voulez.

38voto

Aleix Mercader Points 201

Les requêtes WMI sont lentes, essayez donc de ne sélectionner que les membres souhaités au lieu d'utiliser Select *.

La requête suivante prend 3.4s :

foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())

Alors que celui-ci prend 0.122s :

foreach (var item in new System.Management.ManagementObjectSearcher("Select NumberOfCores from Win32_Processor").Get())

1 votes

Sur quel système fonctionnez-vous ? J'utilise plusieurs requêtes "Select *" et cela ne prend pas de temps. partout près de 3,4 secondes, testé sur des milliers d'ordinateurs sur lesquels mon logiciel est déployé. Je fais un Select * parce que j'obtiens plusieurs propriétés de l'objet. Cependant, je le fais un peu différemment : je crée un ObjectQuery sur le Select * ; je récupère le ManagementObjectCollection ; puis foreach ManagementObject dans le ManagementObjectCollection.

0 votes

@deegee : vous avez raison, la requête elle-même ne prend pas beaucoup plus de temps avec "Select *", c'est juste que le parsing des int ci-dessous est lent si l'on itère toutes les valeurs retournées au lieu de seulement NumberOfCores.

19voto

Mithrax Points 1906

Nombre de processeurs de l'environnement devrait vous donner le nombre de cœurs sur la machine locale.

62 votes

Cela donne le nombre de processeurs logiques, et non le nombre de cœurs.

1voto

IrishGeek82 Points 339

Une option serait de lire les données à partir du registre. Article MSDN sur le sujet : http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v=vs.71).aspx )

Les processeurs, je crois qu'ils peuvent être localisés ici, HKEY_LOCAL_MACHINE \HARDWARE\DESCRIPTION\System\CentralProcessor

    private void determineNumberOfProcessCores()
    {
        RegistryKey rk = Registry.LocalMachine;
        String[] subKeys = rk.OpenSubKey("HARDWARE").OpenSubKey("DESCRIPTION").OpenSubKey("System").OpenSubKey("CentralProcessor").GetSubKeyNames();

        textBox1.Text = "Total number of cores:" + subKeys.Length.ToString();
    }

Je suis raisonnablement sûr que l'entrée dans le registre sera présente sur la plupart des systèmes.

Mais je voudrais ajouter mon grain de sel.

0 votes

Cela donnera le nombre de processeurs qui est déjà disponible dans Environment.ProcessorCount, y a-t-il un autre moyen similaire pour obtenir le nombre de cœurs pour chaque processeur ?

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