草庐IT

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

coder 2023-11-13 原文

我的应用程序包含几个“自旋”的延迟关键线程,即从不阻塞。 这样的线程预计会占用一个 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 可能会有所帮助:

最佳答案

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

原因(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/

有关c++ - 我应该将 "bind" "spinning"线程连接到某个核心吗?的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  5. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  6. ruby - ruby 中的 TOPLEVEL_BINDING 是什么? - 2

    它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput

  7. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  8. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  9. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  10. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

随机推荐