假设Linux,并假设当前的shell 启动时可能受到taskset的限制,我可以编写一些代码来获取当前进程亲和力,如下所示

#include <vector>
#include <pthread.h>
#include <stdio.h>

int getNumberOfAvailableCores() {
    pthread_t self = pthread_self();
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
    int res = ::pthread_getaffinity_np(self, sizeof(cpuset), &cpuset);
    int num_cores = 0;
    if ( res!=0 ) return -1;
    for (int j = 0; j < CPU_SETSIZE; j++) {
        if (CPU_ISSET(j, &cpuset)) ++num_cores;
    }
    return num_cores;
}


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

https://godbolt.org/z/TxT67WWT6

但在我甚至没有安装编译器的机器上,有没有办法猜测可用内核的数量?

getconf _NPROCESSORS_ONLN将返回在线处理器的数量,但不会考虑隔离的核心数量.GREG /proc/cpuinfolscpu也是如此.

我调查了/proc/self个,但找不到一个干净利落的方法.

推荐答案

您需要命令nproc:

nproc-打印可用处理单元的数量

关联掩码包含3个处理器的示例:

$ taskset --cpu-list 0,2,4 bash
$ nproc
3

如果nproc由于某些原因无法使用,我以前的回答可能会有用:

命令taskset用于设置或检索给定ID的运行进程的CPU亲和性

taskset-p选项是:

  • 在现有的PID上操作,并且不启动新任务.

因此,您将获得一个带有进程亲和性掩码的十六进制数.示例:

$ taskset -p $$
pid 1643922's current affinity mask: fff

Now, you want to do a (count the number of 1s in the binary representation of the number).

这个 idea 是将数字转换成二进制形式,然后数出1的数量.下面是一句俏皮话:

taskset -p $$ | \
tr '[[:lower:]]' '[[:upper:]]' | \
sed -E 's/.*:\s*/ibase=16;obase=2;/' | bc | tr -d '0\n' | wc -c
  • tr '[[:lower:]]' '[[:upper:]]'-将taskset的输出转换为大写(因为bc需要大写的十六进制数字).
  • sed -E 's/.*:\s*/ibase=16;obase=2;/' - remove the textual output from taskset and replace it with instructions for bc. ibase is the base of the input number (16 = hex) and obase is the base we want for the output (2 = binary).
    • 在这一点上,我们将有ibase=16;obase=2;FFF
  • bc-读取ibase=16;obase=2;FFF并将FFF打印为111111111111
  • tr -d '0\n'-从bc的输出中删除所有零和换行符
  • wc -c-计算所有字符.

在我的例子中,亲和性掩码是fff,输出是12.


测试:我在这里启动了一个带有3个可用处理器的子shell ,然后在该shell 中使用上面的onlininer来解决这个问题:

$ taskset --cpu-list 0,2,4 bash
$ taskset -p $$ | \
> tr '[[:lower:]]' '[[:upper:]]' | \
> sed -E 's/.*:\s*/ibase=16;obase=2;/' | bc | tr -d '0\n' | wc -c
3

Linux相关问答推荐

将UTC字符串日期时间转换为毫秒UTC时间戳

创建守护进程时打开0,1,2描述符

为什么硬编码的阿拉伯字母与Unicode代码点不具有相同的值

通过添加1位数字替换最后4位数字(不包括0x)

2023 年如何在现代 Linux 上安装 Firebird SQL 版本 3 或 4?

如何让xargs对 bash 脚本中find命令找到的所有文件执行?

如何验证所有 csv 文件是否具有相同的第一行?

在 Ubuntu 中,如何设置 Tomcat 9 以使用 Java 17?

将 Visual Studio C++ 项目迁移到 Linux 和 CMake

Ubuntu 20 不支持 MAP_FIXED_NOREPLACE

将文件的一部分插入到另一个文件的特定位置

文件未在脚本中使用 cp 命令复制到 Docker 容器中

进程Forking 后 pthread_key_create() 生成的密钥会发生什么?

如何计算制表符分隔的文本文件中字段的唯一值的数量?

如何将 bash 别名定义为多个命令的序列?

将原始数据发送到 TCP 服务器的 Linux 工具

Shell 脚本, echo 消息后在同一行读取

如何在 Linux 中查看日志(log)文件并在查看时应用自定义过滤器?

以 qsub 开头的 shell 脚本的参数

如何使用mv命令移动特定目录中的文件除外?