C++ STL(ExecutionPolicy)算法如何确定要使用多少并行线程?

Sco*_*ley 19 c++ parallel-processing concurrency multithreading stl

C++ 17通过使用可选的ExecutionPolicy参数(作为第一个参数)升级了69个STL算法以支持并行性.例如.

std::sort(std::execution::par, begin(v), end(v));
Run Code Online (Sandbox Code Playgroud)

我怀疑C++ 17标准故意没有说明如何实现多线程算法,而是由图书馆作者决定什么是最好的(并允许他们改变主意,稍后).尽管如此,我仍然希望在高层次上理解在并行STL算法的实现中正在考虑哪些问题.

我心中的一些问题包括(但不限于!):

  • 如何(通过C++应用程序)使用的最大线程数与机器上的CPU和/或GPU核心数相关?
  • 每个算法使用的线程数有什么不同?(在每种情况下,每种算法是否总是使用相同数量的线程?)
  • 在其他线程上(在同一个应用程序中)是否考虑过其他并行STL调用?(例如,如果一个线程调用std :: for_each(par,...),它是否会使用更多/更少/相同的线程,具体取决于std :: sort(par,...)是否已经在某个其他线程上运行(s)?是否有线程池?)
  • 是否因为外部因素而考虑核心的繁忙程度?(例如,如果1个核心非常繁忙,比如分析SETI信号,那么C++应用程序会减少它使用的线程数吗?)
  • 有些算法只使用CPU内核吗?还是只有GPU核心?
  • 我怀疑实现会因库而不同(编译器到编译器?),甚至有关此的详细信息也会很有趣.

我意识到这些并行算法的目的是保护程序员不必担心这些细节.但是,任何能让我高度了解图书馆内部内容的精彩信息的信息都将受到赞赏.

oxu*_*xuf 7

到目前为止,这些问题大多数都无法通过标准来回答。但是,据我所知,您的问题包含两个概念:

C1。并行算法的约束

C2。执行算法

所有C ++ 17并行STL都是关于C1的:它对如何在并行计算中对指令和/或线程进行交织/转换设置了约束。另一方面,C2即将被标准化,关键字为executor(稍后会详细介绍)。

为C1,有3个标准策略(在std::execution::seqparpar_unseq),其对应于任务和指令并行的每一种组合。例如,当执行整数累加时,par_unseq可以使用,因为顺序并不重要。但是,对于浮点算术,其中加法不是关联的,更好的拟合seq至少是得到确定的结果。简而言之:策略对并行计算设置了约束,而这些约束可能会被智能编译器利用。

另一方面,一旦有了并行算法及其约束(并且可能经过一些优化/转换),executor它将找到执行该算法的方法。有默认的执行程序(例如,对于CPU),或者您可以创建自己的执行程序,然后,可以设置所有与线程数,工作量,处理单元等有关的配置。

到今天为止,C1是标准配置,但不是C2,因此,如果将C1与兼容的编译器一起使用,您将无法指定所需的执行配置文件,并且库实现将由您决定(也许通过扩展)。

因此,为解决您的问题:

(关于您的前5个问题)根据定义,为了允许可能的数据流转换,C ++ 17并行STL库不定义任何计算,仅定义数据相关性。所有这些问题都将得到(希望)回答executor,您可以在此处查看当前的建议。它看起来像:

executor = get_executor();
sort( std::execution::par.on(executor), vec.begin(), vec.end());
Run Code Online (Sandbox Code Playgroud)

即使您的某些问题已在该提案中定义,但我在这里讨论这些问题时并不感到有信心...但是我鼓励您阅读并提出自己的答案;)

(第六篇)那里有许多已经实现了类似概念的库(C ++ executor确实受到其中一些启发),AFAIK:hpx,Thrust或Boost.Compute。我不知道最后两个的实际实现方式,但是对于hpx,它们使用轻量级线程,您可以配置执行配置文件。同样,上面C ++ 17代码的预期(尚未标准化)语法基本上与hpx中的语法相同(受其启发)。

参考文献:

  1. C ++ 17并行算法及其超越 Bryce Adelstein lelbach
  2. Wong 的ISO C ++异构计算的未来
  3. Michael Wong 撰写的主题演讲C ++执行者将在今天的明天C ++中启用异构计算
  4. C ++执行者-Detlef Vollmann的长话