【问题标题】:Make sure that main thread run on it's own core alone确保主线程单独在它自己的核心上运行
【发布时间】:2016-05-02 18:54:10
【问题描述】:

我有一个主线程来做一些不那么繁重的工作,而且我正在创建工作线程来做非常繁重的工作。所有文档和示例都展示了如何创建数量等于std::thread::hardware_concurrency() 的硬件线程。但由于主线程已经存在,线程数变为std::thread::hardware_concurrency() + 1。例如:

  • 我的机器支持 2 个硬件线程。
  • 在主线程中,我创建了这 2 个线程,线程总数变为 3。
  • 一个带有主线程的内核完成它的工作加上(可能)工作线程的工作。

我当然不希望这样,因为 UI(在主线程中完成)由于延迟而变得没有响应。如果我创建std::thread::hardware_concurrency() - 1 线程会发生什么?它会保证主线程和唯一的主线程在单核上运行吗?如何查看?

P.S.:我正在使用某种池 - 我在程序启动时启动线程并在退出时停止。在执行过程中,所有工作线程都会无限循环while

【问题讨论】:

  • 您无法得到任何保证,即使您的线程数少于硬件支持的线程数。如果机器上正在运行其他程序怎么办?这取决于它实际运行线程的操作系统。您可以通过平台特定的行为获得一些改进。你的目标是什么平台?
  • 让操作系统决定什么是最好的有什么问题?为什么你认为你能够做出比它更好的决定?
  • 我使用的是 Windows 7/8/10。而且我认为我不能比 OS 做得更好,我只是希望我的程序运行顺畅。
  • @nikitablack 只需确保您没有在无限循环中忙于等待。如果你在等待工作,你应该使用条件变量。
  • 假设您没有在 UI 事件处理程序中做诸如等待/轮询之类的坏事,只需降低工作线程的优先级,以便 UI 在准备就绪时始终可以获取 CPU。 Prabindh 提出了这个建议,这是一个比搞乱核心亲和力更好、更简单的解决方案。

标签: c++ multithreading c++11


【解决方案1】:

正如其他人在 cmets 中所写的那样,您应该仔细考虑是否可以比操作系统做得更好。

话虽如此,在技术上是可行的:

  1. 使用native_handle 方法获取操作系统对线程的句柄。

  2. 请查阅您操作系统的文档以设置线程关联性。例如,使用 pthreads,你会想要pthread_set_affinity

这使您可以完全控制每个线程的运行位置。特别是,您可以为其中一个线程提供自己的核心。

请注意,这不是标准的一部分,因为它是不可移植的关卡。这可能是另一个暗示,它可能不是您正在寻找的东西。

【讨论】:

    【解决方案2】:

    否 - std::thread::hardware_concurrency() 只会提示您用于多线程的潜在内核数量。您可能对CPU Affinity Masks (Putting Threads on different CPUs) 感兴趣。这适用于您可以通过std::thread::native_handle (http://en.cppreference.com/w/cpp/thread/thread/native_handle) 访问的 pthread 级别

    【讨论】:

    • 提问者指出他们使用的是Windows。看起来您在该评论之前已回答,但也许您可以编辑指向 Windows 的某些类似功能的链接?
    【解决方案3】:

    根据您的操作系统,您可以获取线程的本机句柄,并使用 pthread_setschedparam() 控制它们的优先级,例如赋予工作线程低于主线程的优先级。这可以是 UI 问题的一种解决方案。一般来说,线程数不必与可用硬件内核数相匹配。

    【讨论】:

    • 这似乎是解决 OP 实际问题的唯一合理解决方案 - 只需降低工作线程的优先级,以便 UI 可以在需要时快速获取 CPU。对这个要求使用核心亲和力只是..不好。
    【解决方案4】:

    在某些情况下,您肯定希望能够完全控制并可靠地分析正在发生的事情。您使用的是 Windows,但作为示例,可以在多核机器上排除例如来自普通 Linux 操作系统调度程序的一个内核,并将该内核用于时间关键的硬实时任务。从本质上讲,您将拥有该内核并为其处理中断,从而实现接近硬实时响应时间和可预测性的东西。需要仔细的编程和分析,并且需要付出很大的努力。但如果做得好,将非常有吸引力。

    【讨论】:

    • 当“时间紧迫的硬实时任务”没有准备好,还有其他线程可以使用 CPU 时,这个“隔离”内核会做什么?只是坐在那里,闲着,停下来?
    • 是的,您专用一个核心,它不能用于其他尽力而为的任务。它将专门用于时间紧迫的任务,这些任务无法等待其余的操作系统/用户空间进程完成它们的工作。
    • 看不出它有多大帮助?当发生中断以使关键线程准备好时,它显然必须由其他内核之一处理。然后,该驱动程序必须中断空闲内核以使其再次执行操作。我能看到的唯一实质性收获是“关键”核心的 L1 缓存没有被其他线程污染。代价是系统的其余部分,包括驱动程序、通信堆栈等,失去了对一个内核的使用。在只有几个内核的系统上,或者与 L1 大小相比,线程不使用太多数据的系统上,这些收益可能不值得:(
    • @MartinJames:想法是将系统分为两组,一组由“普通”Linux内核处理,一组单独处理硬实时,并显式绑定实时对实时内核之一的敏感中断。有关更多详细信息,请尝试在 ENEA 上查找 Patrik Strömblad 撰写的“在嵌入式多核设备上实现实时 Linux”的副本。我在 2014 年 LinuxCon Europe 上得到了一份硬拷贝。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-26
    • 2019-03-09
    • 1970-01-01
    相关资源
    最近更新 更多