c# .net cpu-cores

¿Cómo encontrar el número de núcleos de CPU a través de.NET/C#?



cpu-cores (10)

¿Existe alguna forma a través de .NET / C # para averiguar el número de núcleos de CPU?

PS Esta es una pregunta de código directo, no un "¿Debo usar subprocesos múltiples?" ¡pregunta! :-)


Desde la fuente de .NET Framework

También puede obtenerlo con PInvoke en Kernel32.dll

El siguiente código viene más o menos de SystemInfo.cs de la fuente de System.Web que se encuentra here :

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


El siguiente programa imprime los núcleos lógicos y físicos de una máquina con 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 */


Es bastante interesante ver cómo .NET consigue esto internamente para decir lo menos ... Es tan "simple" como a continuación:

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


Estaba buscando lo mismo, pero no quiero instalar ningún nuget o paquete de servicio, por lo que encontré esta solución, es bastante simple y sencillo. Usando this discusión, pensé que sería tan fácil de ejecutar ese comando de WMIC. y obtener ese valor, aquí está el código C #. Solo necesita usar el espacio de nombres System.Management (y unir más espacios de nombres estándar para el proceso, etc.).

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


Las consultas de WMI son lentas, así que intente seleccionar solo los miembros deseados en lugar de usar Select *.

La siguiente consulta toma 3.4s:

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

Si bien éste toma 0.122s:

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


The the easyest way = Environment.ProcessorCount Exemple from Environment.ProcessorCount Property

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


Una opción sería leer los datos del registro. Artículo de MSDN sobre el tema: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v=vs.71).aspx )

Los procesadores, creo que se pueden ubicar aquí, 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(); }

Estoy razonablemente seguro de que la entrada del registro estará allí en la mayoría de los sistemas.

Aunque yo tiraría mis $ 0.02.


Environment debe proporcionarle el número de núcleos en la máquina local.


Hay varios datos diferentes relacionados con los procesadores que puede obtener:

  1. Número de procesadores físicos
  2. Numero de nucleos
  3. Número de procesadores lógicos.

Todos estos pueden ser diferentes; en el caso de una máquina con 2 procesadores de doble núcleo habilitados para hyper-threading, hay 2 procesadores físicos, 4 núcleos y 8 procesadores lógicos.

El número de procesadores lógicos está disponible a través de la clase Environment , pero la otra información solo está disponible a través de WMI (y es posible que tenga que instalar algunas revisiones o paquetes de servicio para obtenerlos en algunos sistemas):

Asegúrese de agregar una referencia en su proyecto a System.Management.dll

Procesadores físicos:

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

Núcleos

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

Procesadores lógicos:

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"]); }

Procesadores excluidos de Windows:

También puede usar las llamadas a la API de Windows en setupapi.dll para descubrir los procesadores que han sido excluidos de Windows (por ejemplo, a través de la configuración de inicio) y no son detectables utilizando los medios anteriores. El siguiente código proporciona el número total de procesadores lógicos (no he podido averiguar cómo diferenciar los procesadores físicos de los lógicos) que existen, incluidos los que se han excluido 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 - 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, }