如何通过.NET / C#查找CPU内核数?

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

有没有办法通过.net/c找出CPU核心的数量?

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


与处理器有关的信息有几种不同的部分,你可以:

  • 物理处理器数
  • 核心数
  • Number of logical processors.
  • 这些都是不同的;在一台具有两个双核心超线程处理器的机器中,有两个物理处理器,四个核心,八个逻辑处理器。

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

    确保在您的项目中添加一个参考到系统。

    物理处理器:

    ZZU1

    核心:

    1
    2
    3
    4
    5
    6
    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);

    逻辑处理器:

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

    黄金

    1
    2
    3
    4
    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:

    你也可以在Setupapi.dll中使用API呼叫,以发现被排除在窗口(E.G.through boot settings)之外的处理器,而这些处理器在上面没有检测到。The code below gives the total number of logical processors(I have not been able to figure out how to differentiate physical from logical processors)that exist,including those that have been excluded from windows:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    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,
    }


    1
    Environment.ProcessorCount

    [文件]


    WMI Queries are slow,so try to select only the desired members instead of using select*。

    The following query takes 3.4s:

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

    While this one takes 0.122s:

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


    Environment.ProcessorCount should give you the number of cores on the local machine.


    我不想让你知道这是怎么回事就像下面的"简单"

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    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;
                }
            }
        }
    }


    简单的方式Example from Environment.ProcesorCount Property

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        using System;

        class Sample

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


    从净框架源

    你也可以在Kernel32.dll

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    [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;
        }
    }


    一个选项是从登记处读取数据。MSDN article on the topic:http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(V=vs.71).

    处理器,我相信可以在这里定位,HKEY Local machine hardware

    1
    2
    3
    4
    5
    6
    7
        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();
        }

    我有理由相信,登记入口将在大多数系统。

    尽管我会把我的0.02


    随后的程序印刷了一个窗口机的逻辑和物理核心。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    #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
    "
    , 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
    */


    我一直在寻找同样的东西,但我不想安装任何水果或餐巾纸,所以我找到了这个解决办法,它很简单,向前看,使用这一讨论,我认为运行WMIC命令和获得价值是很容易的,这里是C 35;代码。你只需要使用系统.管理名称空间(并对过程和过程中更多的标准名称空间)。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
        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();