Wie finde ich die Anzahl der CPU-coree über .NET / C #?

Gibt es einen Weg über .NET / C # , um die Anzahl der CPU-coree herauszufinden?

PS Dies ist eine Frage mit einem geraden Code, nicht ein “Sollte ich Multithreading verwenden?” Frage! 🙂

    Es gibt verschiedene Informationen zu processoren, die Sie erhalten könnten:

    1. Anzahl der physischen processoren
    2. Anzahl der coree
    3. Anzahl der logischen processoren

    Diese können alle verschieden sein; Im Fall einer Maschine mit zwei Dual-Core-Hyper-Threading-fähigen processoren gibt es 2 physikalische processoren, 4 coree und 8 logische processoren.

    Die Anzahl der logischen processoren ist über die Environment- class verfügbar, die anderen Informationen sind jedoch nur über WMI verfügbar (und Sie müssen möglicherweise einige Hotfixes oder Service Packs installieren, um sie auf einigen Systemen zu erhalten):

    Stellen Sie sicher, eine Referenz in Ihrem Projekt zu System.Management.dll hinzuzufügen

    Physische processoren:

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

    coree:

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

    Logische processoren:

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

    ODER

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

    Von Windows ausgeschlossene processoren:

    Sie können auch Windows-API-Aufrufe in setupapi.dll verwenden, um nach processoren zu suchen , die von Windows ausgeschlossen wurden (z. B. über Starteinstellungen ) und die mit den oben genannten Methoden nicht erkannt werden können . Der folgende Code gibt die Gesamtanzahl der logischen processoren (ich bin nicht in der Lage gewesen, physikalische von logischen processoren zu unterscheiden), einschließlich der, die von Windows ausgeschlossen wurden:

     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, } 
     Environment.ProcessorCount 

    [Dokumentation]

    WMI-Abfragen sind langsam. Versuchen Sie daher, anstelle von Select * nur die gewünschten Elemente auszuwählen.

    Die folgende Abfrage benötigt 3.4s:

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

    Während dieser 0.122s dauert:

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

    Environment.ProcessorCount sollte Ihnen die Anzahl der coree auf dem lokalen Computer geben.

    Es ist ziemlich interessant zu sehen, wie .NET das innerlich erhält, um es gelinde auszudrücken … Es ist so “einfach” wie unten:

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

    Von der .NET Framework-Quelle

    Sie können es auch mit PInvoke auf coreel32.dll

    Der folgende Code stammt mehr oder weniger von SystemInfo.cs aus der Quelle System.Web, die sich hier befindet :

     [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 { 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; } } 

    Der einfachste Weg = Environment.ProcessorCount Beispiel aus der Environment.ProcessorCount-Eigenschaft

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

    Eine Möglichkeit wäre, die Daten aus der Registrierung zu lesen. MSDN-Artikel zum Thema: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v=vs.71).aspx )

    Die processoren, glaube ich, können hier gefunden werden, 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(); } 

    Ich bin mir ziemlich sicher, dass der Registrierungseintrag auf den meisten Systemen vorhanden sein wird.

    Obwohl ich meine $ 0,02 reincasting würde.

    Das folgende Programm druckt die logischen und physischen coree eines Windows-Rechners.

     #define STRICT #include "stdafx.h" #include  #include  #include  template T *AdvanceBytes(T *p, SIZE_T cb) { return reinterpret_cast(reinterpret_cast(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 (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 */ 

    Ich war auf der Suche nach der gleichen Sache, aber ich möchte kein nugget oder Servicepack installieren, also fand ich diese Lösung, es ist ziemlich einfach und direkt, mit dieser Diskussion dachte ich, es wäre so einfach, diesen WMIC-Befehl auszuführen und diesen Wert erhalten, hier ist der C # -Code. Sie müssen nur den System.Management-Namespace verwenden (und weitere Standardnamespaces für den process usw. koppeln).

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