【问题标题】:Threadpool - CPU usage?线程池 - CPU 使用率?
【发布时间】:2018-08-02 03:18:54
【问题描述】:

我正在开发一个 Windows C++ 应用程序。我们使用 boost 库。我的应用程序中有一个操作可以并行化以在多个线程上运行。线程数每次取决于操作参数,并且可能很大(比如 50 或 70)。我不想产生尽可能多的线程,因为这是应用程序对其他操作无响应的风险(因为所有处理器都可能被占用)。我怎样才能确保我不会造成我所描述的情况?线程池有帮助吗?如果有,如何帮助?

【问题讨论】:

  • 如果您认为创建 50 个线程是一个好主意,那么,是的,非常支持线程池。它内置在操作系统中,您会喜欢 SetThreadpoolThreadMaximum()。

标签: windows multithreading c++11 boost threadpool


【解决方案1】:

您可以将std::async 与默认启动策略一起使用。但是,这与 线程池 不同。

在 OpenMP 中,您可以设置固定数量的线程,然后使用 OpenMP tasks。不幸的是,C++11 中没有这样的选项。标准说,可以推迟选择是在新线程中异步调用函数还是在对相应std::future 对象调用waitget 的线程中同步调用该函数,但是,仍然a选择异步调用时,必须创建新线程

【讨论】:

  • 这并不能真正回答问题。 Op 没有使用 OpenMP,正如您自己指出的那样,std::async 不是解决此问题的可行解决方案(至少在我们获得 C++ 执行程序之前不会)。
  • @ComicSansMS 同意,应该是评论。
【解决方案2】:

只需创建一个线程池,例如我在这里发布的boost thread throwing exception "thread_resource_error: resource temporarily unavailable"

这里还有两种口味c++ work queues with blocking(一种使用 Asio,一种仅使用 C++11)

【讨论】:

    【解决方案3】:

    现代硬件上的 70 个线程可以轻松处理,而不会对系统性能产生任何明显影响。线程创建时间、内存使用、调度和上下文切换开销可能是一个问题,但我们不知道在您的特定情况下这是否是一个问题。

    如果创建 70 个线程不是一个选项,请考虑使用 OpenMP(所有主要编译器都支持),因为它是一种非常简单且通常非常有效的解决方案:

    #pragma omp parallel for
    for(int i = 1; i < 100; ++i)
    {
       do_task(i);
    }
    

    它使用底层的线程池。

    如果由于某些原因 OpenMP 不可接受,您可以使用显式线程池。它可以是“自制”线程池(不推荐),或者来自@sehe 的答案,或者由操作系统提供的线程池(正如@Hans Passant 在他的评论中提到的那样),或者来自第 3 方库(例如英特尔线程构建模块)。

    是的,线程池有助于提高响应能力,尽管默认情况下典型的线程池实现会创建线程数 == 逻辑 CPU 内核数。这意味着您的所有核心都可能忙于工作,这不一定是问题。 Windows 使用抢占式多线程。这意味着它可以处理比 CPU 数量多得多的线程数,并且仍然具有响应性。

    线程池可以提供帮助,因为不可能同时执行多于您拥有的逻辑 CPU 内核数量的任务。由于更好地使用缓存和减少上下文切换次数,线程池可以更高效。或者因为可以使用相同的线程多次执行您的操作。要确定了解您的表现。

    【讨论】:

    • 谢谢@Andriy!我正在考虑使用 OpenMP。如果某些操作不应该基于某些条件继续完整操作,我该怎么办?我如何返回?
    • 我打算像您在代码中提到的那样调用一个函数(它会进行一些广泛的计算,或者在某些情况下我想返回时不会)。当我尝试编写一个简单的程序来查看 OpenMP 的工作原理时,它并没有在 openmp 并行块内通过返回进行编译,但是当我让 openmp 的并行块调用一个函数并从中返回时,它可以工作。为什么我不能在两者之间休息/返回?另外,顺便说一句,使用 OpenMP 有哪些问题/缺点?
    • @user7795930:最好在线搜索 OpenMP 讨论,因为 cmets 不适合这个。从parallel for 重新返回:我想这是不可能的,因为它是 parallel for,因此不会在每次迭代时检查循环条件,以后的迭代可能已经在运行。检查这个answer
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多