C++17并行`for_each`是否可以限制线程数?

17
我使用std::for_eachstd::execution::par对表示为结构向量的大型输入执行复杂计算。该计算不需要与硬件相关的任何延迟(例如网络或磁盘IO),它是“仅CPU”计算。对我来说,逻辑上讲,没有更多的操作系统线程比我们拥有的硬件线程更有意义;然而,Visual C++ 2019 平均创建50个线程,有时甚至会创建高达500个线程,即使只有12个硬件线程。

是否有办法通过std::for_eachstd::execution::par限制并行线程数到hardware_concurrency,或者唯一的方法是使用自定义代码和std::thread来创建合理的线程数?


http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0443r0.html#thread-pool-type - 但我认为这仍然是一个提案? - Caramiriel
1
即使将来这可能会成为标准,线程池的主要问题是它比<algorithm>头文件中的std::for_each和其他算法低级得多。std::execution::par背后的主要思想是使并行代码与顺序代码一样简单,并通过最小的代码和语义更改并行化现有算法。 - Vitalii
1
这个回答解决了你的问题吗?C++ STL(ExecutionPolicy)算法如何确定使用多少并行线程? - Jodocus
2个回答

13
“C++17的parallel for_each函数是否可以限制线程数量?” “不可以,至少在C++17中是不可以的。 然而,有一个提案executors即将成为标准,它基本上给了你影响高级STL算法接口执行上下文(位置和时间)的能力。”
thread_pool pool{ std::thread::hardware_concurrency() };
auto exec = pool.executor();
std::for_each(std::execution::par.on(exec), begin(data), end(data), some_operation);

到目前为止,您必须信任编译器供应商知道什么对整体性能最好,例如Visual Studio的开发人员state

我们实现中的调度由Windows系统线程池处理。线程池利用标准库无法使用的信息,例如系统上其他线程正在做什么,线程正在等待哪些内核资源等。它选择何时创建更多线程以及何时终止它们。它还与其他系统组件共享,包括不使用C ++ 的组件。

另一种选择是放弃仅依赖标准库并使用已经具有新提案的STL实现。


1
关于“对我来说,创建更多的操作系统线程没有意义,因为我们已经有了硬件线程”这一观点-这并不总是正确的:由于在CPU级别上密集使用流水线技术,存在大量的空闲周期,可以利用这些空闲时间让另一个线程进行一些处理。 因此,大多数不太缓存密集的算法将能够使用比本机线程更多的线程来提高性能。然而,最佳乘数取决于算法和具体的CPU,您需要进行个别基准测试。
例如,在我的一个筛选算法实现中,筛选阶段非常缓存密集,因此限制在本机核心内以保持在L1缓存范围内是非常有意义的。另一方面,计数阶段主要是算术运算,通过实验我确定,在12核心7900X CPU上,该阶段的最佳线程数是300个。

好的笔记,但或许更适合作为评论。 - joseph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接