sched_yield 标记为***热点
Posted
技术标签:
【中文标题】sched_yield 标记为***热点【英文标题】:sched_yield flagged as top hotspot 【发布时间】:2021-07-29 11:57:42 【问题描述】:在使用 Vtune 分析程序时,我看到 libc
函数 sched_yield
被标记为重要热点。
现在我看到这个函数大致负责上下文切换;粗略地说是因为第一次遇到这个函数,所以我的理解是它运行在OS调度器内部,为改变活动线程提供支持。
将sched_yield
作为主要热点对我的程序意味着什么?这是否意味着我创建了比我应该创建的更多的线程并且操作系统正在尝试处理连续的上下文切换?
对于这种情况有什么补救措施?是否可以求助于更集中的线程池来避免过度生成线程?
接下来我应该分析什么?在这种情况下是否有“典型”的后续步骤? Vtune 已经建议对“线程”进行分析。
【问题讨论】:
sched_yield
的行为很大程度上取决于操作系统。你运行的是什么操作系统?
sched_yield 的预期行为是让其他东西运行。从分析器的角度来看,调用函数和从函数返回之间的时间将被计为在函数内部花费的时间。所以也许它应该看起来像一个热点?
经验法则:使用sched_yield
的代码通常是错误的、非常错误的或深奥的魔法™。拿一根很长的杆子,不要碰它。
@AndreySemashev Debian 9
是否有一个调用图可以表明 std::thread 背后的特性是什么? Libc 似乎只在线程死亡时调用 yield。
【参考方案1】:
将
sched_yield
作为主要热点对我的程序意味着什么?
在 Linux 上,sched_yield
不一定会切换到另一个线程执行。如果没有准备好在同一 CPU 上运行的线程,内核不会重新调度调用线程。最后一部分很重要,因为内核不会在调用时在 CPU 之间重新调度准备好运行的线程。这是一个设计折衷,因为sched_yield
应该是对内核的低成本提示。
由于sched_yield
可能会立即返回而无需执行任何操作,因此您的代码可能会围绕此调用进行忙碌循环,这看起来像是您的个人资料中的热点。您的代码只是在sched_yield
周围循环很多次,而没有做太多其他事情。这种旋转会消耗大量 CPU 周期,这些周期可能会用于系统上运行的其他线程和应用程序。
对于这种情况有什么补救措施?
这在很大程度上取决于您的用例。当您愿意浪费一些 CPU 周期来换取更好的延迟时,使用sched_yield
可能是可以接受的。你必须意识到这个决定,即便如此,我还是建议对不同的解决方案进行基准测试,并使用适当的线程阻塞。 Linux 线程调度程序非常高效,因此阻塞和唤醒线程不像其他一些系统那样昂贵。
sched_yield
通常用于自定义自旋锁算法。我建议将这些替换为 pthread 组件,特别是 pthread_cond_t
,它允许正确阻塞和唤醒线程。如果您使用 C++,标准库中有等价物(例如std::condition_variable
)。在其他情况下,可能值得探索其他阻塞 API,例如 select
和 epoll。确切的解决方案取决于您的用例。
【讨论】:
以上是关于sched_yield 标记为***热点的主要内容,如果未能解决你的问题,请参考以下文章