Encuentre programáticamente la cantidad de núcleos en una máquina

¿Hay alguna manera de determinar cuántos núcleos tiene una máquina de C / C ++ de una manera independiente de la plataforma? Si no existe tal cosa, ¿qué hay de determinarla por plataforma (Windows / * nix / Mac)?

C ++ 11

//may return 0 when not able to detect unsigned concurentThreadsSupported = std::thread::hardware_concurrency(); 

Referencia: std :: thread :: hardware_concurrency


En C ++ antes de C ++ 11, no hay una forma portátil. En su lugar, deberá usar uno o más de los siguientes métodos (protegidos por las líneas apropiadas #ifdef ):

  • Win32

     SYSTEM_INFO sysinfo; GetSystemInfo(&sysinfo); int numCPU = sysinfo.dwNumberOfProcessors; 
  • Linux, Solaris, AIX y Mac OS X> = 10.4 (es decir, Tiger en adelante)

     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 o iOS)

     NSUInteger a = [[NSProcessInfo processInfo] processorCount]; NSUInteger b = [[NSProcessInfo processInfo] activeProcessorCount]; 

Esta funcionalidad es parte del estándar C ++ 11.

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

Para comstackdores más antiguos, puede usar la biblioteca Boost.Thread .

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

En cualquier caso, hardware_concurrency() devuelve la cantidad de subprocesos que el hardware es capaz de ejecutar de manera concurrente en función de la cantidad de núcleos de CPU y unidades de subprocesamiento.

OpenMP es compatible con muchas plataformas (incluido Visual Studio 2005) y ofrece una

 int omp_get_num_procs(); 

función que devuelve la cantidad de procesadores / núcleos disponibles en el momento de la llamada.

Si tiene acceso en lenguaje ensamblador, puede usar la instrucción CPUID para obtener todo tipo de información sobre la CPU. Es portátil entre los sistemas operativos, aunque deberá usar información específica del fabricante para determinar cómo encontrar la cantidad de núcleos. Aquí hay un documento que describe cómo hacerlo en chips Intel , y la página 11 de este describe la especificación de AMD.

(Casi) Función independiente de plataforma en 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 } 

En Linux, puede leer el archivo / proc / cpuinfo y contar los núcleos.

Tenga en cuenta que la “cantidad de núcleos” podría no ser un número particularmente útil, es posible que tenga que calificar un poco más. ¿Cómo desea contar las CPU de subprocesos múltiples como Intel HT, IBM Power5 y Power6, y lo más famoso, las Niagara / UltraSparc T1 y T2 de Sun? O incluso más interesante, el MIPS 1004k con sus dos niveles de enhebrado de hardware (supervisor Y nivel de usuario) … Sin mencionar lo que sucede cuando te mueves a sistemas soportados por hipervisor donde el hardware puede tener decenas de CPU pero tu SO particular solo ve algunos.

Lo mejor que puede esperar es contar la cantidad de unidades lógicas de procesamiento que tiene en su partición de sistema operativo local. Olvídate de ver la verdadera máquina a menos que seas un hipervisor. La única excepción a esta regla hoy es en x86 land, pero el final de las máquinas no virtuales está llegando rápidamente …

Una receta más de Windows: use la variable de entorno de todo el sistema NUMBER_OF_PROCESSORS :

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

Probablemente no podrá obtenerlo de manera independiente de la plataforma. Windows obtienes cantidad de procesadores.

Información del sistema Win32

Más sobre OS X: sysconf(_SC_NPROCESSORS_ONLN) solo está disponible en versiones> = 10.5, no en 10.4.

Una alternativa es el código BSD HW_AVAILCPU/sysctl() que está disponible en versiones> = 10.2.

Windows Server 2003 y posterior le permite aprovechar la función GetLogicalProcessorInformation

http://msdn.microsoft.com/en-us/library/ms683194.aspx

No relacionado con C ++, pero en Linux generalmente lo hago:

 grep processor /proc/cpuinfo | wc -l 

Útil para lenguajes de scripting como bash / perl / python / ruby.

hwloc (http://www.open-mpi.org/projects/hwloc/) vale la pena mirar. Aunque requiere otra integración de biblioteca en su código, pero puede proporcionar toda la información sobre su procesador (número de núcleos, topología, etc.)

En Linux, puede no ser seguro usar _SC_NPROCESSORS_ONLN ya que no es parte del estándar POSIX y el manual de sysconf lo dice. Entonces, existe la posibilidad de que _SC_NPROCESSORS_ONLN no esté 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). 

Un enfoque simple sería leer /proc/stat o /proc/cpuinfo y contarlos:

 #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 /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; } 

El mismo enfoque en shell usando grep:

 grep -c ^processor /proc/cpuinfo 

O

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

Windows (x64 y Win32) y C ++ 11

La cantidad de grupos de procesadores lógicos que comparten un único núcleo de procesador. (Usando GetLogicalProcessorInformationEx , vea GetLogicalProcessorInformation también)

 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; } 

Tenga en cuenta que la implementación de NumberOfPhysicalCores es IMHO lejos de ser trivial (es decir, "use GetLogicalProcessorInformation o GetLogicalProcessorInformationEx "). En cambio, es bastante sutil si se lee la documentación (presente explícitamente para GetLogicalProcessorInformation y presente implícitamente para GetLogicalProcessorInformationEx ) en MSDN.

La cantidad de procesadores 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); } 

Tenga en cuenta que ambos métodos se pueden convertir fácilmente a C / C ++ 98 / C ++ 03.

Alternativa OS X: la solución descrita anteriormente basada en [[NSProcessInfo processInfo] processorCount] solo está disponible en OS X 10.5.0, de acuerdo con los documentos. Para versiones anteriores de OS X, use la función de carbono MPProcessors ().

Si eres un progtwigdor de Cocoa, no te asustes por el hecho de que es carbono. Solo necesita agregar la estructura de Carbon a su proyecto de Xcode y MPProcessors () estará disponible.

En Linux, la mejor forma programática, hasta donde yo sé, es usar

 sysconf(_SC_NPROCESSORS_CONF) 

o

 sysconf(_SC_NPROCESSORS_ONLN) 

Estos no son estándar, pero están en mi página man para Linux.

Para Win32:

Mientras GetSystemInfo () obtiene la cantidad de procesadores lógicos , use GetLogicalProcessorInformationEx () para obtener la cantidad de procesadores físicos .

también puede usar WMI en .net, pero depende del servicio de wmi, etc. A veces funciona de manera local, pero falla cuando se ejecuta el mismo código en los servidores. Creo que es un problema de espacio de nombres, relacionado con los “nombres” cuyos valores estás leyendo.

En Linux, puede verificar dmesg y filtrar las líneas donde ACPI inicializa las CPU, algo como:

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

Otra posibilidad es usar dmidecode para filtrar la información del procesador.