Você precisa saber quantos núcleos existem ou quantos processadores lógicos existem? Por apenas executar vários encadeamentos, provavelmente é suficiente, mas há cenários em que a diferença pode ser importante.
Kevin Kibler
Existe uma maneira mais nova de fazer isso?
MoonKnight
Respostas:
477
Existem várias informações diferentes relacionadas aos processadores que você pode obter:
Número de processadores físicos
Número de núcleos
Número de processadores lógicos.
Tudo isso pode ser diferente; no caso de uma máquina com 2 processadores habilitados para hyperthreading de núcleo duplo, existem 2 processadores físicos, 4 núcleos e 8 processadores lógicos.
O número de processadores lógicos está disponível na classe Environment , mas as outras informações estão disponíveis apenas no WMI (e talvez você precise instalar alguns hotfixes ou service packs para obtê-lo em alguns sistemas):
Certifique-se de adicionar uma referência no seu projeto ao System.Management.dll
No .NET Core, isso está disponível (apenas para Windows) como um pacote NuGet.
Processadores físicos:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem").Get()){Console.WriteLine("Number Of Physical Processors: {0} ", item["NumberOfProcessors"]);}
Cores:
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);
Processadores lógicos:
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"]);}
Processadores excluídos do Windows:
Você também pode usar as chamadas da API do Windows em setupapi.dll para descobrir os processadores que foram excluídos do Windows (por exemplo, através das configurações de inicialização) e não são detectáveis usando os meios acima. O código abaixo fornece o número total de processadores lógicos (não consegui descobrir como diferenciar processadores físicos de lógicos) existentes, incluindo aqueles que foram excluídos do 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: Verdade, mas eu gostaria que estivesse em um formato melhor. A capacidade de descoberta é muito baixa quando você precisa criar consultas de sequência bruta.
Kevin Kibler
5
O WMI Code Creator ajudará na descoberta de valor e na criação de consultas (ele pode até gerar stubs em c # / vb.net).
StingyJack
4
Está no System.Management.dll. Você incluiu uma referência a essa montagem em seu projeto?
Kevin Kibler
2
Problema secundário menor no código acima. Desde deviceCounté baseado em zero, a contagem de núcleos deve ser uma saída como esta:Console.WriteLine("Number of cores: {0}", deviceCount + 1);
Francis Litterio
2
Você não está causando problemas por não descartar os objetos de gerenciamento e os pesquisadores?
Isso é tão lindamente simples que estou quase derramando lágrimas. Obrigado pela resposta!
MrGreggles # 9/10/09
70
Isso fornece o número de processadores lógicos, não o número de núcleos.
Kevin Kibler
8
@KevinKibler Da pergunta, suspeito que o OP não entenda a diferença, e se você não souber a diferença, provavelmente é isso que você deseja.
Glenn Maynard
1
Isso também retorna a contagem incorreta em muitos sistemas principais. Estou executando dois processadores core dodeca com hyper-threading, o que me dá um total de 48 processadores lógicos. Environment.ProcessorCountretorna 32.
Allen Clark Copeland Jr
1
@AlexanderMorou, sim, isso não fornecerá resultados precisos em alguns servidores com várias CPUs. Existe uma correção para isso, mas ainda não a testamos.
TheLegendaryCopyCoder
35
As consultas WMI são lentas, portanto, tente selecionar apenas os membros desejados em vez de usar o Select *.
A consulta a seguir leva 3.4s:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select * from Win32_Processor").Get())
Enquanto este leva 0,122s:
foreach(var item innewSystem.Management.ManagementObjectSearcher("Select NumberOfCores from Win32_Processor").Get())
Em que sistema você está executando isso? Uso várias consultas "Select *" e não demora nem 3,4 segundos, testadas em milhares de computadores nos quais meu software está implantado. Eu faço um Select * porque estou obtendo várias propriedades do objeto. No entanto, faço um pouco diferente: crie uma ObjectQuery no Select *; obtenha o ManagementObjectCollection; em seguida, foreach ManagementObject no ManagementObjectCollection.
deegee
@deegee: você está certo, a consulta em si não leva muito mais tempo com "Select *", mas a análise int abaixo é lenta se iterar todos os valores retornados, em vez de apenas NumberOfCores.
using System;classSample{publicstaticvoidMain(){Console.WriteLine("The number of processors "+"on this computer is {0}.",Environment.ProcessorCount);}}
Isso fornecerá o número de processadores que já estão disponíveis no Environment.ProcessorCount, existe outra maneira semelhante de obter o número de núcleos para cada processador?
Armen
0
O programa a seguir imprime os núcleos lógicos e físicos de uma máquina 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
*/
Esta pergunta está etiquetada como .NET; seu código não é código .NET.
Wai Ha Lee
-1
Eu estava procurando a mesma coisa, mas não quero instalar nenhum nuget ou service pack, então encontrei esta solução, é bastante simples e direta, usando esta discussão, achei que seria tão fácil executar esse comando WMIC e obtenha esse valor, aqui está o código C #. Você só precisa usar o espaço para nome System.Management (e acoplar mais espaços para nome padrão para processo e assim por diante).
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();
Não sei por que você faz uma consulta WMI simples tão complicada. Iniciar a linha de comando WMI como um processo externo e analisar sua saída realmente não é necessário. O .NET possui suporte interno para consultas WMI (System.Management.ManagementObjectSearcher), como algumas das outras respostas aqui já ilustradas. Além disso, eu não sei por que você acha pacotes NuGet ou service packs seria necessária quando se utiliza do .NET suporte embutido WMI em vez de Wmic.exe ...
Respostas:
Existem várias informações diferentes relacionadas aos processadores que você pode obter:
Tudo isso pode ser diferente; no caso de uma máquina com 2 processadores habilitados para hyperthreading de núcleo duplo, existem 2 processadores físicos, 4 núcleos e 8 processadores lógicos.
O número de processadores lógicos está disponível na classe Environment , mas as outras informações estão disponíveis apenas no WMI (e talvez você precise instalar alguns hotfixes ou service packs para obtê-lo em alguns sistemas):
Certifique-se de adicionar uma referência no seu projeto ao System.Management.dll No .NET Core, isso está disponível (apenas para Windows) como um pacote NuGet.
Processadores físicos:
Cores:
Processadores lógicos:
OU
Processadores excluídos do Windows:
Você também pode usar as chamadas da API do Windows em setupapi.dll para descobrir os processadores que foram excluídos do Windows (por exemplo, através das configurações de inicialização) e não são detectáveis usando os meios acima. O código abaixo fornece o número total de processadores lógicos (não consegui descobrir como diferenciar processadores físicos de lógicos) existentes, incluindo aqueles que foram excluídos do Windows:
fonte
deviceCount
é baseado em zero, a contagem de núcleos deve ser uma saída como esta:Console.WriteLine("Number of cores: {0}", deviceCount + 1);
[Documentação]
fonte
Environment.ProcessorCount
retorna 32.As consultas WMI são lentas, portanto, tente selecionar apenas os membros desejados em vez de usar o Select *.
A consulta a seguir leva 3.4s:
Enquanto este leva 0,122s:
fonte
Environment.ProcessorCount deve fornecer o número de núcleos na máquina local.
fonte
É bastante interessante ver como o .NET faz isso internamente para dizer o mínimo ... É tão "simples" quanto abaixo:
fonte
A maneira mais fácil =
Environment.ProcessorCount
Exemplo de Propriedade Environment.ProcessorCount
fonte
Da fonte do .NET Framework
Você também pode obtê-lo com o PInvoke no
Kernel32.dll
O código a seguir vem mais ou menos da
SystemInfo.cs
fonte System.Web localizada aqui :fonte
Uma opção seria ler os dados do registro. Artigo do MSDN sobre o tópico: http://msdn.microsoft.com/en-us/library/microsoft.win32.registry.localmachine(v=vs.71).aspx )
Os processadores, acredito, podem estar localizados aqui, HKEY_LOCAL_MACHINE \ HARDWARE \ DESCRIPTION \ System \ CentralProcessor
Tenho certeza de que a entrada do registro estará presente na maioria dos sistemas.
Embora eu jogasse meus US $ 0,02.
fonte
O programa a seguir imprime os núcleos lógicos e físicos de uma máquina Windows.
fonte
Eu estava procurando a mesma coisa, mas não quero instalar nenhum nuget ou service pack, então encontrei esta solução, é bastante simples e direta, usando esta discussão, achei que seria tão fácil executar esse comando WMIC e obtenha esse valor, aqui está o código C #. Você só precisa usar o espaço para nome System.Management (e acoplar mais espaços para nome padrão para processo e assim por diante).
fonte