当前位置: 首页 > news >正文

windows C++-并行编程-并行算法(三)-分区工作

并行模式库 (PPL) 提供了对数据集合并行地执行工作的算法。这些算法类似于 C++ 标准库提供的算法。并行算法由并发运行时中的现有功能组成。

若要对数据源操作进行并行化,一个必要步骤是将源分区为可由多个线程同时访问的多个部分。 分区程序将指定并行算法应如何在线程之间对范围进行分区。 如本文档前面所述,PPL 使用的是默认分区机制,该默认分区机制创建初始工作负荷并在工作负荷不平衡时使用工作窃取算法和范围窃取来平衡这些分区。 例如,当某个循环迭代完成一个迭代范围时,运行时会将其他线程的工作重新分配给该线程。 但是,在某些方案中,你可能希望指定另一个更适用于你的问题的分区机制。

parallel_for、parallel_for_each 和 parallel_transform 算法提供采用一个附加参数 _Partitioner 的重载版本。 此参数定义了用于划分工作的分区程序类型。 以下是 PPL 定义的分区程序种类:

concurrency::affinity_partitioner
将工作划分为一个固定数量的范围(通常是可用于在循环中工作的辅助线程的数量)。 此分区程序类型与 static_partitioner 类似,但通过将范围映射到辅助线程的方式改善了缓存的关联。 当在相同数据集中多次执行一个循环(例如一个循环内的循环)且数据适合缓存时,此分区程序类型可提高性能。 此分区程序不完全参与取消。 它也不使用协作停滞语义,因此不能与具有前向依赖关系的并行循环一起使用。

concurrency::auto_partitioner
将工作划分为一个初始数量的范围(通常是可用于在循环中工作的辅助线程的数量)。 当您不调用采用 _Partitioner 参数的重载的并行算法时,运行时默认使用此类型。 每个范围可以划分为子范围,从而实现负载平衡。 当一个工作范围完成时,运行时会将其他线程工作的子范围重新分配给该线程。 如果您的工作负荷不在另外一个类别下或者您需要完全支持取消或协作停滞,请使用该分区程序。

concurrency::simple_partitioner
将工作划分到范围中,使每个范围至少拥有给定区块大小所指定的迭代的数目。 此分区程序类型加入了负载平衡;然而,运行时未将范围划分为子范围。 对于每个辅助,运行时将在 _Chunk_size 迭代完成后检查取消情况并执行负载平衡。

concurrency::static_partitioner
将工作划分为一个固定数量的范围(通常是可用于在循环中工作的辅助线程的数量)。 此分区程序类型可以提高性能,因为它不使用工作窃取,开销较小。 当一个并行循环的每次迭代执行固定和统一数量的工作而且您不需要支持取消或前向协作停滞时,请使用此分区程序类型。

parallel_for_each 和 parallel_transform 算法仅支持为静态、简单和关联分区程序使用随机访问迭代器(如 std::vector)的容器。 采用双向和向前迭代器的容器的使用会导致编译时错误。 默认分区程序 auto_partitioner 支持所有这三种迭代器类型。

通常,除 affinity_partitioner 外,这些分区程序的使用方式相同。 大多数分区程序类型不会维持状态,而且不会由运行时进行修改。 因此,如下例所示,您可以在调用站点创建这些分区程序对象。

// static-partitioner.cpp
// compile with: /EHsc
#include <ppl.h>using namespace concurrency;void DoWork(int n)
{// TODO: Perform a fixed amount of work...
}int wmain()
{// Use a static partitioner to perform a fixed amount of parallel work.parallel_for(0, 100000, [](int n) {DoWork(n);}, static_partitioner());
}

但是,必须将 affinity_partitioner 对象作为非 const 左值引用传递,以便算法可以存储状态,以供未来循环重用。 下面的示例演示对数据集多次并行执行相同操作的基本应用程序。 因为数组有可能适合缓存,使用 affinity_partitioner 可以提高性能。

// affinity-partitioner.cpp
// compile with: /EHsc
#include <ppl.h>
#include <array>using namespace concurrency;
using namespace std;int wmain()
{// Create an array and fill it with zeroes.array<unsigned char, 8 * 1024> data;data.fill(0);// Use an affinity partitioner to perform parallel work on data// that is likely to remain in cache.// We use the same affinitiy partitioner throughout so that the // runtime can schedule work to occur at the same location for each // iteration of the outer loop.affinity_partitioner ap;for (int i = 0; i < 100000; i++){parallel_for_each(begin(data), end(data), [](unsigned char& c){c++;}, ap);}
}

在修改依赖于协作停滞语义的现有代码以使用 static_partitioner 或 affinity_partitioner 时应谨慎。 这些分区程序类型不使用负载平衡或范围窃取,因此可能会更改应用程序的行为。

确定在任何给定方案中是否使用分区程序的最佳方式是:体验并度量操作在有代表性的负载和计算机配置下要花多长时间完成。 例如,如果是只有几个内核的多核计算机,静态分区可以让速度显著提升;但如果是内核相对较多的计算机,静态分区可能会导致速度降低。

http://www.lryc.cn/news/437419.html

相关文章:

  • 下载 llama2-7b-hf 全流程【小白踩坑记录】
  • Codeforces practice C++ 2024/9/11 - 2024/9/13
  • RabbitMQ创建交换机和队列——配置类 注解
  • proteus+51单片机+AD/DA学习5
  • 【Python机器学习】长短期记忆网络(LSTM)
  • 【Go】使用Goland创建第一个Go项目
  • STM32学习笔记(一、使用DAP仿真器下载程序)
  • 储能运维管理云平台解决方案EMS能量管理系统
  • 网络药理学:16、速通流程版
  • P2515 [HAOI2010] 软件安装
  • 51单片机快速入门之定时器和计数器
  • 【计算机网络 - 基础问题】每日 3 题(一)
  • Unity全面取消Runtime费用 安装游戏不再收版费
  • IDEA测试类启动报 “java: 常量字符串过长” 解决办法
  • 计算机科学基础 -- 访存单元
  • Linux压缩、解压缩、查看压缩内容详解使用(tar、gzip、bzip2、xz、jar、war、aar)
  • StreamReader 和 StreamWriter提供自动处理字符编码的功能
  • Gitlab备份、迁移、恢复和升级(Gitlab Backup, migration, recovery, and upgrade)
  • MySQL:INSERT command denied to user
  • 【Android安全】Ubuntu 16.04安装GDB和GEF
  • ISO 21434与网络安全管理系统(CSMS)的协同作用
  • Vue 67 vuex 四个map方法的使用
  • Unity自带脚本之GameObject脚本
  • 软件测试面试题-自测
  • 深度学习-神经网络
  • Redis - 集群篇 - 集群模式
  • Robot Operating System——线速度和角速度
  • 量化投资策略_因子打分选股的案例实现
  • 架构师知识梳理(七):软件工程-工程管理与开发模型
  • bp的模块被隐藏了