c++ - 如何根据程序的计算需求自动将线程添加到池中?

标签 c++ multithreading threadpool

我们有一个 C++ 程序,根据用户配置它的方式,它可能受 CPU 限制或 IO 限制。为了与程序配置松散耦合,我想让我的线程池自动意识到程序何时会受益于更多线程(即 CPU 绑定(bind))。如果它意识到它何时受 I/O 限制并减少 worker 的数量,那就太好了,但这只是一个奖励(即,我会对自动增长而不会自动收缩的东西感到满意)。

我们使用 Boost,所以如果有什么可以帮助我们可以使用它。我意识到任何解决方案都可能是特定于平台的,因此我们主要对 Windows 和 Linux 感兴趣,其次是对 OS X 或任何其他 *nix。

最佳答案

简短回答:对 CPU 密集型操作和 IO 使用不同的固定大小线程池。除了池大小之外,事件线程数的进一步调节将由同步计算机和工作流的 IO 步骤的有界缓冲区(生产者/消费者)完成。

对于计算密集型和数据密集型问题,其中瓶颈是不同资源之间的移动目标(例如 CPU 与 IO),明确区分线程和线程可能很有用,特别是作为第一近似值:

  • 为使用更多 CPU 周期而创建的线程(“CPU 线程”)
  • 为处理异步 IO 操作而创建的线程(“IO 线程”)

更一般地说,线程应该根据它们需要的资源类型进行隔离。目标应该是确保单个线程不使用多个资源(例如,避免在同一线程中在读取数据和处理数据之间切换)。当线程使用多个资源时,它应该被拆分,并且两个生成的线程应该通过有界缓冲区同步。

通常情况下,CPU 线程的数量应该与系统上所有可用内核的指令流水线饱和所需的数量完全相同。为确保这一点,只需拥有一个“CPU 线程池”,其中包含许多专用于计算工作的线程。如果可以信任,那将是 boost::std::thread::hardware_concurrency()。当应用程序需要较少时,CPU 线程池中只会有未使用的线程。当它需要更多时,工作就会排队。您可以使用 c++11 std::async 而不是“CPU 线程池”,但您需要通过选择的同步工具(例如计数信号量)来实现线程节流机制。

除了“CPU线程池”之外,还可以有另一个线程池(或其他几个线程池)专用于异步IO操作。在您的情况下,似乎 IO 资源争用可能是一个问题。如果是这种情况(例如本地硬盘驱动器),则应仔细控制最大线程数(例如本地硬盘驱动器上最多 2 个读取线程和 2 个写入线程)。这在概念上与 CPU 线程相同,您应该有一个固定大小的线程池用于读取,另一个用于写入。不幸的是,可能没有任何好的原语可用于决定这些线程池的大小(如果您的 IO 模式非常规则,测量可能很简单)。如果资源争用不是问题(例如 NAS 或小型 HTTP 请求),那么 boost::asio 或 c++11 std::async 可能是更好的选择一个线程池;在这种情况下,线程节流可以完全留给有界缓冲区。

关于c++ - 如何根据程序的计算需求自动将线程添加到池中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29548687/

相关文章:

java - 如何以多线程方式调用不同类的相同方法

java - Java 5 中的 Lock 和 ReentrantLock 有什么区别?

c++ - 多维数组的划分

c++ - 如何使用 BOOST_FOREACH 枚举 BOOST_ENUM?

c++ - 在运行时检测Catch2中的特定标签匹配

c# - 是否可以使用 Monitor.Enter 获取正在等待的排队线程的计数?

c++ - 如何正确设计工作线程? (例如避免 sleep (1))

java - 在Java中使用Netty发送连续数据的最佳方式

python - 如何在发生错误时重新执行 ThreadPoolExecutor 中的函数?

c++ - 光线追踪三角形网格对象