如何通过 .NET/C# 找到 CPU 核心数?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1542213/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 18:39:55  来源:igfitidea点击:

How to find the Number of CPU Cores via .NET/C#?

c#.netcpu-cores

提问by MrGreggles

Is there a way via .NET/C#to find out the number of CPU cores?

有没有办法通过.NET/C#找出 CPU 内核的数量?

PS This is a straight code question, not a "Should I use multi-threading?" question! :-)

PS 这是一个直接的代码问题,而不是“我应该使用多线程吗?” 题!:-)

采纳答案by Kevin Kibler

There are several different pieces of information relating to processors that you could get:

您可以获得与处理器相关的多种不同信息:

  1. Number of physical processors
  2. Number of cores
  3. Number of logical processors.
  1. 物理处理器数量
  2. 核心数
  3. 逻辑处理器的数量。

These can all be different; in the case of a machine with 2 dual-core hyper-threading-enabled processors, there are 2 physical processors, 4 cores, and 8 logical processors.

这些都可以不同;在具有 2 个双核超线程处理器的机器的情况下,有 2 个物理处理器、4 个内核和 8 个逻辑处理器。

The number of logical processors is available through the Environmentclass, but the other information is only available through WMI(and you may have to install some hotfixes or service packsto get it on some systems):

逻辑处理器的数量可通过Environment类获得,但其他信息只能通过WMI 获得(并且您可能需要安装一些修补程序或服务包才能在某些系统上获得它):

Make sure to add a reference in your project to System.Management.dllIn .NET Core, this is available (for Windows only) as a NuGet package.

确保在项目中添加对 System.Management.dll 的引用。在 .NET Core 中,这作为 NuGet 包可用(仅适用于 Windows)。

Physical Processors:

物理处理器:

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

Cores:

核心:

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

Logical Processors:

逻辑处理器:

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

OR

或者

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

Processors excluded from Windows:

从 Windows 中排除的处理器:

You can also use Windows API calls in setupapi.dllto discover processors that have been excluded from Windows (e.g. through boot settings) and aren't detectable using the above means. The code below gives the total number of logical processors (I haven't been able to figure out how to differentiate physical from logical processors) that exist, including those that have been excluded from Windows:

您还可以在setupapi.dll 中使用 Windows API 调用来发现已从 Windows 中排除(例如通过启动设置)并且无法使用上述方法检测到的处理器。下面的代码给出了存在的逻辑处理器总数(我一直无法弄清楚如何区分物理处理器和逻辑处理器),包括那些已从 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,
}

回答by Sam Harwell

Environment.ProcessorCount

[Documentation]

[文档]

回答by Mithrax

Environment.ProcessorCountshould give you the number of cores on the local machine.

Environment.ProcessorCount应该为您提供本地机器上的内核数。

回答by Aleix Mercader

WMI queries are slow, so try to Select only the desired members instead of using Select *.

WMI 查询很慢,因此请尝试仅选择所需的成员,而不是使用 Select *。

The following query takes 3.4s:

以下查询需要 3.4 秒:

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

While this one takes 0.122s:

虽然这个需要 0.122 秒:

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

回答by Arumugam Muruganantham

The following program prints the logical and physical cores of a windows machine.

以下程序打印 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
*/

回答by IrishGeek82

One option would be to read the data from the registry. MSDN Article On The Topic: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v=vs.71).aspx)

一种选择是从注册表中读取数据。有关该主题的 MSDN 文章:http: //msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v= vs.71) .aspx)

The processors, I believe can be located here, HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor

处理器,我相信可以位于这里,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();
    }

I am reasonably sure the registry entry will be there on most systems.

我有理由确信大多数系统上都会有注册表项。

Though I would throw my $0.02 in.

虽然我会投入 0.02 美元。

回答by Armen

I was looking for the same thing but I don't want to install any nuget or servicepack, so I found this solution, it is pretty simple and straight forward, using thisdiscussion, I thought it would be so easy to run that WMIC command and get that value, here is the C# code. You only need to use System.Management namespace (and couple more standard namespaces for process and so on).

我一直在寻找同样的东西,但我不想安装任何 nuget 或 servicepack,所以我找到了这个解决方案,它非常简单直接,使用这个讨论,我认为运行该 WMIC 命令会很容易并获得该值,这里是 C# 代码。您只需要使用 System.Management 命名空间(并为进程等耦合更多标准命名空间)。

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

回答by Ostati

It's rather interesting to see how .NET get this internally to say the least... It's as "simple" as below:

看看 .NET 如何在内部至少可以这么说是相当有趣的......它就像下面一样“简单”:

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

回答by Fab

From .NET Framework source

来自 .NET Framework 源

You can also get it with PInvokeon Kernel32.dll

你也可以用得到它的PInvokeKernel32.dll

The following code is coming more or less from SystemInfo.csfrom System.Web source located here:

以下代码或多或少来自SystemInfo.cs位于此处的System.Web 源代码:

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

回答by Sanfour ben sanfer

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

在该easyest方式=Environment.ProcessorCount
为例,从Environment.ProcessorCount物业

using System;

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