Domanda

C'è un modo tramite NET / C # per trovare il numero di core della CPU?

PS Questa è una domanda di codice dritto, non un "devo usare il multi-threading?" domanda! : -)

È stato utile?

Soluzione

Ci sono diversi pezzi di informazioni relative ai processori che si potrebbe ottenere:

  1. numero di processori fisici
  2. Numero di core
  3. numero di processori logici.

Questi possono essere tutti diversi; nel caso di una macchina con 2 processori-threading abilitato iper dual-core, ci sono 2 processori fisici, 4 core e 8 processori logici.

Il numero di processori logici è disponibile attraverso la Ambiente classe, ma le altre informazioni è disponibile solo tramite WMI (e potrebbe essere necessario installare alcuni hotfix o service pack per ottenere su alcuni sistemi):

Assicurarsi di aggiungere un riferimento nel progetto per System.Management.dll

Processori fisici:

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

core:

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);

processori logici:

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

o

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

Processori esclusi da Windows:

È inoltre possibile utilizzare le chiamate API di Windows in setupapi.dll per scoprire i processori che sono state escluse da Windows (per esempio tramite le impostazioni di avvio) e non sono rilevabili con i mezzi di cui sopra. Il codice che segue riporta il numero totale di processori logici (non sono stato in grado di capire come differenziare fisica da processori logici) che esistono, compresi quelli che sono stati esclusi da 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 - 1;
                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,
}

Altri suggerimenti

Environment.ProcessorCount

[Documentazione]

query WMI sono lenti, quindi cercate di selezionare solo i componenti desiderati invece di utilizzare Select *.

La seguente query richiede 3.4s:

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

Anche se questo si prende 0.122s:

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

Environment.ProcessorCount dovrebbe darvi il numero di anime sulla macchina locale.

E 'piuttosto interessante vedere come .NET ottenere questo internamente a dir poco ... E' come "semplice", come di seguito:

namespace System.Threading
{
    using System;
    using System.Runtime.CompilerServices;

    internal static class PlatformHelper
    {
        private const int PROCESSOR_COUNT_REFRESH_INTERVAL_MS = 0x7530;
        private static volatile int s_lastProcessorCountRefreshTicks;
        private static volatile int s_processorCount;

        internal static bool IsSingleProcessor
        {
            get
            {
                return (ProcessorCount == 1);
            }
        }

        internal static int ProcessorCount
        {
            get
            {
                int tickCount = Environment.TickCount;
                int num2 = s_processorCount;
                if ((num2 == 0) || ((tickCount - s_lastProcessorCountRefreshTicks) >= 0x7530))
                {
                    s_processorCount = num2 = Environment.ProcessorCount;
                    s_lastProcessorCountRefreshTicks = tickCount;
                }
                return num2;
            }
        }
    }
}

Il modo in cui il easyest = Environment.ProcessorCount Esempio da Environment.ProcessorCount proprietà

    using System;

    class Sample 

{
    public static void Main() 
    {
    Console.WriteLine("The number of processors " +
        "on this computer is {0}.", 
        Environment.ProcessorCount);
    }
}

Dalla sorgente di .NET Framework

È anche possibile ottenere con PInvoke sul Kernel32.dll

Il codice seguente viene più o meno da SystemInfo.cs dalla fonte System.Web situata qui :

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SYSTEM_INFO
{
  public ushort wProcessorArchitecture;
  public ushort wReserved;
  public uint dwPageSize;
  public IntPtr lpMinimumApplicationAddress;
  public IntPtr lpMaximumApplicationAddress;
  public IntPtr dwActiveProcessorMask;
  public uint dwNumberOfProcessors;
  public uint dwProcessorType;
  public uint dwAllocationGranularity;
  public ushort wProcessorLevel;
  public ushort wProcessorRevision;
}

internal static class SystemInfo 
{
    static int _trueNumberOfProcessors;
    internal static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);    

    [DllImport("kernel32.dll", CharSet = CharSet.Unicode)]
    internal static extern void GetSystemInfo(out SYSTEM_INFO si);

    [DllImport("kernel32.dll")]
    internal static extern int GetProcessAffinityMask(IntPtr handle, out IntPtr processAffinityMask, out IntPtr systemAffinityMask);

    internal static int GetNumProcessCPUs()
    {
      if (SystemInfo._trueNumberOfProcessors == 0)
      {
        SYSTEM_INFO si;
        GetSystemInfo(out si);
        if ((int) si.dwNumberOfProcessors == 1)
        {
          SystemInfo._trueNumberOfProcessors = 1;
        }
        else
        {
          IntPtr processAffinityMask;
          IntPtr systemAffinityMask;
          if (GetProcessAffinityMask(INVALID_HANDLE_VALUE, out processAffinityMask, out systemAffinityMask) == 0)
          {
            SystemInfo._trueNumberOfProcessors = 1;
          }
          else
          {
            int num1 = 0;
            if (IntPtr.Size == 4)
            {
              uint num2 = (uint) (int) processAffinityMask;
              while ((int) num2 != 0)
              {
                if (((int) num2 & 1) == 1)
                  ++num1;
                num2 >>= 1;
              }
            }
            else
            {
              ulong num2 = (ulong) (long) processAffinityMask;
              while ((long) num2 != 0L)
              {
                if (((long) num2 & 1L) == 1L)
                  ++num1;
                num2 >>= 1;
              }
            }
            SystemInfo._trueNumberOfProcessors = num1;
          }
        }
      }
      return SystemInfo._trueNumberOfProcessors;
    }
}

