当谈到多线程时,线程似乎被平等对待--就像主线程一样,只是在它旁边运行。
然而,在一些新的处理器上,如Apple“M”系列和即将推出的Intel Alder Lake系列,并非所有线程的性能都一样,因为这些芯片具有独立的高性能内核和高效率、较慢的内核。
这并不是说没有超线程之类的东西,但这似乎有一个更大的性能影响。
有没有办法查询std::thread
的属性,并强制它们在C++中的哪些内核上运行?
当谈到多线程时,线程似乎被平等对待--就像主线程一样,只是在它旁边运行。
然而,在一些新的处理器上,如Apple“M”系列和即将推出的Intel Alder Lake系列,并非所有线程的性能都一样,因为这些芯片具有独立的高性能内核和高效率、较慢的内核。
这并不是说没有超线程之类的东西,但这似乎有一个更大的性能影响。
有没有办法查询std::thread
的属性,并强制它们在C++中的哪些内核上运行?
6条答案
按热度按时间bvhaajcl1#
如何区分C中的高性能和低性能内核/线程?
请理解,“线程”是硬件功能的抽象概念,您无法控制的某些东西(操作系统、内核调度程序)负责创建和管理此抽象概念。“重要性”和性能提示是此抽象概念的一部分(通常以线程优先级的形式表示)。
任何试图打破“线程”抽象(例如确定核心是低性能核心还是高性能核心)的行为都是错误的。例如,当您发现自己正在高性能核心上运行时,操作系统可能会立即将您的线程更改为低性能核心,导致您误以为自己正在高性能核心上运行。
即使将线程固定到特定的内核(希望它始终使用高性能内核)也可能/将会适得其反(导致您完成的工作量减少,因为您阻止自己在高性能内核忙碌其他工作时使用“比没有快”的低性能内核)。
最大的问题是C在操作系统提供的“可能更好”的抽象之上创建了一个更差的抽象(
std::thread
)。具体地说,使用std::thread
无法设置、修改或获得线程优先级;因此,您无法控制“性能提示”,而这些提示(对于操作系统、调度程序)对于做出良好的“负载、性能和电源管理”决策是必要的。在讨论多线程时,似乎线程通常被平等对待
通常人们认为我们还在使用20世纪60年代的分时系统。不要再听这些傻瓜的话了。**现代系统不允许CPU时间浪费在不重要的工作上,而更重要的工作则在等待。有效地使用线程优先级是一项基本的性能要求。**其他一切(“负载、性能和电源管理”决策)必然超出您的控制范围(在您使用的“线程”抽象的另一端)。
bihw5rsg2#
有没有办法查询std::thread的属性,并强制它们在C中的哪些内核上运行?
否。C中没有用于此操作的标准API。
特定于平台的API确实有能力为软件线程指定一个特定的逻辑核(或一组这样的核),例如GNU有
pthread_setaffinity_np
。注意,这允许你为你的线程指定“核心1”,但这并不一定有助于获得“性能”核心,除非你知道那是哪个核心。要弄清楚,你可能需要进入操作系统级别以下,进入CPU特定的汇编编程。在英特尔的情况下,据我所知,你会使用增强的硬件反馈接口。
lb3vh1jj3#
不,C++标准库没有直接的方法来查询CPU的子类型,或者您希望线程在特定CPU上运行的状态。
但是
std::thread
(和jthread
)确实有.native_handle()
,在大多数平台上都会让你这么做。如果您知道
std::thread
的线程库实现,则可以使用native_handle()
来获取底层原语,然后使用底层线程库来完成此类低级工作。当然,这将是完全不可携带的。
z9smfwbn4#
iPhone、iPad和较新的Mac电脑都有高性能和低性能的内核,这是有原因的。低性能内核允许在使用尽可能少的能量的情况下完成一些合理的工作量,使设备的电池使用时间更长。这些额外的内核不仅仅是为了好玩;如果你试图绕过它们,你最终会给用户带来糟糕得多的体验。
如果你使用C++标准库来运行多线程,操作系统会检测到你在做什么,并采取相应的行动,如果你的任务在高性能内核上只需要10 ms,它会被移到低性能内核上;它的速度足够快,并节省电池寿命。如果您有多个线程使用100%的CPU时间,高性能核心将自动使用(加上低性能核心以及)。如果您的电池电量不足,设备可以切换到所有低性能核心,这将获得更多的工作完成 * 与电池电量 *。
你真的应该想想你想做什么。你应该把用户的需求放在你感知到的需求之前。除此之外,苹果建议为你的线程分配特定于操作系统的优先级,如果你做得对,这会改善你的行为。给一个线程最高的优先级,这样你就可以得到更好的基准测试结果,通常不是“做得对”。
vc6uscn95#
使用
std::thread
时,您无法选择线程将在哪个内核上运行。有关详细信息,请参阅here。我建议使用OpenMP、MPI之类的框架,否则您将不得不深入研究select the core for your thread to execute on.的原生MacOS APIvql8enpb6#
macOS为任务、任务队列和运行循环以及线程提供了“服务质量”的概念。如果您使用libdispatch/GCD,则队列优先级也会Map到QoS。This article详细描述了QoS系统。
使用macOS pthreads接口,您可以在创建线程之前设置线程QoS,查询线程的QoS,或使用pthread/qos.h中的不可移植函数临时覆盖线程的QoS级别(但在查询函数中不可见
这个系统并不保证线程将如何被调度,但是可以用来给调度器一个提示。
我不知道有什么方法可以在其他系统上获得类似的接口,但这并不意味着它们不存在。我想随着这些混合CPU变得越来越普遍,它们会得到更广泛的讨论。
编辑:英特尔提供了here信息,关于如何查询这些信息,为他们的混合处理器在Windows和当前的CPU使用cpuid,还没有机会玩这个虽然。