x86 - 当线程可能切换内核时,如何正确使用 TSX-NI(HLE 和 RTM)?
问题描述
似乎英特尔的事务同步扩展 (TSX-NI) 在每个 CPU 的基础上工作。
这适用于_InterlockedXxx_HLE{Acquire,Release}
Hardware Lock Elision 函数 (HLE) 以及_xbegin
/ _xend
/etc。受限事务内存 (RTM) 功能。
在多核系统上使用这些功能的“正确”方式是什么?
鉴于他们的正确性保证,我认为我只需要担心这里的性能。
那么,考虑到线程总是有可能突然切换内核并因此这些指令可能需要退回到较慢的代码路径,我应该如何构建和编写我的代码以使我的代码具有最佳性能?
例如,我应该尝试显式设置线程 CPU 关联性,还是这是不好的做法?
还有什么我应该担心的吗?
解决方案
如果 CPU 在中间发生中断,则事务将中止。在保存 RIP 之前处理中止,因此中断-> CPU 迁移无法在此或另一个内核上恢复并在xend
不在事务内部的情况下运行。
因此不存在正确性问题。
将线程固定到内核可以帮助提高缓存局部性的性能,如果操作系统的进程调度程序会试图以对您的工作负载不理想的方式反弹线程。
但这对 TSX 没有特别的帮助:中断后在同一个内核上恢复并没有更好,因为事务已经中止。 该核心将拥有您需要的所有缓存行,可能在 L1d 中仍然很热,并希望仍处于 Exclusive 或 Modified 状态。
只有当中断使用户空间任务进入睡眠状态并且另一个内核上的内核决定获取该任务时,CPU 迁移才会发生。
在内核代码中,显然不要schedule()
在事务内部调用;并不是说它对正确性很重要,因为事务中止(可能)或执行最终或快速返回到该任务,我们到达xend
并成功提交作为单个大事务发生的所有事情(包括调度程序和可能另一个任务所做的所有事情)。
我实际上并没有玩过这个,但我认为没有任何理由期望 TSX 的线程关联性能考虑与非 TSX 有显着不同。