微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何区分 C++ 中的高性能和低性能内核/线程?

如何解决如何区分 C++ 中的高性能和低性能内核/线程?

在谈论多线程时,线程似乎通常被视为平等——与主线程相同,但在主线程旁边运行。

但是,在某些新处理器上,例如 Apple M1 芯片和即将推出的英特尔 Alder Lake 系列,并非所有线程的性能都与这些芯片的性能相同,因为这些芯片具有独立的高性能内核和高效率,较慢的内核。

这并不是说还没有超线程之类的东西,但这似乎对性能有更大的影响。

有没有办法查询 std::thread属性并强制它们在 C++ 中运行的核心?

解决方法

如何区分 C++ 中高性能和低性能的内核/线程?

请理解,“线程”是硬件功能的抽象,而您无法控制的东西(操作系统、内核的调度程序)负责创建和管理此抽象。 “重要性”和性能提示是该抽象的一部分(通常以线程优先级的形式呈现)。

任何打破“线程”抽象的尝试(例如,确定内核是低性能还是高性能内核)都是误入歧途的。例如。在您发现自己在高性能内核上运行后,操作系统可能会立即将您的线程更改为低性能内核,从而导致您认为自己运行的是高性能内核,而实际上并非如此。

即使将您的线程固定到特定内核(希望它始终使用高性能内核)也可能/会适得其反(导致您完成更少的工作,因为您已阻止自己使用“当高性能核心忙于做其他工作时,比什么都快”的低性能核心)。

最大的问题是 C++ 在操作系统提供的“可能更好”的抽象之上创建了一个更糟糕的抽象 (std::thread)。具体来说,无法使用 std::thread 设置、修改或获取线程优先级;因此,您无法控制(对于操作系统、调度程序)做出良好“负载、性能、电源管理”决策所必需的“性能提示”。

在谈论多线程时,似乎线程被平等对待

人们通常认为我们仍在使用 1960 年代的分时系统。别再听这些傻子了。 现代系统不允许将 CPU 时间浪费在不重要的工作上,而更重要的工作在等待。有效使用线程优先级是一项基本的性能要求。 其他一切(“负载、性能、电源管理”决策)必然超出您的控制(在“线程”抽象的另一侧,您正在使用)。

,

有没有办法查询 std::thread 的属性并强制它们在 C++ 中运行的核心?

没有。 C++ 中没有用于此的标准 API。

特定于平台的 API 确实能够为软件线程指定特定的逻辑核心(或一组此类核心)。例如,GNU 有 pthread_setaffinity_np

请注意,这允许您为线程指定“核心 1”,但这不一定有助于获得“性能”核心,除非您知道这是哪个核心。要弄清楚这一点,您可能需要低于操作系统级别并进行特定于 CPU 的汇编编程。据我了解,就英特尔而言,您将使用增强型硬件反馈接口。

,

不,C++ 标准库没有直接的方法来查询 CPU 的子类型,或声明您希望线程在特定 CPU 上运行。

但是 std::thread(和 jthread)确实有 .native_handle(),在大多数平台上都可以让您这样做。

如果您知道 std::thread 的线程库实现,则可以使用 native_handle() 获取底层原语,然后使用底层线程库来完成此类低级工作。

当然,这将是完全不可移植的。

,

iPhone、iPad 和较新的 Mac 具有高性能和低性能内核是有原因的。低性能内核允许在使用尽可能少的能量的同时完成一些合理的工作,从而使设备的电池持续更长时间。这些额外的内核不仅仅是为了好玩;如果你试图绕过它们,最终会给用户带来更糟糕的体验。

如果您使用 C++ 标准库来运行多个线程,操作系统将检测您在做什么,并采取相应的行动。如果你的任务在一个高性能核心上只需要 10ms,它就会被转移到一个低性能核心上;它足够快,可以节省电池寿命。如果您有多个线程使用 100% 的 CPU 时间,则将自动使用高性能内核(以及低性能内核)。如果您的电池电量不足,设备可以切换到所有低性能核心,这将使用您拥有的电池电量来完成更多工作

你真的应该考虑一下你想做什么。你应该把用户的需求放在你感知的需求之前。除此之外,Apple 建议为您的线程分配特定于操作系统的优先级,如果您做得对,这会改善行为。为线程赋予最高优先级以便获得更好的基准测试结果通常不是“做对”。

,

您不能使用 std::thread 选择线程将在物理上运行的内核。请参阅 here 了解更多信息。我建议使用 OpenMPMPI 之类的框架,否则您将深入研究原生 Mac OS API 以 select the core for your thread to execute on.

,

低性能内核使设备能够在使用最少能源的情况下完成一些工作。这使其持续时间更长。这些核心不是为了娱乐;它们会使用户的体验变得更糟。

C++ standard library 允许您运行多个线程。这将允许操作系统检测您的操作并采取适当的操作。如果您的任务在高性能内核上花费的时间少于 10 毫秒,操作系统会将其移至性能较低的内核。这样更快、更有效。

使用 100% CPU 时间的多个线程将自动被高性能内核(以及任何低性能内核)使用。如果电池电量不足,设备可以切换到所有低性能核心。这将允许设备执行更多操作。

考虑您的目标很重要。您感知的需求应该放在用户的需求之前。 Apple 还建议您为线程分配特定于操作系统的优先级。如果正确完成,这会改善行为。为获得更好的基准测试结果而赋予线程最高优先级的情况并不常见。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。