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

发布于 2024-10-10 14:14:39 字数 395 浏览 0 评论 0原文

Linux 中有没有可以获取可用 CPU 数量的 API? 我的意思是,在不使用 /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;
}

但是,没有使用通用库的更高级别吗?

Is there an API to get the number of CPUs available in Linux?
I mean, without using /proc/cpuinfo or any other sys-node file...

I've found this implementation using 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;
}

But, isn't there anything more higher level using common libraries?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

顾冷 2024-10-17 14:14:40
#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

#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

少女的英雄梦 2024-10-17 14:14:40

此代码(取自此处)应该适用于两者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
}

This code (drawn from here) should work on both windows and *NIX platforms.

#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
}
飘然心甜 2024-10-17 14:14:40

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

sched_affinity() version you mention in the beginning is still better than /proc/cpuinfo and/or _SC_NPROCESSORS_ONLN since it only counts CPUs available for a given process (some may be disabled by sched_setaffinity() invoked by an outside process). The only change would be using CPU_COUNT() instead of doing CPU_ISSET in a loop.

智商已欠费 2024-10-17 14:14:40

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

_SC_NPROCESSORS_ONLN 解决方案依赖于非标准(glibc 特定的)sysconf 扩展,该扩展比 /proc 具有更大的依赖性(所有 Linux系统有 /proc,但有些系统有非 glibc libcs​​ 或缺少 _SC_NPROCESSORS_ONLN 的旧版本 glibc)。

Using /proc/cpuinfo is the cleanest and most portable solution. In case the open fails, you could simply assume 1 cpu or 2 cpus. Code that depends on knowing the number of cpus for a purpose other than micro-optimizing (e.g. choosing the ideal number of threads to run) is almost surely doing something dumb.

The _SC_NPROCESSORS_ONLN solution depends on a non-standard (glibc-specific) sysconf extension, which is a much bigger dependency than /proc (all Linux systems have /proc, but some have non-glibc libcs or older versions of glibc that lack _SC_NPROCESSORS_ONLN).

不甘平庸 2024-10-17 14:14:40

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

None of the answers that involve sysconf(...) or get_nprocs() are correct for honouring the number of processors restricted to a task by cpu affinity.

You need something like this to get the number of processors available to a task:

#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;
}
苍风燃霜 2024-10-17 14:14:40

就我个人而言,对于最近的 Intel cpu(不是一般的 x86,只是 Intel),我使用 EAX=0Bh cpuid 叶子。请参阅维基百科,了解有关您获得的信息的一些详细信息关于当前套接字(又名封装)中的核心。在多插槽系统上,这可能是系统范围物理/逻辑核心数量的一半或四分之一。英特尔有

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

Personally for recent Intel cpus (not x86 in general, just Intel) I use the EAX=0Bh cpuid leaf. See Wikipedia for some details on what info you get about the cores in the current socket aka package. On a multi-socket system, this might be half or a quarter of the system-wide number of physical / logical cores. Intel has a whitepaper on enumerating CPUs with details on what to check in case of multi-socket systems. This code doesn't do that, it just checks one sub-leaf (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);
}

Output:

Cores: 4
Threads: 8
Actual thread: 1

Or, more concisely:

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

Output:

Cores: 4
Threads: 8
HyperThreading: Yes
鹿港巷口少年归 2024-10-17 14:14:40

在 Linux (Ubuntu) 上:(

#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <sched.h>
int GetCPUCount()
{
 cpu_set_t cs;
 sched_getaffinity(0, sizeof(cs), &cs);
 return CPU_COUNT_S(sizeof(cs), &cs);
}

假设当前进程具有默认的 CPU 关联性。)

On Linux (Ubuntu):

#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#include <sched.h>
int GetCPUCount()
{
 cpu_set_t cs;
 sched_getaffinity(0, sizeof(cs), &cs);
 return CPU_COUNT_S(sizeof(cs), &cs);
}

(Assuming the current process has the default CPU affinity.)

哆啦不做梦 2024-10-17 14:14:40

另一种扫描 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;
}

Another method scanning cpu* directories under sys file system:

#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;
}
随风而去 2024-10-17 14:14:39
#include <unistd.h>
long number_of_processors = sysconf(_SC_NPROCESSORS_ONLN);
#include <unistd.h>
long number_of_processors = sysconf(_SC_NPROCESSORS_ONLN);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文