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

是否有一个 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;
}

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

82037 次浏览
#include <unistd.h>
long number_of_processors = sysconf(_SC_NPROCESSORS_ONLN);

使用 /proc/cpuinfo是最干净和最便携的解决方案。如果打开失败,您可以简单地假设有1个 cpu 或2个 cpu。除了微优化(例如选择要运行的线程的理想数量)之外,那些依赖于知道 CPU 数量的代码几乎肯定是在做一些愚蠢的事情。

_SC_NPROCESSORS_ONLN解决方案依赖于一个非标准的(glibc 特定的) sysconf扩展,这是一个比 /proc更大的依赖(所有 Linux 系统都有 /proc,但是有些有非 glibc libcs 或者没有 _SC_NPROCESSORS_ONLN的 glibc 旧版本)。

这段代码(取自 给你)应该可以同时在 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
}

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

另一种扫描系统文件系统下的 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;
}
#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

就个人而言,我使用的是 EAX=0Bh cpuid叶片(一般不是 x86,只是 Intel)。请参阅 维基百科获得关于当前套接字又名软件包中核心信息的一些详细信息。在多套接字系统上,这可能是整个系统物理/逻辑内核数量的一半或四分之一。英特尔有 白皮书枚举 CPU 的详细信息,在多套接字系统的情况下应该检查什么。这段代码没有这样做,它只是检查一个子叶(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

没有一个涉及到 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;
}