Encuentra programáticamente el número de núcleos en una máquina
464
¿Hay alguna manera de determinar cuántos núcleos tiene una máquina de C / C ++ de forma independiente de la plataforma? Si no existe tal cosa, ¿qué hay de determinarlo por plataforma (Windows / * nix / Mac)?
Si desea usarlo, averigüe cuántos hilos comenzar, use NUMBER_OF_PROCESSORS como medida principal. Les dejo como ejercicio por qué esto es mucho mejor (si la gente lo usara más) que usar núcleos de hardware. ¡Cuántos núcleos pertenecen a su programa son un problema ambiental!
Lothar
Tenga en cuenta que std::thread::hardware_concurrencydevuelve el número de núcleos de CPU físicos, pero nprocen Linux muestra solo el número de núcleos de CPU en los que se puede ejecutar el proceso actual, que se pueden controlar sched_setaffinity. No he encontrado una manera de obtener eso en lugar de C ++ estándar :, consulte, por ejemplo, en Python: stackoverflow.com/questions/1006289/…
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
Respuestas:
706
C ++ 11
#include<thread>//may return 0 when not able to detectconstauto processor_count = std::thread::hardware_concurrency();
En C ++ anterior a C ++ 11, no hay una forma portátil. En su lugar, deberá utilizar uno o más de los siguientes métodos (protegido por las #ifdeflíneas apropiadas ):
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];
@mcandre: eso se deja como ejercicio para el lector. Si estuviera implementando, probablemente usaría el enfoque de política de plantilla donde la política se definió en las directivas de preprocesador. O ... podría usar boost thread :: hardware_concurrency ().
paxos1977
3
Como punto de aclaración, la solución Win32 devuelve el número total de núcleos (lo que se solicitó), no el número total de CPU físicas.
Eric
1
La forma Linux / Solaris / AIX también funciona en FreeBSD y lo ha hecho desde al menos 2006. Además, eso devolverá las CPU en línea, si un sistema es capaz de apagar algunas, es posible que no se cuenten. Llamar a sysconf con "_SC_NPROCESSORS_CONF" devolverá el total de CPU configuradas.
Chris S
3
Un par de cosas a tener en cuenta. HW_NCPUestá en desuso en OS X. En Windows GetSystemInfosolo es útil si su sistema tiene 32 procesadores lógicos o menos, utilícelo GetLogicalProcessorInformationpara sistemas que tengan más de 32 procesadores lógicos.
1
@Trejkaz, la documentación dice claramente "lógico", que siempre cuenta los núcleos HT, la palabra "físico" siempre se refiere a los núcleos informados por el BIOS / UEFI, ya que los núcleos también pueden ser emulados / virtualizados. Puede diferenciar entre núcleos HT / no HT con funciones como GetLogicalProcessorInformation , por ejemplo. Nota: HT! = Emulación o virtualización, eso es una gran diferencia, HT es una optimización de hardware, por así decirlo
En cualquier caso, hardware_concurrency()devuelve el número de subprocesos que el hardware es capaz de ejecutar simultáneamente en función del número de núcleos de CPU y unidades de hiperprocesamiento.
Secundado ... iba a usar el código de muestra anterior y algunas macros de preprocesador para exponer una sola función, pero el trabajo duro fue hecho por mí.
jkp
Para win32, es una llamada a GetSystemInfo. (A partir de la versión 1.41.0 de impulso) ¿Captura eso toda la información para determinar cuántos hilos de trabajo serían efectivos? ¿Es necesario tener en cuenta tanto el número de núcleos como el hiperprocesamiento? hilo sin firmar :: hardware_concurrency () {SYSTEM_INFO info = {0}; GetSystemInfo (& info); return info.dwNumberOfProcessors; }
Jive Dadson
Según MSDN, GetSystemInfo () devuelve el número de "procesadores físicos" en dwNumberOfProcessors pero no define lo que significa con eso. La documentación de Boost parece afirmar que incluye unidades de hyperthreading.
porque es una respuesta incorrecta De gcc.gnu.org/bugzilla/show_bug.cgi?id=37586 "omp_get_num_procs () solo devolverá un número menor que el número de CPU del sistema en línea, si se utiliza GOMP_CPU_AFFINITY env var, o si el proceso de llamada y / o el hilo tienen Afinidad de CPU limitada a un subconjunto de CPU ". Entonces, si llama anteriormente, por ejemplo, sched_setaffinityesto no funcionará.
angainor
77
Esta función devuelve el número de CPU disponibles para el proceso de llamada. ¿No es el caso de uso más común de todos modos? El tamaño real de algunos propósitos de informes inútiles, el número real de núcleos de hardware de CPU no es relevante para usted si no puede aprovecharlos en su código.
macbirdie
@EvanTeran Además del hecho de que era el propósito de la pregunta, por supuesto puede ser útil. Por ejemplo, con el fin de establecer la afinidad de hilo. Digamos, quiero ejecutar 4 hilos vinculados a los cuatro últimos núcleos de CPU en mi máquina, en lugar de cuatro primeros núcleos. Y además, hay otras formas de paralelizar el código, excepto OpenMP. Es posible que quiera generar pthreads yo mismo. Esos seguramente están disponibles y no están restringidos por las variables de entorno de OpenMP.
Angainor
2
Esto devuelve el número de CPU lógicas, no núcleos (CPU físicas) como tales.
Michael Konečný
37
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 sistemas operativos, aunque necesitará usar información específica del fabricante para determinar cómo encontrar el número 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 AMD.
Es posible que se haya rechazado porque la pregunta está etiquetada como C ++ y esta respuesta no se aplica a los sistemas que ejecutan C ++ en arquitecturas que no son x86 (ARM, PPC, etc.). No digo que sea una buena razón para rechazar una respuesta, solo una posibilidad.
Ferruccio
3
Una trampa de este método es si está utilizando CPUID para detectar HyperThreading en procesadores Intel. Me encontré con este problema en mi computadora portátil: mientras que la CPU que puse en la máquina admite HyperThreading (y, por supuesto, informa que lo hace a través de CPUID), el BIOS no. Por lo tanto, no debe intentar utilizar la capacidad HT simplemente desde una lectura de CPUID. Como no puede consultar el BIOS sobre el soporte HT (de ninguna manera que haya visto), se debe consultar el sistema operativo para obtener el recuento lógico del procesador.
Chuck R
32
(Casi) Plataforma Función independiente en código c
Excepto que que además cuenta hyperthreaded u otras soluciones SMT como más núcleos ...
jakobengblom2
13
@Arafangion: hyperthreading no es una verdadera ejecución paralela, es una tecnología para reducir la sobrecarga de cambio de contexto. Una CPU hyperthreaded solo puede ejecutar un subproceso a la vez, pero puede almacenar el estado arquitectónico (valores de registro, etc.) de dos subprocesos al mismo tiempo. Las características de rendimiento son muy diferentes de tener dos núcleos.
Wim Coenen
77
@Wim: Eso no es completamente correcto. Las CPU con hyperthreading generalmente tienen múltiples ALU y pueden enviar múltiples instrucciones por ciclo. Si debido a dependencias de datos y paradas, no todas las ALU pueden mantenerse ocupadas por un subproceso, esas ALU se utilizarán para la ejecución simultánea del segundo subproceso de hardware.
Ben Voigt
11
Tenga en cuenta que "número de núcleos" puede no ser un número particularmente útil, puede que tenga que calificarlo un poco más. ¿Cómo desea contar las CPU de subprocesos múltiples como Intel HT, IBM Power5 y Power6, y más famoso, Sun's Niagara / UltraSparc T1 y T2? O aún más interesante, el MIPS 1004k con sus dos niveles de subprocesamiento de hardware (supervisor Y nivel de usuario) ... Sin mencionar lo que sucede cuando se muda a sistemas compatibles con hipervisor donde el hardware puede tener decenas de CPU pero su sistema operativo particular solo ve unos pocos.
Lo mejor que puede esperar es decir la cantidad de unidades de procesamiento lógico que tiene en su partición local del sistema operativo. Olvídate de ver la verdadera máquina a menos que seas un hipervisor. La única excepción a esta regla hoy es en tierra x86, pero el final de las máquinas no virtuales está llegando rápidamente ...
Tenga en cuenta que la implementación de en NumberOfPhysicalCoresmi humilde opinión está lejos de ser trivial (es decir, "uso GetLogicalProcessorInformationo GetLogicalProcessorInformationEx"). En cambio, es bastante sutil si uno lee la documentación (explícitamente presente GetLogicalProcessorInformatione implícitamente presente GetLogicalProcessorInformationEx) en MSDN.
El número de procesadores lógicos. (Usando GetSystemInfo )
¡Gracias! Estaba buscando esto porque GetLogicalProcessorInformationno trabajaba con varios tamaños de búfer que usaba. Más que satisfecho! ^^
KeyWeeUsr
@KeyWeeUsr Gracias La programación de Windows está lejos de ser trivial y lógica. Mientras tanto, uso una versión de C ++ 17 ligeramente más actualizada que también es más correcta según el analizador estático PVS-Studio con respecto a algunos size_tmodelos. (Aunque msvc ++ no se queja en W4.)
Matthias
5
Más sobre OS X: sysconf(_SC_NPROCESSORS_ONLN)solo está disponible versiones> = 10.5, no 10.4.
Una alternativa es el HW_AVAILCPU/sysctl()código BSD que está disponible en versiones> = 10.2.
Para python:import multiprocessingprint multiprocessing.cpu_count()
initzero
3
¡Ha pasado mucho tiempo, pero greptiene -cbandera para contar entradas!
Lapshin Dmitry
3
Vale la pena mirar hwloc (http://www.open-mpi.org/projects/hwloc/). 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, la topología, etc.)
En Linux, es posible que no sea seguro de usar, _SC_NPROCESSORS_ONLNya que no forma parte del estándar POSIX y el manual sysconf lo dice tanto. Entonces, existe la posibilidad de que _SC_NPROCESSORS_ONLNno 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 leerlos /proc/stato /proc/cpuinfocontarlos:
#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;}
Utilizando /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;}
El mismo enfoque en shell usando grep:
grep -c ^processor /proc/cpuinfo
O
grep -c ^cpu /proc/stat # subtract 1 from the result
Alternativa OS X: la solución descrita anteriormente basada en [[NSProcessInfo processInfo] processorCount] solo está disponible en OS X 10.5.0, según los documentos. Para versiones anteriores de OS X, use la función Carbon MPProcessors ().
Si eres un programador de Cocoa, no te asustes por el hecho de que se trata de carbono. Solo necesita agregar el marco Carbon a su proyecto Xcode y MPProcessors () estará disponible.
Si bien GetSystemInfo () le proporciona la cantidad de procesadores lógicos , use
GetLogicalProcessorInformationEx ()
para obtener la cantidad de procesadores físicos .
también puede usar WMI en .net, pero luego depende del servicio wmi que se ejecuta, etc. A veces funciona localmente, pero luego 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.
std::thread::hardware_concurrency
devuelve el número de núcleos de CPU físicos, peronproc
en Linux muestra solo el número de núcleos de CPU en los que se puede ejecutar el proceso actual, que se pueden controlarsched_setaffinity
. No he encontrado una manera de obtener eso en lugar de C ++ estándar :, consulte, por ejemplo, en Python: stackoverflow.com/questions/1006289/…Respuestas:
C ++ 11
Referencia: std :: thread :: hardware_concurrency
En C ++ anterior a C ++ 11, no hay una forma portátil. En su lugar, deberá utilizar uno o más de los siguientes métodos (protegido por las
#ifdef
líneas apropiadas ):Win32
Linux, Solaris, AIX y Mac OS X> = 10.4 (es decir, Tiger en adelante)
FreeBSD, MacOS X, NetBSD, OpenBSD, etc.
HPUX
IRIX
Objective-C (Mac OS X> = 10.5 o iOS)
fuente
HW_NCPU
está en desuso en OS X. En WindowsGetSystemInfo
solo es útil si su sistema tiene 32 procesadores lógicos o menos, utilíceloGetLogicalProcessorInformation
para sistemas que tengan más de 32 procesadores lógicos.Esta funcionalidad es parte del estándar C ++ 11.
Para compiladores más antiguos, puede usar la biblioteca Boost.Thread .
En cualquier caso,
hardware_concurrency()
devuelve el número de subprocesos que el hardware es capaz de ejecutar simultáneamente en función del número de núcleos de CPU y unidades de hiperprocesamiento.fuente
OpenMP es compatible con muchas plataformas (incluido Visual Studio 2005) y ofrece un
función que devuelve el número de procesadores / núcleos disponibles en el momento de la llamada.
fuente
sched_setaffinity
esto no funcionará.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 sistemas operativos, aunque necesitará usar información específica del fabricante para determinar cómo encontrar el número 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 AMD.
fuente
(Casi) Plataforma Función independiente en código c
fuente
HW_NCPU
está en desuso en la fuenteEn Linux, puede leer el archivo / proc / cpuinfo y contar los núcleos.
fuente
Tenga en cuenta que "número de núcleos" puede no ser un número particularmente útil, puede que tenga que calificarlo un poco más. ¿Cómo desea contar las CPU de subprocesos múltiples como Intel HT, IBM Power5 y Power6, y más famoso, Sun's Niagara / UltraSparc T1 y T2? O aún más interesante, el MIPS 1004k con sus dos niveles de subprocesamiento de hardware (supervisor Y nivel de usuario) ... Sin mencionar lo que sucede cuando se muda a sistemas compatibles con hipervisor donde el hardware puede tener decenas de CPU pero su sistema operativo particular solo ve unos pocos.
Lo mejor que puede esperar es decir la cantidad de unidades de procesamiento lógico que tiene en su partición local del sistema operativo. Olvídate de ver la verdadera máquina a menos que seas un hipervisor. La única excepción a esta regla hoy es en tierra x86, pero el final de las máquinas no virtuales está llegando rápidamente ...
fuente
Una receta más de Windows: use la variable de entorno de todo el sistema
NUMBER_OF_PROCESSORS
:fuente
Probablemente no podrá obtenerlo de forma independiente de la plataforma. Windows obtienes varios procesadores.
Información del sistema Win32
fuente
Windows (x64 y Win32) y C ++ 11
El número de grupos de procesadores lógicos que comparten un solo núcleo de procesador. (Usando GetLogicalProcessorInformationEx , vea también GetLogicalProcessorInformation )
Tenga en cuenta que la implementación de en
NumberOfPhysicalCores
mi humilde opinión está lejos de ser trivial (es decir, "usoGetLogicalProcessorInformation
oGetLogicalProcessorInformationEx
"). En cambio, es bastante sutil si uno lee la documentación (explícitamente presenteGetLogicalProcessorInformation
e implícitamente presenteGetLogicalProcessorInformationEx
) en MSDN.El número de procesadores lógicos. (Usando GetSystemInfo )
Tenga en cuenta que ambos métodos se pueden convertir fácilmente a C / C ++ 98 / C ++ 03.
fuente
GetLogicalProcessorInformation
no trabajaba con varios tamaños de búfer que usaba. Más que satisfecho! ^^size_t
modelos. (Aunque msvc ++ no se queja en W4.)Más sobre OS X:
sysconf(_SC_NPROCESSORS_ONLN)
solo está disponible versiones> = 10.5, no 10.4.Una alternativa es el
HW_AVAILCPU/sysctl()
código BSD que está disponible en versiones> = 10.2.fuente
Windows Server 2003 y posterior le permite aprovechar la función GetLogicalProcessorInformation
http://msdn.microsoft.com/en-us/library/ms683194.aspx
fuente
Sin relación con C ++, pero en Linux generalmente lo hago:
Práctico para lenguajes de script como bash / perl / python / ruby.
fuente
import multiprocessing
print multiprocessing.cpu_count()
grep
tiene-c
bandera para contar entradas!Vale la pena mirar hwloc (http://www.open-mpi.org/projects/hwloc/). 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, la topología, etc.)
fuente
En Linux, la mejor forma programática que yo sepa es usar
o
Estos no son estándar, pero están en mi página de manual para Linux.
fuente
En Linux, es posible que no sea seguro de usar,
_SC_NPROCESSORS_ONLN
ya que no forma parte del estándar POSIX y el manual sysconf lo dice tanto. Entonces, existe la posibilidad de que_SC_NPROCESSORS_ONLN
no esté presente:Un enfoque simple sería leerlos
/proc/stat
o/proc/cpuinfo
contarlos:Utilizando
/proc/cpuinfo
:El mismo enfoque en shell usando grep:
O
fuente
Alternativa OS X: la solución descrita anteriormente basada en [[NSProcessInfo processInfo] processorCount] solo está disponible en OS X 10.5.0, según los documentos. Para versiones anteriores de OS X, use la función Carbon MPProcessors ().
Si eres un programador de Cocoa, no te asustes por el hecho de que se trata de carbono. Solo necesita agregar el marco Carbon a su proyecto Xcode y MPProcessors () estará disponible.
fuente
Para Win32:
Si bien GetSystemInfo () le proporciona la cantidad de procesadores lógicos , use GetLogicalProcessorInformationEx () para obtener la cantidad de procesadores físicos .
fuente
también puede usar WMI en .net, pero luego depende del servicio wmi que se ejecuta, etc. A veces funciona localmente, pero luego 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.
fuente
En Linux, puede pagar dmesg y filtrar las líneas donde ACPI inicializa las CPU, algo así como:
dmesg | grep 'ACPI: Processor
'Otra posibilidad es usar dmidecode para filtrar la información del procesador.
fuente