【问题标题】:How to designate a Process/Thread to a certain core in a multi-core environment?如何在多核环境中为某个核指定进程/线程?
【发布时间】:2013-02-28 04:15:13
【问题描述】:

我的意思是,在操作系统的实现中,什么机制可以完成这项工作?例如,在 Linux 内核中?或者,我们都知道有一些工具可以方便地实现这一点,比如 Windows 任务管理器,但内部机制是什么?

【问题讨论】:

  • 您是在询问如何以编程方式设置亲和力,或者在内核中如何实现亲和力?目前还不是很清楚。
  • 感谢关注。我的意思是如何在内核中实现亲和力。

标签: process operating-system multicore


【解决方案1】:

快速解答

在 Linux 中,您需要查看 sched_setaffinity() 或 pthread_setaffinity_np()。

更长的答案

您需要对核心亲和性相当小心(即将进程/线程指定给某个核心)。现代 CPU 和操作系统会做各种各样的事情,以使在一般情况下不必摆弄核心亲和力,如果您摆弄并弄错了,这些可能会开始对您不利。

例子

在双芯片 i7 平台上,它确实会变得相当复杂。在这样的平台上,超线程意味着 BIOS 报告 16 个内核,其中只有 8 个是真实的。将两个线程绑定到一个内核及其超线程的另一个自我很容易导致两个慢线程。

内存通常在两个芯片之间交错,一次 4kpage(另一种 BIOS 设置)。因此,将线程绑定到特定核心可以使其远离正在操作的数据;这会使两个芯片之间的 QPI 链接过载并减慢一切。顺便说一句,您也可以将内存分配给芯片,看看this。这是一个复杂的话题,但您可能也必须接受它。

一般而言,跨机器内核、芯片和 SIMM 的线程及其内存的最佳部署取决于每台 PC。例如,考虑一台机器中有两个 i7;最佳部署取决于插入了多少内存 SIMM。这些是操作系统非常清楚的事情,并且通常可以很好地移动线程以获得最佳性能。

您必须有一个非常特殊的环境,您会发现自己进行分发会更好。除非你有一个非常固定的硬件配置,否则你已经编写了你的​​应用程序,以便它在每次运行时为自己确定最佳部署。这是很多编程工作。

总结

简而言之,通常最好不要管它。

英特尔做了什么

让我们退后一步,看看英特尔当前的设计背后的理念是什么,其中存在两个或更多芯片。

英特尔决定,通常计算机在不同的数据集上同时执行许多不同的任务,线程和进程之间仅适度共享数据。这允许他们使用 QPI 合成一个 SMP 架构,将他们的 CPU 绑定到一个公共内存映射中(否则它将是严格的 NUMA,而不是 SMP)。在一般情况下,这会提供出色的性能。当然,AMD 早在几年前就得出了相同的结论,并使用 Hypertransport 来实现它。

重要的是,就应用程序和操作系统而言,它还提供了简单性,因为整台机器中的每个内核都可以看到整个内存,即使只是通过 QPI 间接地看到。

规则的例外情况

但是,如果应用程序的性质是由每个内核上的线程处理的海量数据集,那么 QPI 上的内存远程可能是一个问题。该架构必须保持所有 CPU 之间的缓存一致性,因此 QPI 链接最终可能会因内存访问和缓存一致性流量而受到影响。例如,在我使用的平台上,QPI 只有 19GB/s,而每个 CPU 的三个内存库都有 25GB/s。这可能在英特尔最新的芯片上有所改变。

在这种情况下,最好将这两个芯片视为 NUMA 架构。这可以通过分配数据集 NUMA 的两个副本来完成,这样每个 CPU 都有自己的副本。还可以让线程只处理本地内存。这减轻了 QPI 链路的负担。

围绕芯片的行为工作

如果要优化到这种程度,那么人们很快就会开始不喜欢现代 CPU 架构中内置的泛化。例如,缓存会假设要加载哪些数据、何时加载以及何时更新 RAM 和其他缓存。一般来说这很好,但有时人们知道得更好。

对我来说,最好的 CPU 是 Playstation 3 中使用的 Cell 处理器。在它的八个数学核心中,它没有缓存,所以没有缓存一致性,什么都没有。程序员全权负责让 DMA 引擎(我希望 Intel 包括)在正确的时间将数据移动到正确的位置,以便由正确的代码处理。或者可以将数据留在原处,然后将代码 DMA 到数据中。它非常复杂,需要大量的脑力,但如果做对了,您可以获得出色的数学性能(2005 年为 200GFLOP;领先英特尔数英里)。

关于哪种哲学是正确的?好吧,英特尔正在抨击 Core this 和 Xeon that,而 Cell 则垂死挣扎。事实证明,能够通过自己控制一切来获得最佳性能的程序员并不多。

【讨论】:

  • 非常感谢这两个接口和所附信息。 sched_setaffinity() 或 pthread_setaffinity_np() 的实现必须说明我在探索什么。
  • 至于操作系统内部的亲和性的实现,归结为调度程序为每个线程维护的数据块。其中包含诸如优先级、拥有进程、内存所有权等数据。每次调度程序确定线程已准备好运行(例如,信号量可用)时,它都会确定哪个内核不忙并在那里启动线程。设置亲和力是程序干预和控制该工作的一种手段。设置相同亲和力的两个程序会运行缓慢!
猜你喜欢
  • 2012-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-26
  • 1970-01-01
相关资源
最近更新 更多