Encontre programaticamente o número de núcleos em uma máquina
464
Existe uma maneira de determinar quantos núcleos uma máquina possui do C / C ++ de maneira independente da plataforma? Se isso não existe, que tal determiná-lo por plataforma (Windows / * nix / Mac)?
Se você quiser usá-lo, descubra quantos threads iniciar, use NUMBER_OF_PROCESSORS como medida principal. Deixo como exercício para você porque isso é muito melhor (se as pessoas o usassem mais) do que usar núcleos de hardware. A quantidade de núcleos pertencentes ao seu programa é uma questão ambiental!
Lothar
Observe que std::thread::hardware_concurrencyretorna o número de núcleos físicos da CPU, mas nprocno Linux mostra apenas o número de núcleos da CPU nos quais o processo atual pode ser executado, que pode ser controlado sched_setaffinity. Eu não encontrei uma maneira de conseguir que, em vez de C ++ padrão :, ver, por exemplo, em Python: stackoverflow.com/questions/1006289/...
Ciro Santilli郝海东冠状病六四事件法轮功
Respostas:
706
C ++ 11
#include<thread>//may return 0 when not able to detectconstauto processor_count = std::thread::hardware_concurrency();
No C ++ anterior ao C ++ 11, não há maneira portátil. Em vez disso, você precisará usar um ou mais dos seguintes métodos (protegidos pelas #ifdeflinhas apropriadas ):
Linux, Solaris, AIX e Mac OS X> = 10.4 (ou seja, Tiger em diante)
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
FreeBSD, MacOS X, NetBSD, OpenBSD, etc.
int mib[4];int numCPU;
std::size_t len =sizeof(numCPU);/* set the mib for hw.ncpu */
mib[0]= CTL_HW;
mib[1]= HW_AVAILCPU;// alternatively, try HW_NCPU;/* get the number of CPUs from the system */
sysctl(mib,2,&numCPU,&len, NULL,0);if(numCPU <1){
mib[1]= HW_NCPU;
sysctl(mib,2,&numCPU,&len, NULL,0);if(numCPU <1)
numCPU =1;}
HPUX
int numCPU = mpctl(MPC_GETNUMSPUS, NULL, NULL);
IRIX
int numCPU = sysconf(_SC_NPROC_ONLN);
Objective-C (Mac OS X> = 10.5 ou iOS)
NSUInteger a =[[NSProcessInfo processInfo] processorCount];NSUInteger b =[[NSProcessInfo processInfo] activeProcessorCount];
@ MCANDRE: isso é deixado como um exercício para o leitor. Se eu estivesse implementando, provavelmente usaria a abordagem de política de modelo, onde a política foi definida nas diretivas de pré-processador. Ou ... você pode usar o boost thread :: hardware_concurrency ().
paxos1977
3
como um ponto de esclarecimento, a solução Win32 retorna o número total de núcleos (o que foi solicitado) e não o número total de CPUs físicas.
Eric
1
A maneira Linux / Solaris / AIX também funciona no FreeBSD e tem desde pelo menos 2006. Além disso, isso retornará as CPUs on-line, se um sistema for capaz de desligar algumas, elas podem não ser contadas. Chamar sysconf com "_SC_NPROCESSORS_CONF" retornará o total de CPUs configuradas.
Chris S
3
Algumas coisas para estar ciente. HW_NCPUfoi descontinuado no OS X. No Windows, GetSystemInfoapenas é útil se o seu sistema tiver 32 processadores lógicos ou menos, use GetLogicalProcessorInformationpara sistemas que tenham mais de 32 processadores lógicos.
1
@Trejkaz, a documentação diz claramente "lógico" - que está sempre contando núcleos HT, a palavra "físico" sempre se refere aos núcleos relatados pelo BIOS / UEFI, pois os núcleos também podem ser emulados / virtualizados. Você pode diferenciar núcleos HT / não HT com funções como GetLogicalProcessorInformation , por exemplo. Nota: HT! = Emulação ou virtualização, isso é uma grande diferença, HT é uma otimização de hardware, por assim dizer
Nos dois casos, hardware_concurrency()retorna o número de threads que o hardware é capaz de executar simultaneamente, com base no número de núcleos da CPU e unidades de hyperthreading.
Destacado ... ia usar o código de exemplo acima e algumas macros do pré-processador para expor uma única função, mas o trabalho duro foi feito para mim.
jkp
Para o win32, é uma chamada para GetSystemInfo. (A partir da versão 1.41.0 do boost) Isso captura todas as informações para determinar quantos threads de trabalho seriam eficazes? É necessário considerar o número de núcleos e o hyperthreading? thread não assinado :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& info); retornar info.dwNumberOfProcessors; }
Jive Dadson,
De acordo com o MSDN, GetSystemInfo () retorna o número de "processadores físicos" em dwNumberOfProcessors, mas não define o que significa isso. A documentação do Boost parece alegar que inclui unidades de hyperthreading.
porque é uma resposta errada. Em gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () retornará apenas um número menor que o número de CPUs do sistema on-line, se GOMP_CPU_AFFINITY env var for usado, ou se o processo de chamada e / ou o thread tiver Afinidade de CPU limitada a um subconjunto de CPUs ". Portanto, se você ligar anteriormente, por exemplo, sched_setaffinityisso não funcionará.
angainor
7
Esta função retorna o número de CPUs disponíveis para o processo de chamada. Não é o caso de uso mais comum, afinal? Fora do tamanho de algumas finalidades inúteis para relatórios, o número real de núcleos de hardware da CPU não é relevante para você se você não puder tirar proveito deles em seu código.
macbirdie
@EvanTeran Além do fato de ter sido o objetivo da pergunta, é claro que pode ser útil. Por exemplo, com a finalidade de definir a afinidade do encadeamento. Digamos, quero executar 4 threads vinculados aos quatro últimos núcleos da CPU em minha máquina, em vez dos quatro primeiros núcleos. Além disso, existem outras maneiras de paralelizar o código, exceto o OpenMP. Eu posso querer criar pthreads eu mesmo. Eles certamente estão disponíveis e não são restritos pelas variáveis de ambiente do OpenMP.
angainor
2
Isso retorna o número de CPUs lógicas, não de núcleos (CPUs físicas) como tal.
Michael Konečný
37
Se você tiver acesso à linguagem assembly, poderá usar a instrução CPUID para obter todos os tipos de informações sobre a CPU. É portátil entre sistemas operacionais, embora você precise usar informações específicas do fabricante para determinar como encontrar o número de núcleos. Aqui está um documento que descreve como fazê-lo em chips Intel , e a página 11 deste descreve a especificação da AMD.
Pode ter sido recusado porque a pergunta está marcada como C ++ e esta resposta não se aplica a sistemas executando C ++ em arquiteturas não-x86 (ARM, PPC, etc.). Não estou dizendo que é uma boa razão para votar uma resposta, apenas uma possibilidade.
Ferruccio
3
Uma armadilha desse método é se você estiver usando o CPUID para detectar o HyperThreading nos processadores Intel. Eu me deparei com esse problema no meu laptop: enquanto a CPU que eu coloco na máquina suporta HyperThreading (e, é claro, relata isso via CPUID), o BIOS não. Portanto, você não deve tentar utilizar o recurso HT simplesmente a partir de uma leitura de CPUID. Como você não pode consultar o BIOS sobre suporte a HT (de jeito nenhum que eu tenha visto), o sistema operacional deve ser consultado para obter a contagem lógica do processador.
Chuck R
32
Função (quase) independente de plataforma no código c
Só que que também conta HyperThreaded ou outras soluções de SMT como mais núcleos ...
jakobengblom2
13
@Arafangion: hyperthreading não é uma execução paralela verdadeira, é uma tecnologia para reduzir a sobrecarga da alternância de contexto. Uma CPU com hyperthread pode executar apenas um encadeamento por vez, mas pode armazenar o estado arquitetural (valores de registro etc.) de dois encadeamentos ao mesmo tempo. As características de desempenho são muito diferentes de ter dois núcleos.
Wim Coenen
7
@ Wim: Isso não está completamente correto. As CPUs com hyperthreading geralmente têm várias ALUs e podem enviar várias instruções por ciclo. Se, devido a dependências e paralisações de dados, nem todas as ALUs puderem ser mantidas ocupadas por um encadeamento, essas ALUs serão usadas para execução simultânea do segundo encadeamento de hardware.
precisa
11
Observe que "número de núcleos" pode não ser um número particularmente útil; talvez seja necessário qualificá-lo um pouco mais. Como você deseja contar com CPUs multithread, como Intel HT, IBM Power5 e Power6, e mais famoso, Niagara / UltraSparc T1 e T2 da Sun? Ou ainda mais interessante, o MIPS 1004k com seus dois níveis de encadeamento de hardware (supervisor E nível de usuário) ... Sem mencionar o que acontece quando você se muda para sistemas suportados por hipervisor, nos quais o hardware pode ter dezenas de CPUs, mas seu SO específico só vê alguns.
O melhor que você pode esperar é informar o número de unidades de processamento lógico que você possui na partição do sistema operacional local. Esqueça de ver a máquina verdadeira, a menos que você seja um hipervisor. Hoje, a única exceção a essa regra está no terreno x86, mas o fim das máquinas não virtuais está chegando rapidamente ...
Observe que a implementação do NumberOfPhysicalCoresIMHO está longe de ser trivial (ou seja, "use GetLogicalProcessorInformationor GetLogicalProcessorInformationEx"). Em vez disso, é bastante sutil se alguém ler a documentação (explicitamente presente para GetLogicalProcessorInformatione implicitamente presente para GetLogicalProcessorInformationEx) no MSDN.
O número de processadores lógicos. (Usando GetSystemInfo )
Obrigado! Eu estava procurando isso por GetLogicalProcessorInformationnão trabalhar com vários tamanhos de buffer que usei. Mais do que satisfeito! ^^
KeyWeeUsr
@KeyWeeUsr Obrigado A programação do Windows está um pouco longe de trivial e lógica. Enquanto isso, uso uma versão C ++ 17 um pouco mais atualizada, que também é mais correta de acordo com o analisador estático PVS-Studio em relação a alguns size_tmodelos. (Embora, msvc ++ não reclamar na W4.)
Matthias
5
Mais informações sobre o OS X: sysconf(_SC_NPROCESSORS_ONLN)está disponível apenas nas versões> = 10.5, não 10.4.
Uma alternativa é o HW_AVAILCPU/sysctl()código BSD que está disponível nas versões> = 10.2.
Para python:import multiprocessingprint multiprocessing.cpu_count()
initzero
3
Já faz muito tempo, mas greptem -csinalizador para contar entradas!
Lapshin Dmitry
3
vale a pena ver o hwloc (http://www.open-mpi.org/projects/hwloc/). Embora exija outra integração de biblioteca em seu código, ele pode fornecer todas as informações sobre seu processador (número de núcleos, topologia etc.)
No Linux, pode não ser seguro usá- _SC_NPROCESSORS_ONLNlo, pois não faz parte do padrão POSIX e o manual sysconf afirma o mesmo. Portanto, há uma possibilidade que _SC_NPROCESSORS_ONLNpode não estar presente:
These values also exist, but may not be standard.[...]- _SC_NPROCESSORS_CONF
The number of processors configured.- _SC_NPROCESSORS_ONLN
The number of processors currently online (available).
Uma abordagem simples seria ler /proc/statou /proc/cpuinfocontá-los:
#include<unistd.h>#include<stdio.h>int main(void){char str[256];int procCount =-1;// to offset for the first entry
FILE *fp;if((fp = fopen("/proc/stat","r"))){while(fgets(str,sizeof str, fp))if(!memcmp(str,"cpu",3)) procCount++;}if( procCount ==-1){
printf("Unable to get proc count. Defaulting to 2");
procCount=2;}
printf("Proc Count:%d\n", procCount);return0;}
Usando /proc/cpuinfo:
#include<unistd.h>#include<stdio.h>int main(void){char str[256];int procCount =0;
FILE *fp;if((fp = fopen("/proc/cpuinfo","r"))){while(fgets(str,sizeof str, fp))if(!memcmp(str,"processor",9)) procCount++;}if(!procCount ){
printf("Unable to get proc count. Defaulting to 2");
procCount=2;}
printf("Proc Count:%d\n", procCount);return0;}
A mesma abordagem no shell usando grep:
grep -c ^processor /proc/cpuinfo
Ou
grep -c ^cpu /proc/stat # subtract 1 from the result
Alternativa para OS X: a solução descrita anteriormente com base em [[NSProcessInfo processInfo] processorCount] está disponível apenas no OS X 10.5.0, de acordo com a documentação. Para versões anteriores do OS X, use a função Carbon MPProcessors ().
Se você é um programador de cacau, não se assuste com o fato de ser carbono. Você só precisa adicionar a estrutura Carbon ao seu projeto Xcode e o MPProcessors () estará disponível.
Enquanto GetSystemInfo () obtém o número de processadores lógicos , use
GetLogicalProcessorInformationEx ()
para obter o número de processadores físicos .
você também pode usar o WMI no .net, mas depende do serviço wmi em execução etc. Às vezes, funciona localmente, mas falha quando o mesmo código é executado nos servidores. Acredito que seja um problema de espaço para nome, relacionado aos "nomes" cujos valores você está lendo.
std::thread::hardware_concurrency
retorna o número de núcleos físicos da CPU, masnproc
no Linux mostra apenas o número de núcleos da CPU nos quais o processo atual pode ser executado, que pode ser controladosched_setaffinity
. Eu não encontrei uma maneira de conseguir que, em vez de C ++ padrão :, ver, por exemplo, em Python: stackoverflow.com/questions/1006289/...Respostas:
C ++ 11
Referência: std :: thread :: hardware_concurrency
No C ++ anterior ao C ++ 11, não há maneira portátil. Em vez disso, você precisará usar um ou mais dos seguintes métodos (protegidos pelas
#ifdef
linhas apropriadas ):Win32
Linux, Solaris, AIX e Mac OS X> = 10.4 (ou seja, Tiger em diante)
FreeBSD, MacOS X, NetBSD, OpenBSD, etc.
HPUX
IRIX
Objective-C (Mac OS X> = 10.5 ou iOS)
fonte
HW_NCPU
foi descontinuado no OS X. No Windows,GetSystemInfo
apenas é útil se o seu sistema tiver 32 processadores lógicos ou menos, useGetLogicalProcessorInformation
para sistemas que tenham mais de 32 processadores lógicos.Essa funcionalidade faz parte do padrão C ++ 11.
Para compiladores mais antigos, você pode usar a biblioteca Boost.Thread .
Nos dois casos,
hardware_concurrency()
retorna o número de threads que o hardware é capaz de executar simultaneamente, com base no número de núcleos da CPU e unidades de hyperthreading.fonte
O OpenMP é suportado em muitas plataformas (incluindo o Visual Studio 2005) e oferece um
função que retorna o número de processadores / núcleos disponíveis no momento da chamada.
fonte
sched_setaffinity
isso não funcionará.Se você tiver acesso à linguagem assembly, poderá usar a instrução CPUID para obter todos os tipos de informações sobre a CPU. É portátil entre sistemas operacionais, embora você precise usar informações específicas do fabricante para determinar como encontrar o número de núcleos. Aqui está um documento que descreve como fazê-lo em chips Intel , e a página 11 deste descreve a especificação da AMD.
fonte
Função (quase) independente de plataforma no código c
fonte
HW_NCPU
foi descontinuado na origem doNo Linux, você pode ler o arquivo / proc / cpuinfo e contar os núcleos.
fonte
Observe que "número de núcleos" pode não ser um número particularmente útil; talvez seja necessário qualificá-lo um pouco mais. Como você deseja contar com CPUs multithread, como Intel HT, IBM Power5 e Power6, e mais famoso, Niagara / UltraSparc T1 e T2 da Sun? Ou ainda mais interessante, o MIPS 1004k com seus dois níveis de encadeamento de hardware (supervisor E nível de usuário) ... Sem mencionar o que acontece quando você se muda para sistemas suportados por hipervisor, nos quais o hardware pode ter dezenas de CPUs, mas seu SO específico só vê alguns.
O melhor que você pode esperar é informar o número de unidades de processamento lógico que você possui na partição do sistema operacional local. Esqueça de ver a máquina verdadeira, a menos que você seja um hipervisor. Hoje, a única exceção a essa regra está no terreno x86, mas o fim das máquinas não virtuais está chegando rapidamente ...
fonte
Mais uma receita do Windows: use a variável de ambiente de todo o sistema
NUMBER_OF_PROCESSORS
:fonte
Você provavelmente não conseguirá obtê-lo de maneira independente da plataforma. Windows você obtém número de processadores.
Informações do sistema Win32
fonte
Windows (x64 e Win32) e C ++ 11
O número de grupos de processadores lógicos que compartilham um único núcleo de processador. (Usando GetLogicalProcessorInformationEx , consulte GetLogicalProcessorInformation também)
Observe que a implementação do
NumberOfPhysicalCores
IMHO está longe de ser trivial (ou seja, "useGetLogicalProcessorInformation
orGetLogicalProcessorInformationEx
"). Em vez disso, é bastante sutil se alguém ler a documentação (explicitamente presente paraGetLogicalProcessorInformation
e implicitamente presente paraGetLogicalProcessorInformationEx
) no MSDN.O número de processadores lógicos. (Usando GetSystemInfo )
Observe que ambos os métodos podem ser facilmente convertidos em C / C ++ 98 / C ++ 03.
fonte
GetLogicalProcessorInformation
não trabalhar com vários tamanhos de buffer que usei. Mais do que satisfeito! ^^size_t
modelos. (Embora, msvc ++ não reclamar na W4.)Mais informações sobre o OS X:
sysconf(_SC_NPROCESSORS_ONLN)
está disponível apenas nas versões> = 10.5, não 10.4.Uma alternativa é o
HW_AVAILCPU/sysctl()
código BSD que está disponível nas versões> = 10.2.fonte
O Windows Server 2003 e versões posteriores permitem que você aproveite a função GetLogicalProcessorInformation
http://msdn.microsoft.com/en-us/library/ms683194.aspx
fonte
Não relacionado ao C ++, mas no Linux eu costumo fazer:
Útil para linguagens de script como bash / perl / python / ruby.
fonte
import multiprocessing
print multiprocessing.cpu_count()
grep
tem-c
sinalizador para contar entradas!vale a pena ver o hwloc (http://www.open-mpi.org/projects/hwloc/). Embora exija outra integração de biblioteca em seu código, ele pode fornecer todas as informações sobre seu processador (número de núcleos, topologia etc.)
fonte
No linux, a melhor maneira programática, até onde eu sei, é usar
ou
Estes não são padrão, mas estão na minha página de manual do Linux.
fonte
No Linux, pode não ser seguro usá-
_SC_NPROCESSORS_ONLN
lo, pois não faz parte do padrão POSIX e o manual sysconf afirma o mesmo. Portanto, há uma possibilidade que_SC_NPROCESSORS_ONLN
pode não estar presente:Uma abordagem simples seria ler
/proc/stat
ou/proc/cpuinfo
contá-los:Usando
/proc/cpuinfo
:A mesma abordagem no shell usando grep:
Ou
fonte
Alternativa para OS X: a solução descrita anteriormente com base em [[NSProcessInfo processInfo] processorCount] está disponível apenas no OS X 10.5.0, de acordo com a documentação. Para versões anteriores do OS X, use a função Carbon MPProcessors ().
Se você é um programador de cacau, não se assuste com o fato de ser carbono. Você só precisa adicionar a estrutura Carbon ao seu projeto Xcode e o MPProcessors () estará disponível.
fonte
Para Win32:
Enquanto GetSystemInfo () obtém o número de processadores lógicos , use GetLogicalProcessorInformationEx () para obter o número de processadores físicos .
fonte
você também pode usar o WMI no .net, mas depende do serviço wmi em execução etc. Às vezes, funciona localmente, mas falha quando o mesmo código é executado nos servidores. Acredito que seja um problema de espaço para nome, relacionado aos "nomes" cujos valores você está lendo.
fonte
No Linux, você pode verificar o dmesg e filtrar as linhas onde a ACPI inicializa as CPUs, algo como:
dmesg | grep 'ACPI: Processor
"Outra possibilidade é usar o dmidecode para filtrar as informações do processador.
fonte