我的应用程序包含几个“旋转”的延迟关键线程,即从不阻塞。
这样的线程预计会 100% 占用一个 CPU 核心。然而,现代操作系统似乎经常将线程从一个核心转移到另一个核心。例如,使用以下 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发现这张幻灯片显示将忙等待线程绑定到 CPU 可能会有所帮助:
如果这是代码中最重要的事情,则在大多数情况下,运行锁定到单个核心的线程可以为该线程提供最佳延迟。
原因(R)是
- 您的代码可能位于您的 iCache 中
- 分支预测器根据您的代码进行调整
- 您的数据可能已在 dCache 中准备就绪
- TLB 指向您的代码和数据。
Unless
- Your running a SMT sytem (ex. hyperthreaded) in which case the evil twin will "help" you with by causing your code to be washed out, your branch predictors to be tuned to its code and its data will push your out of the dCache, your TLB is impacted by its use.
- 成本未知,每个缓存未命中数据的成本约为 4 纳秒、约 15 纳秒和约 75 纳秒,这很快就会达到数千纳秒。
- 它节省了上述每个 R 的原因,但仍然存在。
- If the 邪恶双胞胎也只是旋转,成本应该低得多。
- Or your allowing interrupts on your core, in which case you get the same problems and
- 你的TLB被刷新了
- 你受到 1000ns-20000ns 的打击上下文切换 http://blog.tsunanet.net/2010/11/how-long-does-it-take-to-make-context.html,如果驱动程序编程良好,大多数应该处于低端。
- Or you allow the OS to switch your process out, in which case you have the same problems as the interrupt, just in the hight end of the range.
- 切换出去还可能导致线程在整个片中暂停,因为它只能在一个(或两个)硬件线程上运行。
- Or you use any system calls that cause context switches.
- 拥有比核心更多的活动(非暂停)线程会增加出现问题的可能性。
因此,如果您需要低于 100 纳秒的延迟来防止应用程序爆炸,您需要防止或减轻 SMT、中断和任务切换对核心的影响。
完美的解决方案是具有静态调度的实时操作系统 http://en.wikipedia.org/wiki/RTLinux。这与您的目标几乎完美匹配,但如果您主要完成服务器和桌面编程,那么这将是一个新世界。
将线程锁定到单核的缺点是:
- It will cost some total throughput.
- 因为如果上下文可以切换,一些线程可能会运行。
- 但在这种情况下,延迟更为重要。
- If the thread gets context switched out it will take some time before it can be scheduled potentially one or more time slices, typically 10-16ms, which is unacceptable in this application.
- 将其锁定到核心及其 SMT 将减轻这个问题,但不能消除它。每个添加的核心都会减轻这个问题。
- 将其优先级设置得更高会减轻问题,但不能消除问题。
- 使用 SCHED_FIFO 和最高优先级进行调度将阻止大多数上下文切换,中断仍然会像某些系统调用一样导致临时切换。
- 如果您有一个多 cpu 设置,您可能能够通过以下方式独占其中一个 CPU 的所有权:cpuset http://man7.org/linux/man-pages/man7/cpuset.7.html。这会阻止其他应用程序使用它。
Using pthread_setschedparam http://man7.org/linux/man-pages/man3/pthread_setschedparam.3.html使用 SCHED_FIFO 和在 SU 中运行的最高优先级并将其锁定到核心及其邪恶双胞胎应该确保所有这些的最佳延迟,只有实时操作系统才能消除所有上下文切换。
其他链接:
讨论中断 https://stackoverflow.com/questions/10235011/how-are-interrupts-handled-on-smp.
你的 Linux 可能会接受你的调用sched_setscheduler http://linux.die.net/man/2/sched_setscheduler, using SCHED_FIFO,但这要求您拥有自己的 PID 而不仅仅是 TID,或者您的线程是协作多任务处理。
这可能并不理想,因为所有线程都只会“自愿”切换,从而消除了内核调度它的灵活性。
进程间通信在100ns http://tradexoft.wordpress.com/2012/10/22/how-to-move-data-between-threads-in-100-nanoseconds/
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)