gpt4 book ai didi

c++ - 我应该将 "bind" "spinning"线程连接到某个核心吗?

转载 作者:可可西里 更新时间:2023-11-01 15:53:27 25 4
gpt4 key购买 nike

我的应用程序包含几个“自旋”的延迟关键线程,即从不阻塞。这样的线程预计会占用一个 CPU 核心的 100%。然而,现代操作系统似乎经常将线程从一个内核转移到另一个内核。因此,例如,使用此 Windows 代码:

void Processor::ConnectionThread()
{
while (work)
{
Iterate();
}
}

我在任务管理器中没有看到“100% 占用”核心,整体系统负载为 36-40%。

但是如果我把它改成这样:

void Processor::ConnectionThread()
{
SetThreadAffinityMask(GetCurrentThread(), 2);
while (work)
{
Iterate();
}
}

然后我确实看到其中一个 CPU 内核被 100% 占用,整体系统负载也降低到 34-36%。

这是否意味着我应该倾向于 SetThreadAffinityMask 来“自旋”线程?如果我在这种情况下添加 SetThreadAffinityMask 来改善延迟?我还应该为“自旋”线程做些什么来改善延迟?

我正在将我的应用程序移植到 Linux,所以如果这很重要,这个问题更多地是关于 Linux 的。

upd 发现这张幻灯片表明将忙等待线程绑定(bind)到 CPU 可能会有所帮助:

enter image description here

最佳答案

如果这是代码中最重要的事情,那么在大多数情况下运行锁定到单个内核的线程可为该线程提供最佳延迟。

原因(R)是

  • 您的代码很可能在您的 iCache 中
  • 分支预测器已根据您的代码进行调整
  • 您的数据很可能已在您的 dCache 中准备就绪
  • TLB 指向您的代码和数据。

除非

  • 你运行的是 SMT 系统(例如超线程),在这种情况下,邪恶的双胞胎 将通过清除你的代码、将你的分支预测器调整到它的代码来“帮助”你并且它的数据会将您推出 dCache,您的 TLB 会受到其使用的影响。
    • 成本未知,每个缓存未命中数据的成本分别为 ~4ns、~15ns 和 ~75ns,这很快就会达到数千纳秒。
    • 它保存了上面提到的每个原因 R,它仍然存在。
    • 如果邪恶的双胞胎也只是旋转成本应该低得多。
  • 或者你允许中断你的核心,在这种情况下你会遇到同样的问题并且
    • 您的 TLB 已刷新
    • 您在 context switch 上进行了 1000ns-20000ns 的命中,如果驱动程序编程良好,大多数应该处于低端。
  • 或者您允许操作系统将您的进程切换出去,在这种情况下,您会遇到与中断相同的问题,只是处于范围的高端。
    • 关闭也可能导致线程暂停整个切片,因为它只能在一个(或两个)硬件线程上运行。
  • 或者您使用任何导致上下文切换的系统调用。
    • 根本没有磁盘 IO。
    • 仅异步 IO 其他。
  • 拥有比内核更多的事件(未暂停)线程会增加出现问题的可能性。

因此,如果您需要小于 100ns 的延迟来防止您的应用程序爆炸,您需要防止或减少 SMT、中断和任务切换对您的核心的影响。完美的解决方案是 Real time operating system with static scheduling .这几乎可以完美匹配您的目标,但如果您主要从事服务器和桌面编程,这将是一个全新的世界。

将线程锁定到单核的缺点是:

  • 它会消耗一些总吞吐量。
    • 如果上下文可以切换,一些线程可能会运行。
    • 但在这种情况下延迟更为重要。
  • 如果线程被上下文切换,它可能需要一些时间才能被安排一个或多个时间片,通常是 10-16 毫秒,这在这个应用程序中是 Not Acceptable 。
    • 将其锁定到核心及其 SMT 会减轻这个问题,但不会消除它。每增加一个核心都会减轻这个问题。
    • 将其优先级设置得更高会减轻问题,但不会消除它。
    • 使用 SCHED_FIFO 和最高优先级进行调度将防止大多数上下文切换,中断仍然会像某些系统调用一样导致临时切换。
    • 如果您有一个多 CPU 设置,您可以通过 cpuset 获得其中一个 CPU 的独占所有权。 .这可以防止其他应用程序使用它。

使用 pthread_setschedparam SCHED_FIFO 和最高优先级在 SU 中运行并将其锁定到核心,它的邪恶双胞胎应该确保所有这些的最佳延迟,只有实时操作系统才能消除所有上下文切换。

其他链接:

关于 interrupts 的讨论.

您的 Linux 可能会接受您调用 sched_setscheduler ,使用 SCHED_FIFO,但这要求您拥有自己的 PID 而不仅仅是 TID,或者您的线程是协作式多任务处理。
这可能并不理想,因为您的所有线程只会“自愿”切换,从而消除了内核对其进行调度的灵 active 。

100ns 中的进程间通信

关于c++ - 我应该将 "bind" "spinning"线程连接到某个核心吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25933912/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com