jan*_*b04 65 c++ performance multithreading intel apple-m1
在谈论多线程时,线程似乎通常被视为平等——与主线程相同,但在它旁边运行。
然而,在某些新处理器上,例如Apple M1芯片和即将推出的 Intel Alder Lake系列,并非所有线程的性能都与这些芯片的性能相同,因为这些芯片具有独立的高性能内核和高效、速度较慢的内核。
这并不是说还没有诸如超线程之类的东西,但这似乎对性能有更大的影响。
有没有办法查询std::thread的属性并强制它们在 C++ 中运行的核心?
Bre*_*dan 60
如何区分 C++ 中的高性能和低性能内核/线程?
请理解,“线程”是硬件功能的抽象,并且超出您控制范围的东西(操作系统、内核的调度程序)负责创建和管理此抽象。“重要性”和性能提示是该抽象的一部分(通常以线程优先级的形式呈现)。
任何打破“线程”抽象的尝试(例如确定内核是低性能还是高性能内核)都是错误的。例如,在您发现自己在高性能内核上运行后,操作系统可能会立即将您的线程更改为低性能内核,从而导致您假设自己在高性能内核上运行,而实际上并非如此。
即使将您的线程固定到特定的内核(希望它始终使用高性能内核)也可能/会适得其反(导致您完成更少的工作,因为您阻止自己使用“比没有快“当高性能内核忙于做其他工作时,低性能内核)。
最大的问题是 C++std::thread在操作系统提供的“可能更好”的抽象之上创建了一个更糟糕的抽象 ( )。具体来说,无法使用std::thread;来设置、修改或获取线程优先级。因此,您无法控制(对于操作系统、调度程序)做出良好“负载与性能与电源管理”决策所必需的“性能提示”。
在谈论多线程时,通常似乎线程被视为平等
人们通常认为我们仍在使用 1960 年代的分时系统。别再听这些傻子了。现代系统不允许将 CPU 时间浪费在不重要的工作上,而更重要的工作在等待。有效使用线程优先级是一项基本的性能要求。其他一切(“负载与性能与电源管理”的决定)必然超出您的控制范围(在您使用的“线程”抽象的另一侧)。
eer*_*ika 23
有什么方法可以查询 std::thread 的属性并强制它们在 C++ 中运行的核心?
不。在 C++ 中没有用于此的标准 API。
特定于平台的 API 确实能够为软件线程指定特定的逻辑核心(或一组此类核心)。例如,GNU 有pthread_setaffinity_np.
请注意,这允许您为线程指定“核心 1”,但这不一定有助于获得“性能”核心,除非您知道这是哪个核心。要弄清楚这一点,您可能需要低于操作系统级别并进行特定于 CPU 的汇编编程。根据我的理解,在英特尔的情况下,您将使用增强型硬件反馈接口。
Yak*_*ont 19
不,C++ 标准库没有直接的方法来查询 CPU 的子类型,或声明您希望线程在特定 CPU 上运行。
但是std::thread(和jthread)确实有.native_handle(),在大多数平台上都可以让您这样做。
如果您知道您的 线程库实现std::thread,则可以使用它native_handle()来获取底层原语,然后使用底层线程库来完成这种低级工作。
当然,这将是完全不可移植的。
gna*_*729 13
iPhone、iPad 和较新的 Mac 具有高性能和低性能内核是有原因的。低性能内核允许在使用尽可能少的能量的同时完成一些合理的工作,从而使设备的电池持续更长时间。这些额外的内核不仅仅是为了好玩;如果你试图绕过它们,最终会给用户带来更糟糕的体验。
如果您使用 C++ 标准库来运行多个线程,操作系统将检测您在做什么,并采取相应的行动。如果你的任务在一个高性能核心上只需要 10ms,它就会被转移到一个低性能核心上;它足够快,可以节省电池寿命。如果您有多个线程使用 100% 的 CPU 时间,则将自动使用高性能内核(以及低性能内核)。如果您的电池电量不足,设备可以切换到所有低性能核心,这将使用您拥有的电池电量完成更多工作。
你真的应该考虑一下你想做什么。你应该把用户的需求放在你感知的需求之前。除此之外,Apple 建议为您的线程分配特定于操作系统的优先级,如果您做得对,这会改善行为。为线程赋予最高优先级以便获得更好的基准测试结果通常不是“做对了”。
您不能使用std::thread. 请参阅此处了解更多信息。我建议使用OpenMP、MPI 之类的框架,否则您将深入研究本机 Mac OS API 来选择要在其上执行线程的核心。