现代 C++ 中 STL 算法的执行策略

17 Mar 2025 | 5 分钟阅读

现代 C++ 中的标准模板库 (STL) 提供了广泛的算法,可在基本序列(包括向量、数组和列表)上运行。这些算法适用于不同的迭代器,并作为模板函数实现。这些算法以泛型编程的基本原理为基础构建,并广泛使用迭代器来抽象底层数据结构。

在 STL 算法的上下文中,执行策略描述了算法如何并行运行。这是在 C++17 中添加的,旨在使程序员能够在处理大数据集时在特定算法中使用并行性。以下是三种执行策略:

1. 顺序执行

此策略,即 std::execution::seq(顺序执行),确保了这一点。如果没有提供执行策略,则使用默认执行策略。它确保算法将在单个线程中运行,并且执行顺序将与输入迭代器的序列匹配。

语法

它具有以下语法:

示例

让我们举一个例子来说明 C++ 中的 **顺序执行**。

输出

Execution Policy of STL Algorithms in Modern C++

2. 标准::执行::并行 (并行执行)

此策略允许并行算法执行。是否使用线程、矢量化或任何其他并行化技术由实现决定;C++ 标准库不强制规定如何实现并行性。

语法

它具有以下语法:

示例

让我们举一个例子来说明 C++ 中的 **并行执行**。

输出

Execution Policy of STL Algorithms in Modern C++

**3. 并行非序列执行**,或 **std::execution::par_unseq**,是一种与 **std::execution::par** 类似的策略,但允许算法的矢量化。这意味着除了能够并行运行之外,算法还可以被矢量化,以提高单个迭代的性能。

语法

它具有以下语法:

示例

让我们举一个例子来说明 C++ 中的 **并行非序列执行**。

输出

Execution Policy of STL Algorithms in Modern C++

重要的是要记住,并非所有算法都可以从并行执行中受益,并且性能增益的大小将取决于算法的性质、数据的大小和硬件架构。在选择并行执行策略之前,应进行性能分析和测量,因为同步和其他因素可能导致并行执行引入开销。

示例

以下是一个简单的示例,演示了将 **std::execution::par** 与 **std::for_each** 结合使用:

输出

Execution Policy of STL Algorithms in Modern C++

说明

在此示例中,**lambda 函数** 并行应用于每个向量元素,使每个元素加倍。

执行策略之间的性能比较

可以使用一个简单的 C++ 程序来比较执行策略之间的性能差异,如下所示:

输出

Execution Policy of STL Algorithms in Modern C++

说明

如您所见,最快的执行策略是 unsequenced_policy,因为它进行了矢量化。接下来是 parallel_policy,然后是 parallel_unsequenced_policy。最终,您按照计划的顺序执行了执行技术。

重要的是要记住,并非每个算法都支持每个执行策略,并且根据选择的执行策略,某些算法的性能可能会有所不同。选择最适合任务要求和手头硬件的执行策略至关重要。您还应该测试各种策略,以找到特定任务的最佳策略。

现代 C++ 中 STL 算法执行策略的优点

由于 C++17 中在 STL 算法中添加了执行策略,开发人员现在可以管理特定算法的并行执行。此功能有几个优点:

  1. **并行性带来的性能提升:** 主要优点是使用并行性来提高多核处理器的性能。通过并行化一些算法以并发处理数据,可以更快地处理大型数据集。
  2. **增强的响应能力:** 处理大型数据集的应用程序可以从并行执行中受益,这可以增强响应能力。通过在多个线程或核心之间分配工作负载,算法可以更快地执行和响应。
  3. **可伸缩性:** 通过利用可用的硬件资源,执行策略使应用程序更具可伸缩性。随着处理器核心数量的增加,实现最佳性能越来越依赖于并行执行。
  4. **灵活性和可移植性:** 开发人员可以根据其应用程序的参数和算法的属性选择最佳执行策略。由于其适应性,可以进行优化以满足各种场景的独特要求。
  5. **细粒度控制:** 可以使用执行策略精细控制并行度。根据算法及其要求,开发人员可以在顺序执行 **(std::execution::seq)**、并行执行 **(std::execution::par)** 和并行非序列执行 **(std::execution::par_unseq)** 之间进行选择。
  6. **与现有代码的兼容性:** 默认情况下,对于使用 STL 算法但未定义执行策略的现有代码,顺序执行功能完美无缺。因此,保证了向后兼容性,开发人员可以根据需要逐步实现并行性。
  7. **性能分析:** 在执行策略之间切换的能力使性能分析和调优更容易。当开发人员可以测试各种策略并衡量它们对性能的影响时,定位瓶颈和优化关键代码段变得更简单。
  8. **简洁易读的代码:** 尽管并行执行的底层复杂性,但在 STL 算法中使用执行策略使开发人员能够简洁易读地表达并行性。算法调用仍然已知,并且行为由充当修改器的执行策略控制。

重要的是要记住,并非所有算法都同样受益于并行化,并且并行执行的效率因算法性质、大小和硬件架构等多个变量而异。建议使用性能分析和仔细考虑来确定在特定情况下执行策略的最佳使用。