Existe-t-il un moyen de déterminer le nombre de cœurs d’une machine à partir de C/C++ d’une manière indépendante de la plate-forme? Si rien de tel n’existe, qu’en est-il de la déterminer par plate-forme (Windows/* nix/Mac)?
//may return 0 when not able to detect
unsigned concurentThreadsSupported = std::thread::hardware_concurrency();
Référence: std :: thread :: hardware_concurrency
En C++ avant C++ 11, il n'y a pas de moyen portable. Au lieu de cela, vous devrez utiliser une ou plusieurs des méthodes suivantes (protégées par les lignes #ifdef
appropriées):
SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo);
int numCPU = sysinfo.dwNumberOfProcessors;
int numCPU = sysconf(_SC_NPROCESSORS_ONLN);
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;
}
int numCPU = mpctl(MPC_GETNUMSPUS, NULL, NULL);
int numCPU = sysconf(_SC_NPROC_ONLN);
NSUInteger a = [[NSProcessInfo processInfo] processorCount];
NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount];
Cette fonctionnalité fait partie de la norme C++ 11.
#include <thread>
unsigned int nthreads = std::thread::hardware_concurrency();
Pour les anciens compilateurs, vous pouvez utiliser la bibliothèque Boost.Thread .
#include <boost/thread.hpp>
unsigned int nthreads = boost::thread::hardware_concurrency();
Dans les deux cas, hardware_concurrency()
renvoie le nombre de threads que le matériel est capable d'exécuter simultanément en fonction du nombre de cœurs de processeur et d'unités d'hyper-threading.
OpenMP est pris en charge sur de nombreuses plates-formes (y compris Visual Studio 2005) et offre une
int omp_get_num_procs();
fonction qui renvoie le nombre de processeurs/cœurs disponibles au moment de l'appel.
Si vous avez accès au langage d'assemblage, vous pouvez utiliser l'instruction CPUID pour obtenir toutes sortes d'informations sur la CPU. Il est portable entre les systèmes d'exploitation. Vous devrez toutefois utiliser les informations spécifiques du fabricant pour déterminer comment trouver le nombre de cœurs. Voici n document décrivant la procédure à suivre pour les puces Intel , et la page 11 de celle-ci décrit la spécification AMD.
Fonction (presque) indépendante de la plate-forme en c-code
#ifdef _WIN32
#include <windows.h>
#Elif MACOS
#include <sys/param.h>
#include <sys/sysctl.h>
#else
#include <unistd.h>
#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
}
Sous Linux, vous pouvez lire le fichier/proc/cpuinfo et compter les cœurs.
Notez que "nombre de cœurs" peut ne pas être un nombre particulièrement utile, vous devrez peut-être le qualifier un peu plus. Comment voulez-vous compter les processeurs multi-threads tels que Intel HT, IBM Power5 et Power6 et, plus célèbre, les serveurs Niagara/UltraSparc T1 et T2 de Sun? Ou encore plus intéressant, le MIPS 1004k avec ses deux niveaux de threading matériel (superviseur ET niveau utilisateur) ... Sans parler de ce qui se passe lorsque vous passez dans des systèmes pris en charge par l'hyperviseur, où le matériel peut comporter des dizaines de CPU mais votre système d'exploitation particulier n'en voit que quelques-uns.
Le mieux que vous puissiez espérer est d'indiquer le nombre d'unités de traitement logique que vous avez dans votre partition OS locale. Oubliez de voir la vraie machine sauf si vous êtes un hyperviseur. La seule exception à cette règle aujourd'hui concerne les pays x86, mais la fin des machines non virtuelles arrive rapidement ...
Une recette Windows supplémentaire: utilisez la variable d'environnement système _NUMBER_OF_PROCESSORS
_:
_printf("%d\n", atoi(getenv("NUMBER_OF_PROCESSORS")));
_
Vous ne pourrez probablement pas l'obtenir d'une manière indépendante de la plate-forme. Windows vous obtenez le nombre de processeurs.
Nombre de groupes de processeurs logiques partageant un seul cœur de processeur. (Utilisation de GetLogicalProcessorInformationEx , voir GetLogicalProcessorInformation = aussi bien)
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_cores = 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_cores;
} while (offset < length);
return nb_physical_cores;
}
Notez que l'implémentation de NumberOfPhysicalCores
est un IMHO loin d'être trivial (c'est-à-dire "utilisez GetLogicalProcessorInformation
ou GetLogicalProcessorInformationEx
"). Au lieu de cela, il est plutôt subtil si on lit la documentation (explicitement présente pour GetLogicalProcessorInformation
et implicitement présente pour GetLogicalProcessorInformationEx
) sur MSDN.
Nombre de processeurs logiques. (Utilisation de 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);
}
Notez que les deux méthodes peuvent facilement être converties en C/C++ 98/C++ 03.
Plus sur OS X: sysconf(_SC_NPROCESSORS_ONLN)
est disponible uniquement pour les versions> = 10.5, et non 10.4.
Une alternative est le code HW_AVAILCPU/sysctl()
BSD disponible sur les versions> = 10.2.
Windows Server 2003 et versions ultérieures vous permettent d'exploiter la fonction GetLogicalProcessorInformation
Non lié au C++, mais sous Linux, je fais habituellement:
grep processor /proc/cpuinfo | wc -l
Pratique pour les langages de script tels que bash/Perl/python/Ruby.
Sous Linux, il peut ne pas être sûr d'utiliser _SC_NPROCESSORS_ONLN
car il ne fait pas partie de la norme POSIX et le manuel sysconf indique tout autant. Donc, il est possible que _SC_NPROCESSORS_ONLN
ne soit pas présent:
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).
Une approche simple consisterait à lire /proc/stat
ou /proc/cpuinfo
et à les compter:
#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);
return 0;
}
Utiliser /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);
return 0;
}
La même approche dans Shell utilisant grep:
grep -c ^processor /proc/cpuinfo
Ou
grep -c ^cpu /proc/stat # subtract 1 from the result
hwloc (http://www.open-mpi.org/projects/hwloc/) vaut la peine d’être examiné. Bien que cela nécessite une autre intégration de bibliothèque dans votre code, il peut fournir toutes les informations sur votre processeur (nombre de cœurs, topologie, etc.).
Pour Win32:
Alors que GetSystemInfo () vous obtient le nombre de processeurs logiques , utilisez GetLogicalProcessorInformationEx () pour obtenir le nombre de physiques processeurs.
Alternative à OS X: La solution décrite précédemment basée sur [[NSProcessInfo processInfo] CPUCount] est uniquement disponible sur OS X 10.5.0, conformément à la documentation. Pour les versions antérieures de OS X, utilisez la fonction Carbon MPProcessors ().
Si vous êtes un programmeur Cocoa, ne soyez pas effrayé par le fait qu'il s'agisse de Carbon. Vous devez simplement ajouter le cadre Carbon à votre projet Xcode et MPProcessors () sera disponible.
Sur Linux, le meilleur moyen de programmation que je connaisse consiste à utiliser
sysconf(_SC_NPROCESSORS_CONF)
ou
sysconf(_SC_NPROCESSORS_ONLN)
Ce ne sont pas standard, mais sont dans ma page de manuel pour Linux.