【发布时间】:2018-06-17 15:06:17
【问题描述】:
在 C++17 中引入了并行标准算法(使用 ExecutionPolicy 参数重载),其中定义了执行顺序、交错和并行化的严格规则,例如 ([algorithm.parallel.exec/3]):
在并行算法中元素访问函数的调用是通过一个执行策略对象来调用的 类型 execution::sequenced_policy 都发生在执行的调用线程中。 [注意:调用不是交错的;见 4.6。 ——尾注]
(current draft 也是一样)
问题是我找不到这些算法的旧的、非并行重载的任何此类要求。
问题:这是否意味着库实现者可以在引入 执行线程 术语的 C++11 之后实现 std::transform 和 std::generate使用 SIMD/多线程/其他(?)?有什么原因吗?
【问题讨论】:
-
只要程序的可观察行为没有改变,编译器和库实现就可以做任何事情。我不认为它们是使用多线程实现的,因为证明多线程不会改变程序的可观察行为是很困难的。另一方面,优化器通常会生成 SIMD 指令。任何你都不必担心的。
-
鉴于你可以
std::transform一个InputIterator在非并行重载,但并行至少需要ForwardIterator,我认为评估的顺序是固定的。 -
@Caleth 一个实现可以在编译时检查它是否被赋予了比要求更好的迭代器。理论上,标准允许它在 as-if-rule 下,而在实践中,除非明确要求,否则标准库实现不会为标准算法创建线程,因为这会不必要地分配全局资源,这是令人惊讶和糟糕的。
-
@nwp 但它可能有一个可用的此类线程池并使用它们。我担心的是是否有任何隐含保证任何此类线程的 thread local 变量将匹配调用线程的 thread local 状态?这两种方式都可能带来惊喜。
-
还有 [res.on.data.races]/8 "除非另有说明,C++ 标准库函数应仅在当前线程内执行所有操作,如果这些操作有对用户可见的效果 (4.7)。”这似乎排除了涉及任何用户定义实体的任何类型的幕后多线程。
标签: c++ c++11 language-lawyer c++17