¿Cómo obtener la cantidad de CPU en Linux usando C?

7 minutos de lectura

avatar de usuario
Treviño

¿Existe una API para obtener la cantidad de CPU disponibles en Linux? Quiero decir, sin usar /proc/cpuinfo o cualquier otro archivo sys-node…

Encontré esta implementación usando sched.h:

int GetCPUCount()
{
 cpu_set_t cs;
 CPU_ZERO(&cs);
 sched_getaffinity(0, sizeof(cs), &cs);

 int count = 0;
 for (int i = 0; i < 8; i++)
 {
  if (CPU_ISSET(i, &cs))
   count++;
 }
 return count;
}

Pero, ¿no hay nada de mayor nivel usando librerías comunes?

  • ¿Por qué la gente tiene tanto miedo de usar /proc? Cada caja de Linux que he visto en los últimos 15 años lo tiene, siempre está actualizado con lo que sabe el kernel, y el formato de las cosas existentes no cambia mucho.

    – chao

    3 de enero de 2011 a las 16:58

  • Creo que es genial que estés tratando de aprender diferentes formas de hacer las cosas, pero ¿estás tratando de reinventar la rueda?

    –David Weiser

    3 de enero de 2011 a las 17:09

  • Para sistemas gnulib esto lo hace trabaje mirando /proc, pero si realmente quiere una sola línea fácil y no tiene consideraciones importantes de rendimiento/seguridad, puede simplemente (system("exit `nproc`") >> 8) …incluso busybox tiene un nproc interno, por lo que debería funcionar bien en casi cualquier Linux (por ejemplo, el firmware de mi enrutador…). El cambio es necesario porque sh los códigos de salida incorporan un byte nulo final para facilitar el procesamiento de cadenas.

    – lk

    5 de mayo de 2019 a las 9:01


  • Consulte también stackoverflow.com/questions/150355/…

    –Jay Sullivan

    1 de febrero de 2020 a las 15:53

  • /proc no es portátil

    – Edd Barrett

    2 de junio de 2021 a las 11:07

avatar de usuario
chrisaycock

#include <unistd.h>
long number_of_processors = sysconf(_SC_NPROCESSORS_ONLN);

  • Buena solución, pero parece una extensión de Linux para POSIX: pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html

    – Ciro Santilli Путлер Капут 六四事

    3 de noviembre de 2015 a las 23:26

  • Esto da el número de núcleos en línea. Si hago un núcleo fuera de línea, no volverá aquí

    – iDebD_gh

    8 de septiembre de 2016 a las 7:01

  • @iDebD_gh – Si no me equivoco, eso es lo que _SC_NPROCESSORS_CONF proporciona.

    – selbie

    22 de noviembre de 2018 a las 3:20

  • @iDebD_gh ¿Qué quiere decir con núcleo fuera de línea?

    –Lewis Chan

    20 de mayo de 2020 a las 9:05

avatar de usuario
Владимир Николайчук

#include <stdio.h>
#include <sys/sysinfo.h>

int main(int argc, char *argv[])
{
    printf("This system has %d processors configured and "
        "%d processors available.\n",
        get_nprocs_conf(), get_nprocs());
    return 0;
}

https://linux.die.net/man/3/get_nprocs

  • Esta respuesta no da el mismo resultado que el fragmento dado en la pregunta. Si un proceso está vinculado a un subconjunto de CPU en la máquina usando tasksetentonces el método que usa sched_getaffinity() da el número de CPU asignadas, mientras que get_nprocs() da el número total de CPUs que la máquina tiene disponibles. Esto es malo si está utilizando esto para decidir sobre una cantidad de subprocesos, ya que si solo se asigna un solo núcleo en una máquina de muchos núcleos, entonces el proceso se colapsará.

    – Ed Bennett

    1 de septiembre de 2021 a las 9:59


avatar de usuario
Vikram.exe

Este código (extraído de aquí) debería funcionar tanto en Windows como en plataformas *NIX.

#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>


int main() {
  long nprocs = -1;
  long nprocs_max = -1;
#ifdef _WIN32
#ifndef _SC_NPROCESSORS_ONLN
SYSTEM_INFO info;
GetSystemInfo(&info);
#define sysconf(a) info.dwNumberOfProcessors
#define _SC_NPROCESSORS_ONLN
#endif
#endif
#ifdef _SC_NPROCESSORS_ONLN
  nprocs = sysconf(_SC_NPROCESSORS_ONLN);
  if (nprocs < 1)
  {
    fprintf(stderr, "Could not determine number of CPUs online:\n%s\n", 
strerror (errno));
    exit (EXIT_FAILURE);
  }
  nprocs_max = sysconf(_SC_NPROCESSORS_CONF);
  if (nprocs_max < 1)
  {
    fprintf(stderr, "Could not determine number of CPUs configured:\n%s\n", 
strerror (errno));
    exit (EXIT_FAILURE);
  }
  printf ("%ld of %ld processors online\n",nprocs, nprocs_max);
  exit (EXIT_SUCCESS);
#else
  fprintf(stderr, "Could not determine number of CPUs");
  exit (EXIT_FAILURE);
#endif
}

  • Obtuve este código hace mucho tiempo de alguien (no recuerdo el nombre).

    – Vikram.exe

    3 de enero de 2011 a las 18:10

  • No estoy seguro de que publicar este fragmento de código realmente responda la pregunta del OP, aunque podrían aplicar ingeniería inversa a alguna información útil.

    – MarkR

    4 de enero de 2011 a las 6:47

  • Estoy de acuerdo con Mark R. Chrisaycock ofrece una respuesta sucinta.

    – puntero

    5 de julio de 2012 a las 17:41

  • Deberías usar el #error directiva de preprocesador si _SC_NPROCESSORS_ONLN no está definido. Esta es una falla en tiempo de compilación, no una falla en tiempo de ejecución.

    – Guido Flohr

    3 de febrero de 2019 a las 11:43

