如何在Linux中使用C获得CPU的数量?

gopyfrb3  于 2022-12-11  发布在  Linux
关注(0)|答案(9)|浏览(123)

有没有一个API来获取Linux中可用的CPU数量?我的意思是,不使用/proc/cpuinfo或任何其他sys-node文件...
我发现这个实现使用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 < 64; i++)
 {
  if (CPU_ISSET(i, &cs))
   count++;
  else
   break;
 }
 return count;
}

但是,难道没有更高层次的使用公共库吗?

kxeu7u2r

kxeu7u2r1#

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

5uzkadbs2#

#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

ncgqoxb0

ncgqoxb03#

此代码(从here中提取)应能在Windows和 *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
}
emeijp43

emeijp434#

您在开头提到的sched_affinity()版本仍然比/proc/cpuinfo和/或_SC_NPROCESSORS_ONLN好,因为它只计算给定进程可用的CPU(某些CPU可能被外部进程调用的sched_setaffinity()禁用)。唯一的变化是使用CPU_COUNT(),而不是在循环中执行CPU_ISSET

czq61nw1

czq61nw15#

使用/proc/cpuinfo是最简洁、最可移植的解决方案。如果打开失败,你可以简单地假设1个cpu或2个cpu。为了微优化之外的目的(例如选择理想的线程数)而依赖于知道cpu数量的代码几乎肯定是在做一些愚蠢的事情。
_SC_NPROCESSORS_ONLN解决方案依赖于一个非标准的(glibc特定的)sysconf扩展,这比/proc的依赖性要大得多(所有的Linux系统都有/proc,但有些系统有非glibc libcs或缺少_SC_NPROCESSORS_ONLN的旧版本glibc)。

zaqlnxep

zaqlnxep6#

个人针对最新英特尔CPU(一般不是x86,只是Intel)我使用EAX=0Bhcpuid leaf。有关当前socket aka包中内核的详细信息,请参见Wikipedia。在多插槽系统上,这可能是系统范围内的物理/逻辑核数量的一半或四分之一。Intel在枚举CPU方面有a whitepaper,详细说明了在多插槽系统中要检查什么。此代码不执行此操作,它只检查一个子叶(ECX=1)。

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

输出量:

Cores: 4
Threads: 8
Actual thread: 1

或者,更简洁地说:

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

输出量:

Cores: 4
Threads: 8
HyperThreading: Yes
koaltpgm

koaltpgm7#

涉及sysconf(...)get_nprocs()的答案中没有一个是正确的,因为根据cpu关联性,处理器的数量限制为一个任务。
您需要类似下面的内容来获取任务可用的处理器数:

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

d8tt03nd8#

在Linux(Ubuntu)上:
第一个
(假设当前进程具有默认的CPU关联。)

aamkag61

aamkag619#

扫描sys文件系统下cpu* 目录的另一种方法:

#include<stdio.h>
#include <dirent.h>
#include <errno.h>
#define LINUX_SYS_CPU_DIRECTORY "/sys/devices/system/cpu"

int main() {
   int cpu_count = 0;
   DIR *sys_cpu_dir = opendir(LINUX_SYS_CPU_DIRECTORY);
   if (sys_cpu_dir == NULL) {
       int err = errno;
       printf("Cannot open %s directory, error (%d).\n", LINUX_SYS_CPU_DIRECTORY, strerror(err));
       return -1;
   }
   const struct dirent *cpu_dir;
   while((cpu_dir = readdir(sys_cpu_dir)) != NULL) {
       if (fnmatch("cpu[0-9]*", cpu_dir->d_name, 0) != 0)
       {
          /* Skip the file which does not represent a CPU */
          continue;
       }
       cpu_count++;
   }
   printf("CPU count: %d\n", cpu_count);
   return 0;
}

相关问题