Müssen Sie wissen, wie viele Kerne es gibt oder wie viele logische Prozessoren es gibt? Für das Ausführen mehrerer Threads ist wahrscheinlich beides ausreichend, aber es gibt Szenarien, in denen der Unterschied wichtig sein kann.
Kevin Kibler
Gibt es einen neueren Weg, dies zu tun?
MoonKnight
Antworten:
477
Es gibt verschiedene Informationen zu Prozessoren, die Sie erhalten können:
Anzahl der physischen Prozessoren
Zahl der Kerne
Anzahl der logischen Prozessoren.
Diese können alle unterschiedlich sein; Bei einem Computer mit 2 Dual-Core-Hyper-Threading-fähigen Prozessoren gibt es 2 physische Prozessoren, 4 Kerne und 8 logische Prozessoren.
Die Anzahl der logischen Prozessoren ist über die Environment- Klasse 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 abzurufen):
Stellen Sie sicher, dass Sie in Ihrem Projekt einen Verweis auf System.Management.dll hinzufügen
In .NET Core ist dieser (nur für Windows) als NuGet-Paket verfügbar.
Physikalische Prozessoren:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get()){Console.WriteLine("Number Of Physical Processors: {0} ", item["NumberOfProcessors"]);}
Kerne:
int coreCount =0;foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get()){
coreCount +=int.Parse(item["NumberOfCores"].ToString());}Console.WriteLine("Number Of Cores: {0}", coreCount);
Logische Prozessoren:
Console.WriteLine("Number Of Logical Processors: {0}",Environment.ProcessorCount);
ODER
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get()){Console.WriteLine("Number Of Logical Processors: {0}", item["NumberOfLogicalProcessors"]);}
Von Windows ausgeschlossene Prozessoren:
Sie können auch Windows-API-Aufrufe in setupapi.dll verwenden , um Prozessoren zu ermitteln, die von Windows ausgeschlossen wurden (z. B. durch Starteinstellungen ) und mit den oben genannten Mitteln nicht erkannt werden können. Der folgende Code gibt die Gesamtzahl der vorhandenen logischen Prozessoren an (ich konnte nicht herausfinden, wie physische von logischen Prozessoren unterschieden werden können), einschließlich derjenigen, die von Windows ausgeschlossen wurden:
staticvoidMain(string[] args){int deviceCount =0;IntPtr deviceList =IntPtr.Zero;// GUID for processor classidGuid processorGuid =newGuid("{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 listfor(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 listif(!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)]privatestaticexternIntPtrSetupDiGetClassDevs(refGuidClassGuid,[MarshalAs(UnmanagedType.LPStr)]String enumerator,IntPtr hwndParent,Int32Flags);[DllImport("setupapi.dll",SetLastError=true)]privatestaticexternInt32SetupDiDestroyDeviceInfoList(IntPtrDeviceInfoSet);[DllImport("setupapi.dll",SetLastError=true)]privatestaticexternboolSetupDiEnumDeviceInfo(IntPtrDeviceInfoSet,Int32MemberIndex,ref SP_DEVINFO_DATA DeviceInterfaceData);[StructLayout(LayoutKind.Sequential)]privatestruct SP_DEVINFO_DATA
{publicint cbSize;publicGuidClassGuid;publicuintDevInst;publicIntPtrReserved;}privateenum DIGCF
{
DEFAULT =0x1,
PRESENT =0x2,
ALLCLASSES =0x4,
PROFILE =0x8,
DEVICEINTERFACE =0x10,}
@StingyJack: Stimmt, aber ich wünschte, es wäre in einem schöneren Format. Die Erkennbarkeit ist ziemlich gering, wenn Sie rohe Zeichenfolgenabfragen erstellen müssen.
Kevin Kibler
5
WMI Code Creator hilft bei der Werterkennung und Abfrageerstellung (es können sogar Stubs in c # / vb.net generiert werden).
StingyJack
4
Es ist in System.Management.dll. Haben Sie in Ihrem Projekt einen Verweis auf diese Baugruppe aufgenommen?
Kevin Kibler
2
Kleines Off-by-One-Problem im obigen Code. Da deviceCountes auf Null basiert, sollte die Kernanzahl wie folgt ausgegeben werden:Console.WriteLine("Number of cores: {0}", deviceCount + 1);
Francis Litterio
2
Verursachen Sie keine Probleme, indem Sie die Verwaltungsobjekte und Sucher nicht entsorgen?
Das ist so schön einfach, dass ich fast Tränen vergieße. Danke für die Antwort!
MrGreggles
70
Dies gibt die Anzahl der logischen Prozessoren an, nicht die Anzahl der Kerne.
Kevin Kibler
8
@ KevinKibler Aus der Frage, ich vermute, das OP versteht den Unterschied nicht, und wenn Sie den Unterschied nicht kennen, ist dies wahrscheinlich das, was Sie wollen.
Glenn Maynard
1
Dies gibt auch bei vielen Kernsystemen die falsche Anzahl zurück. Ich verwende zwei Dodeca-Core-Prozessoren mit Hyper-Threading, wodurch ich insgesamt 48 logische Prozessoren habe. Environment.ProcessorCountergibt 32.
Allen Clark Copeland Jr
1
@AlexanderMorou, ja, dies liefert auf einigen Multi-CPU-Servern keine genauen Ergebnisse. Es gibt eine Lösung dafür, aber noch nicht getestet.
TheLegendaryCopyCoder
35
WMI-Abfragen sind langsam. Versuchen Sie daher, nur die gewünschten Mitglieder auszuwählen, anstatt Select * zu verwenden.
Die folgende Abfrage dauert 3,4 Sekunden:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
Während dieser 0,122s dauert:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select NumberOfCores from Win32_Processor").Get())
Auf welchem System läuft das? Ich verwende mehrere "Select *" - Abfragen und es dauert nicht annähernd 3,4 Sekunden, getestet auf Tausenden von Computern, auf denen meine Software bereitgestellt wird. Ich mache eine Auswahl *, weil ich mehrere Eigenschaften vom Objekt erhalte. Ich mache es jedoch etwas anders: Erstellen Sie eine ObjectQuery auf dem Select *; Holen Sie sich die ManagementObjectCollection; dann für jedes ManagementObject in der ManagementObjectCollection.
Deegee
@deegee: Sie haben Recht, die Abfrage selbst dauert mit "Select *" nicht viel länger. Es ist nur so, dass das unten stehende int-Parsing langsam ist, wenn alle zurückgegebenen Werte anstelle von nur NumberOfCores wiederholt werden.
using System;classSample{publicstaticvoidMain(){Console.WriteLine("The number of processors "+"on this computer is {0}.",Environment.ProcessorCount);}}
Versuchte dies, aber es gibt die Anzahl der logischen Prozessoren zurück - das ist das gleiche Ergebnis wie beim Aufrufen von Environment.ProcessorCount.
Dies gibt die Anzahl der Prozessoren an, die bereits in Environment.ProcessorCount verfügbar sind. Gibt es eine andere ähnliche Möglichkeit, die Anzahl der Kerne für jeden Prozessor abzurufen?
Armen
0
Das folgende Programm druckt die logischen und physischen Kerne eines Windows-Computers.
#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);}classEnumLogicalProcessorInformation{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);}voidMoveNext(){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 */return0;}/*
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
*/
Diese Frage ist mit .NET gekennzeichnet. Ihr Code ist kein .NET-Code.
Wai Ha Lee
-1
Ich habe nach dem gleichen gesucht, aber ich möchte kein Nuget oder Servicepack installieren. Deshalb habe ich diese Lösung gefunden. Sie ist ziemlich einfach und unkompliziert. Mit dieser Diskussion dachte ich, es wäre so einfach, diesen WMIC-Befehl auszuführen und erhalten Sie diesen Wert, hier ist der C # -Code. Sie müssen nur den System.Management-Namespace verwenden (und weitere Standard-Namespaces für den Prozess usw. koppeln).
string fileName =Path.Combine(Environment.SystemDirectory,"wbem","wmic.exe");string arguments =@"cpu get NumberOfCores";Process process =newProcess{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();
Ich bin mir nicht sicher, warum Sie eine einfache WMI-Abfrage so kompliziert machen. Das Starten der WMI-Befehlszeile als externer Prozess und das Parsen der Ausgabe ist nicht unbedingt erforderlich. .NET bietet integrierte Unterstützung für WMI-Abfragen (System.Management.ManagementObjectSearcher), wie einige der anderen hier bereits veranschaulichten Antworten zeigen. Außerdem weiß ich nicht, warum Sie glauben, dass Nuget-Pakete oder Service Packs erforderlich sind, wenn Sie die integrierte WMI-Unterstützung von .NET anstelle von wmic.exe verwenden ...
Antworten:
Es gibt verschiedene Informationen zu Prozessoren, die Sie erhalten können:
Diese können alle unterschiedlich sein; Bei einem Computer mit 2 Dual-Core-Hyper-Threading-fähigen Prozessoren gibt es 2 physische Prozessoren, 4 Kerne und 8 logische Prozessoren.
Die Anzahl der logischen Prozessoren ist über die Environment- Klasse 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 abzurufen):
Stellen Sie sicher, dass Sie in Ihrem Projekt einen Verweis auf System.Management.dll hinzufügen In .NET Core ist dieser (nur für Windows) als NuGet-Paket verfügbar.
Physikalische Prozessoren:
Kerne:
Logische Prozessoren:
ODER
Von Windows ausgeschlossene Prozessoren:
Sie können auch Windows-API-Aufrufe in setupapi.dll verwenden , um Prozessoren zu ermitteln, die von Windows ausgeschlossen wurden (z. B. durch Starteinstellungen ) und mit den oben genannten Mitteln nicht erkannt werden können. Der folgende Code gibt die Gesamtzahl der vorhandenen logischen Prozessoren an (ich konnte nicht herausfinden, wie physische von logischen Prozessoren unterschieden werden können), einschließlich derjenigen, die von Windows ausgeschlossen wurden:
quelle
deviceCount
es auf Null basiert, sollte die Kernanzahl wie folgt ausgegeben werden:Console.WriteLine("Number of cores: {0}", deviceCount + 1);
[Dokumentation]
quelle
Environment.ProcessorCount
ergibt 32.WMI-Abfragen sind langsam. Versuchen Sie daher, nur die gewünschten Mitglieder auszuwählen, anstatt Select * zu verwenden.
Die folgende Abfrage dauert 3,4 Sekunden:
Während dieser 0,122s dauert:
quelle
Environment.ProcessorCount sollte die Anzahl der Kerne auf dem lokalen Computer angeben.
quelle
Es ist ziemlich interessant zu sehen, wie .NET dies intern schafft, um es gelinde auszudrücken ... Es ist so "einfach" wie unten:
quelle
Der einfachste Weg =
Environment.ProcessorCount
Beispiel aus der Environment.ProcessorCount-Eigenschaft
quelle
Aus der .NET Framework-Quelle
Sie können es auch mit PInvoke erhalten auf
Kernel32.dll
Der folgende Code stammt mehr oder weniger aus
SystemInfo.cs
der System.Web-Quelle, die sich hier befindet :quelle
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 )
Ich glaube, die Prozessoren befinden sich hier, HKEY_LOCAL_MACHINE \ HARDWARE \ DESCRIPTION \ System \ CentralProcessor
Ich bin mir ziemlich sicher, dass der Registrierungseintrag auf den meisten Systemen vorhanden sein wird.
Obwohl ich meine $ 0,02 in werfen würde.
quelle
Das folgende Programm druckt die logischen und physischen Kerne eines Windows-Computers.
quelle
Ich habe nach dem gleichen gesucht, aber ich möchte kein Nuget oder Servicepack installieren. Deshalb habe ich diese Lösung gefunden. Sie ist ziemlich einfach und unkompliziert. Mit dieser Diskussion dachte ich, es wäre so einfach, diesen WMIC-Befehl auszuführen und erhalten Sie diesen Wert, hier ist der C # -Code. Sie müssen nur den System.Management-Namespace verwenden (und weitere Standard-Namespaces für den Prozess usw. koppeln).
quelle