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

How do I automatically add threads to a pool based on the computational needs of the program?

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

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

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

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

  • 创建一个线程以使用更多 CPU 个周期("CPU thread")
  • 为处理异步 IO 操作而创建的线程([=3​​2=])

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

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

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