Encontre programaticamente o número de núcleos em uma máquina

Existe uma maneira de determinar quantos núcleos uma máquina tem de C / C ++ de maneira independente de plataforma? Se não existe tal coisa, que tal determinar por plataforma (Windows / * nix / Mac)?

Esta funcionalidade faz parte do padrão C ++ 11.

 #include  unsigned int nthreads = std::thread::hardware_concurrency(); 

Para compiladores antigos, você pode usar a biblioteca Boost.Thread .

 #include  unsigned int nthreads = boost::thread::hardware_concurrency(); 

Em ambos os casos, hardware_concurrency() retorna o número de threads que o hardware é capaz de executar simultaneamente com base no número de núcleos de CPU e unidades de hyper-threading.

O OpenMP é suportado em muitas plataformas (incluindo o Visual Studio 2005) e oferece

 int omp_get_num_procs(); 

function que retorna o número de processadores / núcleos disponíveis no momento da chamada.

Se você tiver access a linguagem assembly, poderá usar a instrução CPUID para obter todos os tipos de informações sobre a CPU. É portátil entre sistemas operacionais, mas você precisará 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 AMD.

(Quase) function independente de plataforma no código c

 #ifdef _WIN32 #include  #elif MACOS #include  #include  #else #include  #endif int getNumCores() { #ifdef WIN32 SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); return sysinfo.dwNumberOfProcessors; #elif MACOS int nm[2]; size_t len = 4; uint32_t count; nm[0] = CTL_HW; nm[1] = HW_AVAILCPU; sysctl(nm, 2, &count, &len, NULL, 0); if(count < 1) { nm[1] = HW_NCPU; sysctl(nm, 2, &count, &len, NULL, 0); if(count < 1) { count = 1; } } return count; #else return sysconf(_SC_NPROCESSORS_ONLN); #endif } 

No Linux, você pode ler o arquivo / proc / cpuinfo e contar os núcleos.

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 CPUs multi-threaded, 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ê entra em sistemas suportados por hypervisor onde o hardware pode ter dezenas de CPUs, mas seu sistema operacional específico só vê alguns.

O melhor que você pode esperar é informar o número de unidades de processamento lógico que você tem em sua partição do SO local. Esqueça de ver a máquina verdadeira, a menos que você seja um hipervisor. A única exceção a essa regra hoje é em x86, mas o fim das máquinas não virtuais está chegando rápido …

Mais uma receita do Windows: use a variável de ambiente NUMBER_OF_PROCESSORS :

 printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS"))); 

Você provavelmente não será capaz de obtê-lo de maneira independente da plataforma. Windows você recebe o número de processadores.

Informações do sistema Win32

Mais sobre o OS X: o sysconf(_SC_NPROCESSORS_ONLN) está disponível apenas em versões> = 10.5, não 10.4.

Uma alternativa é o código BSD HW_AVAILCPU/sysctl() que está disponível nas versões> = 10.2.

Windows Server 2003 e posterior permite aproveitar a function GetLogicalProcessorInformation

http://msdn.microsoft.com/pt-br/library/ms683194.aspx

Não relacionado ao C ++, mas no Linux eu geralmente faço:

 grep processor /proc/cpuinfo | wc -l 

Útil para linguagens de script como bash / perl / python / ruby.

O hwloc (http://www.open-mpi.org/projects/hwloc/) vale a pena ser visto. Embora exija outra integração de biblioteca em seu código, mas ele pode fornecer todas as informações sobre seu processador (número de núcleos, a topologia, etc.)

No Linux, pode não ser seguro usar _SC_NPROCESSORS_ONLN já que não faz parte do padrão POSIX e do manual do sysconf . Portanto, há uma possibilidade de que _SC_NPROCESSORS_ONLN não esteja 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/stat ou /proc/cpuinfo e contá-los:

 #include #include 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); return 0; } 

Usando o /proc/cpuinfo :

 #include #include 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); return 0; } 

A mesma abordagem no shell usando grep:

 grep -c ^processor /proc/cpuinfo 

Ou

 grep -c ^cpu /proc/stat # subtract 1 from the result 

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)

 size_t NumberOfPhysicalCores() noexcept { DWORD length = 0; const BOOL result_first = GetLogicalProcessorInformationEx(RelationProcessorCore, nullptr, &length); Assert(result_first == FALSE); Assert(GetLastError() == ERROR_INSUFFICIENT_BUFFER); std::unique_ptr< uint8_t[] > buffer(new uint8_t[length]); const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX info = reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get()); const BOOL result_second = GetLogicalProcessorInformationEx(RelationProcessorCore, info, &length); Assert(result_second == TRUE); size_t nb_physical_colors = 0; size_t offset = 0; do { const PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX current_info = reinterpret_cast< PSYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX >(buffer.get() + offset); offset += current_info->Size; ++nb_physical_colors; } while (offset < length); return nb_physical_cores; } 

Observe que a implementação de NumberOfPhysicalCores é IMHO longe de trivial (ou seja, "use GetLogicalProcessorInformation ou GetLogicalProcessorInformationEx "). Em vez disso, é bastante sutil se alguém ler a documentação (explicitamente presente para GetLogicalProcessorInformation e implicitamente presente para GetLogicalProcessorInformationEx ) no MSDN.

O número de processadores lógicos. (Usando GetSystemInfo )

 size_t NumberOfSystemCores() noexcept { SYSTEM_INFO system_info; ZeroMemory(&system_info, sizeof(system_info)); GetSystemInfo(&system_info); return static_cast< size_t >(system_info.dwNumberOfProcessors); } 

Note que ambos os methods podem ser facilmente convertidos para C / C ++ 98 / C ++ 03.

Alternativa 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 os documentos. Para versões anteriores do OS X, use a function Carbono MPProcessors ().

Se você é um programador de cacau, não se assuste com o fato de que isso é carbono. Você só precisa adicionar o framework Carbon ao seu projeto Xcode e os MPProcessors () estarão disponíveis.

No linux a melhor forma programática, tanto quanto eu sei, é usar

 sysconf(_SC_NPROCESSORS_CONF) 

ou

 sysconf(_SC_NPROCESSORS_ONLN) 

Estes não são padrão, mas estão na minha página man do Linux.

Para Win32:

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, ele funciona localmente, mas falha quando o mesmo código é executado nos servidores. Eu acredito que é um problema de namespace, relacionado aos “nomes” cujos valores você está lendo.

No Linux, você pode fazer o checkout do dmesg e filtrar as linhas onde o ACPI inicializa as CPUs, algo como:

dmesg | grep 'ACPI: Processor dmesg | grep 'ACPI: Processor

Outra possibilidade é usar o dmidecode para filtrar as informações do processador.