Có cách nào thông qua .NET / C # để tìm ra số lượng lõi CPU không?
PS Đây là một câu hỏi mã thẳng, không phải là "Tôi có nên sử dụng đa luồng không?" câu hỏi :-)
Có cách nào thông qua .NET / C # để tìm ra số lượng lõi CPU không?
PS Đây là một câu hỏi mã thẳng, không phải là "Tôi có nên sử dụng đa luồng không?" câu hỏi :-)
Câu trả lời:
Có một số thông tin khác nhau liên quan đến bộ xử lý mà bạn có thể nhận được:
Những điều này có thể khác nhau; trong trường hợp máy có 2 bộ xử lý siêu phân luồng kép, có 2 bộ xử lý vật lý, 4 lõi và 8 bộ xử lý logic.
Số lượng bộ xử lý logic có sẵn thông qua lớp Môi trường , nhưng thông tin khác chỉ có sẵn thông qua WMI (và bạn có thể phải cài đặt một số hotfix hoặc gói dịch vụ để có được nó trên một số hệ thống):
Đảm bảo thêm một tham chiếu trong dự án của bạn vào System.Man Quản lý Trong .NET Core, điều này có sẵn (chỉ dành cho Windows) dưới dạng gói NuGet.
Bộ xử lý vật lý:
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get())
{
Console.WriteLine("Number Of Physical Processors: {0} ", item["NumberOfProcessors"]);
}
Lõi:
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);
Bộ xử lý logic:
Console.WriteLine("Number Of Logical Processors: {0}", Environment.ProcessorCount);
HOẶC LÀ
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get())
{
Console.WriteLine("Number Of Logical Processors: {0}", item["NumberOfLogicalProcessors"]);
}
Bộ xử lý loại trừ khỏi Windows:
Bạn cũng có thể sử dụng các lệnh gọi API của Windows trong setupapi.dll để khám phá các bộ xử lý đã bị loại trừ khỏi Windows (ví dụ: thông qua cài đặt khởi động) và không thể phát hiện được bằng các phương tiện trên. Đoạn mã dưới đây cung cấp tổng số bộ xử lý logic (tôi chưa thể tìm ra cách phân biệt vật lý với bộ xử lý logic) tồn tại, bao gồm cả những bộ xử lý đã bị loại trừ khỏi 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,
}
deviceCount
là không dựa trên, nên số lượng cốt lõi sẽ là đầu ra như thế này:Console.WriteLine("Number of cores: {0}", deviceCount + 1);
Environment.ProcessorCount
Environment.ProcessorCount
mang lại 32.
Các truy vấn WMI chậm, vì vậy hãy cố gắng chỉ chọn các thành viên mong muốn thay vì sử dụng Chọn *.
Truy vấn sau đây mất 3,4 giây:
foreach (var item in new System.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
Trong khi cái này mất 0.122s:
foreach (var item in new System.Management.ManagementObjectSearcher("Select NumberOfCores from Win32_Processor").Get())
Môi trường.ProcessorCount sẽ cung cấp cho bạn số lượng lõi trên máy cục bộ.
Thật thú vị khi xem .NET làm thế nào để nói điều này trong nội bộ để nói rằng ít nhất ... Nó "đơn giản" như dưới đây:
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;
}
}
}
}
Cách dễ nhất = Environment.ProcessorCount
Ví dụ từ Môi trường.ProcessorCount Thuộc tính
using System;
class Sample
{
public static void Main()
{
Console.WriteLine("The number of processors " +
"on this computer is {0}.",
Environment.ProcessorCount);
}
}
Bạn cũng có thể tải nó với PInvoke trênKernel32.dll
Đoạn mã sau đến SystemInfo.cs
từ nguồn System.Web được đặt ở đây :
[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;
}
}
Một lựa chọn sẽ là đọc dữ liệu từ sổ đăng ký. Bài viết về MSDN về chủ đề: http://msdn.microsoft.com/en-us/l Library / microsoft.win32.registry.localmachine (v = vs.71 ) .aspx )
Các bộ xử lý, tôi tin rằng có thể được đặt ở đây, 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();
}
Tôi chắc chắn chắc chắn rằng mục đăng ký sẽ có mặt trên hầu hết các hệ thống.
Mặc dù tôi sẽ ném 0,02 đô la của tôi vào.
Chương trình sau đây in các lõi logic và vật lý của máy 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
*/
Tôi đang tìm kiếm điều tương tự nhưng tôi không muốn cài đặt bất kỳ nuget hoặc gói dịch vụ nào, vì vậy tôi đã tìm thấy giải pháp này, nó khá đơn giản và dễ dàng, sử dụng cuộc thảo luận này , tôi nghĩ rằng sẽ rất dễ dàng để chạy lệnh WMIC đó và nhận giá trị đó, đây là mã C #. Bạn chỉ cần sử dụng không gian tên System.Man Quản lý (và thêm vài không gian tên tiêu chuẩn cho quy trình, v.v.).
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();