Utilizando /proc/cpuinfo es la solución más limpia y portátil. En caso de que falle la apertura, simplemente podría asumir 1 CPU o 2 CPU. El código que depende de conocer la cantidad de CPU para un propósito que no sea la microoptimización (por ejemplo, elegir la cantidad ideal de subprocesos para ejecutar) casi seguramente está haciendo algo tonto.

los _SC_NPROCESSORS_ONLN la solución depende de un no estándar (específico de glibc) sysconf extension, que es una dependencia mucho mayor que /proc (todos los sistemas Linux tienen /procpero algunos tienen libcs ​​que no son glibc o versiones anteriores de glibc que carecen _SC_NPROCESSORS_ONLN).

avatar de usuario
RCL

sched_affinity() la versión que mencionas al principio sigue siendo mejor que /proc/cpuinfo y/o _SC_NPROCESSORS_ONLN ya que solo cuenta las CPU disponibles para un proceso dado (algunas pueden ser deshabilitadas por sched_setaffinity() invocado por un proceso externo). El único cambio sería usar CPU_COUNT() en lugar de hacer CPU_ISSET en un bucle

Personalmente para cpus intel recientes Yo uso esto:

int main()
{
unsigned int eax=11,ebx=0,ecx=1,edx=0;

asm volatile("cpuid"
        : "=a" (eax),
          "=b" (ebx),
          "=c" (ecx),
          "=d" (edx)
        : "0" (eax), "2" (ecx)
        : );
            
printf("Cores: %d\nThreads: %d\nActual thread: %d\n",eax,ebx,edx);
}

Producción:

Cores: 4
Threads: 8
Actual thread: 1

O, más concisamente:

#include <stdio.h>

int main()
{
unsigned int ncores=0,nthreads=0,ht=0;

asm volatile("cpuid": "=a" (ncores), "=b" (nthreads) : "a" (0xb), "c" (0x1) : );

ht=(ncores!=nthreads);

printf("Cores: %d\nThreads: %d\nHyperThreading: %s\n",ncores,nthreads,ht?"Yes":"No");

return 0;
}

Producción:

Cores: 4
Threads: 8
HyperThreading: Yes

avatar de usuario
Damián Zammit

Ninguna de las respuestas que involucran sysconf(...) o get_nprocs() son correctos para respetar la cantidad de procesadores restringidos a una tarea por afinidad de CPU.

Necesita algo como esto para obtener la cantidad de procesadores disponibles para una tarea:

#define _GNU_SOURCE
#include <sched.h>
#include <stdio.h>

int nprocs()
{
  cpu_set_t cs;
  CPU_ZERO(&cs);
  sched_getaffinity(0, sizeof(cs), &cs);
  return CPU_COUNT(&cs);
}

int main()
{
  printf("procs=%d\n", nprocs());
  return 0;
}

  • ¿Seguiría siendo correcto si el proceso llamó a cpu_setaffinity para restringir la cantidad de CPU afines?

    – usuario1637056

    10 de agosto de 2020 a las 23:43

  • Para la prueba, tengo un script bash while : ; do echo 0 > /sys/devices/system/cpu/cpu3/online && sleep 0.5 && echo 1 > /sys/devices/system/cpu/cpu3/online ; sleep 0.5 ; echo Hey! ; done ; apaga y enciende cpu3 muy rápido. sysconf(_SC_NPROCESSORS_ONLN) no muestra la CPU correcta cuando se coloca dentro de un ciclo while, pero si lo coloco en un watch -n 0.1 ./a.out (elección terrible), entonces muestra que el núcleo cuenta correctamente. Lo mismo con getconf, se reinicia cada vez que se ve y muestra la información correcta. Su secuencia de comandos también muestra los valores correctos.

    – S.Goswami

    20 de diciembre de 2020 a las 21:18

  • Pero la advertencia es que si uso task -c 0 ./a.outme da procs=1 en lugar de 4, en otras palabras, solo cuenta la CPU asignada al proceso.

    – S.Goswami

    21 de diciembre de 2020 a las 7:42

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad