如何设置线程亲和性到性能或高效内核?

How to set thread affinity to either performance or efficient cores?

提问人:user2023370 提问时间:11/2/2023 最后编辑:user2023370 更新时间:11/3/2023 访问量:99

问:

我熟悉用于设置线程想要运行的 cpu。在下面的代码中,线程请求执行(设置为 13),方法是通过宏设置 affinity mask 来执行。pthread_attr_setaffinity_nptcpu_targetcpusetCPU_SET

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

int main(int argc, char *argv[])
{
  pthread_attr_t attr;
  pthread_t t;
  cpu_set_t cpuset;
  const int cpu_target = 13;
  if (cpu_target >= get_nprocs_conf())
    return -1;

  CPU_ZERO(&cpuset);
  CPU_SET(cpu_target, &cpuset);
  pthread_attr_init(&attr);
  pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);
  pthread_create(&t, &attr, [](void*) -> void* { return nullptr; }, nullptr);

  pthread_join(t, nullptr);
  pthread_attr_destroy(&attr);

  return 0;
}

我们可以询问有多少个内核可用。如果有可用的内核,我们可以将每个线程的关联掩码设置为在内核上运行 从 到 。N0N-1

现在,许多处理器都具有高性能和高效的内核。例如,i9-14900K 有 24 个核心(8 个性能核心和 16 个高效核心);8 个性能核心,每个核心能够运行 2 个超线程。

如何为性能核心配置线程关联性;还是效率核心?

C++ C 多线程 CPU 架构 关联性

评论

3赞 Pepijn Kramer 11/2/2023
一般来说,您应该能够让操作系统解决这个问题(至少新处理器有很多逻辑可以为您做到这一点)。但似乎已经有了一个答案:stackoverflow.com/questions/24645880/...指的是(eli.thegreenplace.net/2016/...)。一般来说,在 C++ 中,尽可能多地使用 std::thread(忘记 pthreads 的存在)
0赞 Red.Wave 11/2/2023
这基本上是一个 POSIX 问题。我想你应该期望在 C 中找到答案。所以标签需要修复,因为没有 C++ 特定的功能存在问题,也没有 - 我猜 - 在即将到来的答案中。
1赞 Peter Cordes 11/3/2023
@Red.Wave:C 和 C++ 是不同的语言,两者都不是另一种语言的子集。例如,C++ 缺少 VLA,并且不允许从 进行隐式转换。这被标记为 [c++],所以这是一个 C++ 问题。不过,它确实使用了 C++ 的类似 C 的子集,这通常是糟糕的风格。即使我要使用 pthread 亲和函数,我也会使用。void*std::thread
2赞 Red.Wave 11/3/2023
@PeterCordes 我不记得使用过“子集”一词。pthread 是一个 POSIX C API,这意味着 OP 要求的是同一 API 中的另一组函数。我想很明显 C++ std 不支持 cpu 亲和性或任何线程自定义。任何第三方 C++ 库都会自然地包装特定于平台的 C API 函数:因此,如果 OP 是可回答的,则 C API 中必须有一些 pthread 函数,这将再次是与 C 语言相关的答案。如果一切都是 C,那么标签也会如此。这会通知 C 社区回答;因为在这件事上,他们知道得更多。
0赞 John Bollinger 11/3/2023
如果这是一个你所指的独家意义上的POSIX问题,@Red.Wave,那么这难道不意味着人们应该期望在POSIX中找到答案吗?但实际上,它不是POSIX函数(这就是它所表示的),C和POSIX(或C++)都没有任何标准功能可以为程序提供区分具有不同特征的执行单元。pthread_attr_setaffinity_np_np

答:

1赞 John Bollinger 11/3/2023 #1

如何为性能核心配置线程关联性;还是效率核心?

C、C++ 或 POSIX 没有定义用于区分具有不同特征的执行单元的标准接口。事实上,它本身就是一个非标准的GNU扩展。*其他环境可能提供类似的接口,但在问题的通用性层面上 - 即不指定特定环境 - 主要答案是没有标准方法来控制程序在哪些执行单元上运行。pthread_attr_setaffinity_np()

第二个答案是,在大多数情况下,你不需要这样做。对于您正在谈论的 CPU 设计类型,一个关键的使能技术是内置逻辑,用于自动选择任何给定线程应该在哪些内核上运行。展望未来,我们也可以合理地预期,编译器将很快在生成代码方面做得更好,从而帮助此类 CPU 做好这项工作,并且操作系统内核将很快学会如何充分利用此类 CPU。只有当你有非常特殊的需求时,才有可能将时间和金钱投入到你所描述的那种手动核心亲和力管理中。

但是,如果您确实有这样的需求,并且我们可以安全地从您的 Glibc 依赖项中得出结论,您正在寻找特定于 Linux 的解决方案,那么这可能是解析以确定系统 CPU 内核的特征。然后使用该信息选择要为其设置关联性的核心。/proc/cpuinfo


*相关函数 sched_setaffinity() 也是如此。

评论

1赞 Peter Cordes 11/4/2023
我能想到的固定到 E 核或 P 核的主要用例是微基准测试,因此您可以分别测量这两种类型的内核。或者,也许是为了确保当某些对延迟敏感的任务唤醒时,P 内核尚未被占用。即使有备用的 P 核,甚至可能只在 E 核上运行一些后台SETI@home类型的工作负载,以优化能效而不是性能。(我认为你的回答是一个很好的平衡,既要实际回答问题,又不要求它证明它的存在是合理的,同时仍然指出你通常不应该这样做。