Avez-vous besoin de savoir combien il y a de cœurs ou combien de processeurs logiques il y a? Pour exécuter simplement plusieurs threads, l'un ou l'autre est probablement suffisant, mais il existe des scénarios où la différence pourrait être importante.
Kevin Kibler
Existe-t-il une nouvelle façon de procéder?
MoonKnight
Réponses:
477
Vous pouvez obtenir plusieurs informations différentes sur les processeurs:
Nombre de processeurs physiques
Nombres de coeurs
Nombre de processeurs logiques.
Tout cela peut être différent; dans le cas d'une machine avec 2 processeurs hyper-threading dual-core, il y a 2 processeurs physiques, 4 cœurs et 8 processeurs logiques.
Le nombre de processeurs logiques est disponible via la classe Environment , mais les autres informations ne sont disponibles que via WMI (et vous devrez peut-être installer certains correctifs ou service packs pour les obtenir sur certains systèmes):
Assurez-vous d'ajouter une référence dans votre projet à System.Management.dll
Dans .NET Core, cela est disponible (pour Windows uniquement) en tant que package NuGet.
Processeurs physiques:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get()){Console.WriteLine("Number Of Physical Processors: {0} ", item["NumberOfProcessors"]);}
Noyaux:
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);
Processeurs logiques:
Console.WriteLine("Number Of Logical Processors: {0}",Environment.ProcessorCount);
OU
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get()){Console.WriteLine("Number Of Logical Processors: {0}", item["NumberOfLogicalProcessors"]);}
Processeurs exclus de Windows:
Vous pouvez également utiliser les appels API Windows dans setupapi.dll pour découvrir les processeurs qui ont été exclus de Windows (par exemple via les paramètres de démarrage) et qui ne sont pas détectables à l'aide des moyens ci-dessus. Le code ci-dessous donne le nombre total de processeurs logiques (je n'ai pas été en mesure de différencier les processeurs physiques des processeurs logiques) qui existent, y compris ceux qui ont été exclus de Windows:
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: C'est vrai, mais j'aimerais que ce soit dans un format plus agréable. La découvrabilité est assez faible lorsque vous devez créer des requêtes de chaînes brutes.
Kevin Kibler
5
WMI Code Creator aidera à la découverte de valeur et à la création de requêtes (il peut même générer des stubs dans c # / vb.net).
StingyJack
4
Il se trouve dans System.Management.dll. Avez-vous inclus une référence à cet assemblage dans votre projet?
Kevin Kibler
2
Problème mineur au cas par cas dans le code ci-dessus. Étant donné qu'il deviceCountest basé sur zéro, le nombre de cœurs doit être généré comme Console.WriteLine("Number of cores: {0}", deviceCount + 1);
suit
2
Ne causez-vous pas des problèmes en ne supprimant pas les objets de gestion et les chercheurs?
C'est tellement simple que je verse presque des larmes. Merci pour la réponse!
MrGreggles
70
Cela donne le nombre de processeurs logiques, pas le nombre de cœurs.
Kevin Kibler
8
@KevinKibler D'après la question, je soupçonne que l'OP ne comprend pas la différence, et si vous ne connaissez pas la différence, c'est probablement ce que vous voulez.
Glenn Maynard
1
Cela renvoie également le nombre incorrect sur de nombreux systèmes de base. J'exécute deux processeurs Dodeca avec hyper-threading, ce qui me donne un total de 48 processeurs logiques. Environment.ProcessorCountdonne 32.
Allen Clark Copeland Jr
1
@AlexanderMorou, oui, cela ne fournira pas de résultats précis sur certains serveurs multi-CPU. Il existe un correctif pour cela, mais je ne l'ai pas encore testé.
TheLegendaryCopyCoder
35
Les requêtes WMI sont lentes, essayez donc de sélectionner uniquement les membres souhaités au lieu d'utiliser Select *.
La requête suivante prend 3,4 secondes:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
Alors que celui-ci prend 0,122s:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select NumberOfCores from Win32_Processor").Get())
Sur quel système utilisez-vous cela? J'utilise plusieurs requêtes « Select * » et il ne prend pas n'importe où près de 3,4 secondes, testé sur des milliers d'ordinateurs que mon logiciel est déployé sur. Je fais un Select * car j'obtiens plusieurs propriétés de l'objet. Cependant, je le fais un peu différemment: créer une ObjectQuery sur Select *; obtenir le ManagementObjectCollection; puis pour chaque objet ManagementObject dans ManagementObjectCollection.
deegee
@deegee: vous avez raison, la requête elle-même ne prend pas beaucoup plus de temps avec "Select *", c'est juste que l'analyse syntaxique ci-dessous est lente si elle itère toutes les valeurs retournées au lieu de seulement NumberOfCores.
using System;classSample{publicstaticvoidMain(){Console.WriteLine("The number of processors "+"on this computer is {0}.",Environment.ProcessorCount);}}
Cela donnera le nombre de processeurs déjà disponibles dans Environment.ProcessorCount, existe-t-il une autre manière similaire d'obtenir le nombre de cœurs pour chaque processeur?
Armen
0
Le programme suivant imprime les cœurs logiques et physiques d'une 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);}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
*/
Cette question est balisée .NET; votre code n'est pas du code .NET.
Wai Ha Lee
-1
Je cherchais la même chose mais je ne veux installer aucun nuget ou servicepack, donc j'ai trouvé cette solution, elle est assez simple et directe, en utilisant cette discussion, j'ai pensé qu'il serait si facile d'exécuter cette commande WMIC et obtenez cette valeur, voici le code C #. Il vous suffit d'utiliser l'espace de noms System.Management (et de coupler plus d'espaces de noms standard pour le processus, etc.).
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();
Vous ne savez pas pourquoi vous compliquez une simple requête WMI. Démarrer la ligne de commande WMI en tant que processus externe et analyser sa sortie n'est vraiment pas nécessaire. .NET a un support intégré pour les requêtes WMI (System.Management.ManagementObjectSearcher), comme certaines des autres réponses ici déjà illustrées. De plus, je ne sais pas pourquoi vous pensez que des packages nuget ou des service packs seraient nécessaires lors de l'utilisation de la prise en charge WMI intégrée de .NET au lieu de wmic.exe ...
Réponses:
Vous pouvez obtenir plusieurs informations différentes sur les processeurs:
Tout cela peut être différent; dans le cas d'une machine avec 2 processeurs hyper-threading dual-core, il y a 2 processeurs physiques, 4 cœurs et 8 processeurs logiques.
Le nombre de processeurs logiques est disponible via la classe Environment , mais les autres informations ne sont disponibles que via WMI (et vous devrez peut-être installer certains correctifs ou service packs pour les obtenir sur certains systèmes):
Assurez-vous d'ajouter une référence dans votre projet à System.Management.dll Dans .NET Core, cela est disponible (pour Windows uniquement) en tant que package NuGet.
Processeurs physiques:
Noyaux:
Processeurs logiques:
OU
Processeurs exclus de Windows:
Vous pouvez également utiliser les appels API Windows dans setupapi.dll pour découvrir les processeurs qui ont été exclus de Windows (par exemple via les paramètres de démarrage) et qui ne sont pas détectables à l'aide des moyens ci-dessus. Le code ci-dessous donne le nombre total de processeurs logiques (je n'ai pas été en mesure de différencier les processeurs physiques des processeurs logiques) qui existent, y compris ceux qui ont été exclus de Windows:
la source
deviceCount
est basé sur zéro, le nombre de cœurs doit être généré commeConsole.WriteLine("Number of cores: {0}", deviceCount + 1);
[Documentation]
la source
Environment.ProcessorCount
donne 32.Les requêtes WMI sont lentes, essayez donc de sélectionner uniquement les membres souhaités au lieu d'utiliser Select *.
La requête suivante prend 3,4 secondes:
Alors que celui-ci prend 0,122s:
la source
Environment.ProcessorCount devrait vous donner le nombre de cœurs sur la machine locale.
la source
C'est plutôt intéressant de voir comment .NET obtient cela en interne pour le moins ... C'est aussi "simple" que ci-dessous:
la source
The the easyest way =
Environment.ProcessorCount
Exemple tiré de la propriété Environment.ProcessorCount
la source
À partir de la source .NET Framework
Vous pouvez également l'obtenir avec PInvoke sur
Kernel32.dll
Le code suivant provient plus ou moins de la
SystemInfo.cs
source System.Web située ici :la source
Une option serait de lire les données du registre. Article MSDN sur le sujet: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v=vs.71).aspx )
Je pense que les processeurs peuvent être situés ici, HKEY_LOCAL_MACHINE \ HARDWARE \ DESCRIPTION \ System \ CentralProcessor
Je suis raisonnablement sûr que l'entrée de registre sera présente sur la plupart des systèmes.
Bien que je jette mes 0,02 $.
la source
Le programme suivant imprime les cœurs logiques et physiques d'une machine Windows.
la source
Je cherchais la même chose mais je ne veux installer aucun nuget ou servicepack, donc j'ai trouvé cette solution, elle est assez simple et directe, en utilisant cette discussion, j'ai pensé qu'il serait si facile d'exécuter cette commande WMIC et obtenez cette valeur, voici le code C #. Il vous suffit d'utiliser l'espace de noms System.Management (et de coupler plus d'espaces de noms standard pour le processus, etc.).
la source