Una possibilità sarebbe quella di leggere i dati dal Registro di sistema. MSDN articolo sul tema: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine (v = vs.71) aspx )

I processori, credo che può essere situato qui, 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();
    }

Sono ragionevolmente sicuro la voce di registro sarà presente sulla maggior parte dei sistemi.

Anche se vorrei buttare la mia $ 0.02 in.

Il seguente programma stampa i core logici e fisici di una macchina Windows.

#define STRICT
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
#include <omp.h>

template<typename T>
T *AdvanceBytes(T *p, SIZE_T cb)
{
 return reinterpret_cast<T*>(reinterpret_cast<BYTE *>(p) + cb);
}

class EnumLogicalProcessorInformation
{
public:
 EnumLogicalProcessorInformation(LOGICAL_PROCESSOR_RELATIONSHIP Relationship)
  : m_pinfoBase(nullptr), m_pinfoCurrent(nullptr), m_cbRemaining(0)
 {
  DWORD cb = 0;
  if (GetLogicalProcessorInformationEx(Relationship,
                                       nullptr, &cb)) return;
  if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) return;

  m_pinfoBase =
   reinterpret_cast<SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *>
                                     (LocalAlloc(LMEM_FIXED, cb));
  if (!m_pinfoBase) return;

  if (!GetLogicalProcessorInformationEx(Relationship, 
                                        m_pinfoBase, &cb)) return;

  m_pinfoCurrent = m_pinfoBase;
  m_cbRemaining = cb;
 }

 ~EnumLogicalProcessorInformation() { LocalFree(m_pinfoBase); }

 void MoveNext()
 {
  if (m_pinfoCurrent) {
   m_cbRemaining -= m_pinfoCurrent->Size;
   if (m_cbRemaining) {
    m_pinfoCurrent = AdvanceBytes(m_pinfoCurrent,
                                  m_pinfoCurrent->Size);
   } else {
    m_pinfoCurrent = nullptr;
   }
  }
 }

 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *Current()
                                         { return m_pinfoCurrent; }
private:
 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *m_pinfoBase;
 SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX *m_pinfoCurrent;
 DWORD m_cbRemaining;
};


int __cdecl main(int argc, char **argv)
{
  int numLogicalCore = 0;
  int numPhysicalCore = 0;

  for (EnumLogicalProcessorInformation enumInfo(RelationProcessorCore);
      auto pinfo = enumInfo.Current(); enumInfo.MoveNext()) 
  {
      int numThreadPerCore = (pinfo->Processor.Flags == LTP_PC_SMT) ? 2 : 1;
      // std::cout << "thread per core: "<< numThreadPerCore << std::endl;
      numLogicalCore += numThreadPerCore;
      numPhysicalCore += 1;
  }

  printf ("Number of physical core = %d , Number of Logical core = %d \n", numPhysicalCore, numLogicalCore );

 char c = getchar(); /* just to wait on to see the results in the command prompt */
 return 0;
}

/*
I tested with Intel Xeon four cores with hyper threading and here is the result
Number of physical core = 4 , Number of Logical core = 8
*/

che stavo cercando la stessa cosa, ma io non voglio installare alcun NuGet o servicepack, così ho trovato questa soluzione, è abbastanza semplice e diretto, utilizzando questa discussione , ho pensato sarebbe così facile da eseguire quel comando WMIC e ottenere che il valore, ecco il codice C #. Hai solo bisogno di usare System.Management namespace (e di coppia spazi dei nomi più standard di processo e di così via).

    string fileName = Path.Combine(Environment.SystemDirectory, "wbem", "wmic.exe");
    string arguments = @"cpu get NumberOfCores";

    Process process = new Process
    {
        StartInfo =
        {
            FileName = fileName,
            Arguments = arguments,
            UseShellExecute = false,
            CreateNoWindow = true,
            RedirectStandardOutput = true,
            RedirectStandardError = true
        }
    };

    process.Start();

    StreamReader output = process.StandardOutput;
    Console.WriteLine(output.ReadToEnd());


    process.WaitForExit();
    int exitCode = process.ExitCode;
    process.Close();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top