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

C++17并行化加速STL算法——std::execution

C++17 并行化STL算法

文章目录

  • C++17 并行化STL算法
    • 概念
      • 环境准备
      • 工具类
    • 并行算法 - 使用
    • 并行算法 - 执行策略
      • 总览
      • 选择标准
      • 详细介绍
        • 顺序执行 seq
        • 并行化顺序执行 par
        • 并行化乱序执行 par_unseq
    • 并行算法 - 异常处理
    • 可以不使用并行算法
    • 并行算法 - 限制
    • 并行算法有哪些
      • 原有算法
      • 17引入新算法

概念

为了从现代的多核体系中受益,C++17标准库引入了并行 STL算法,允许使用多个线程并行处理元素。

C++17为许多算法扩展了一个新的参数来指明是否要并行运行算法。并且新增了一些专为并行编程补充的新算法。

环境准备

并行算法在 linux上使用 gcc 或者 clang进行编译,需要

  1. 安装 tbb库—— 线程构建模块 (TBB) Thread Building Blocks
  2. 链接时指定-ltbb选项

否则:

tbb链接结果
安装指定-ltbb选项可正常使用并行算法
安装未指定编译错误
未安装指定编译错误
未安装未指定正常编译,但并行算法会串行化,变得和串行算法一样
# 编译选项
g++ ‐std=c++17 ‐ltbb main.cpp ‐o a.out

工具类

有时需要计时器来测量算法的速度。因此,引入一个简单的辅助类。

初始化一个计时器,提供 printDiff()来打印出消耗的毫秒数 并 重新初始化计时器

#include <iostream>
#include <string>
#include <chrono>
/********************************************
* timer to print elapsed time
********************************************/
class Timer {
private:std::chrono::steady_clock::time_point last;
public:Timer() : last{std::chrono::steady_clock::now()} {}void printDiff(const std::string& msg = "Timer diff: ") {auto now{std::chrono::steady_clock::now()};std::chrono::duration<double, std::milli> diff{now ‐ last};std::cout << msg << diff.count() << "ms\n";last = std::chrono::steady_clock::now();}
};

并行算法 - 使用

怎么让现有算法并行运行和使用新的并行算法

  • 包含头文件 <execution>
#include <execution> 
  • C++17之后,一般来说可以向并行 STL算法传递不同的 执行策略 (execution policies) 作为第一个参数。

    • cpprefrence上看看STL算法支不支持,一般是:添加执行策略到第一个参数即可。例如,std::execution::par

    • 使用参数 传递/修改 执行策略 的好处:可在运行时更改策略时(顺序执行/并行执行),不需要再修改调用方式。

所有的并行算法要求迭代器至少是前向迭代器。

#include <execution> // for 执行策略
#include <algorithm>std::vector<std::string> coll {"a", "b", "c"};sort(coll.begin(), coll.end());
sort(std::execution::seq, coll.begin(), coll.end());
sort(std::execution::par, coll.begin(), coll.end());
sort(std::execution::par_unseq, coll.begin(), coll.end());// 并行计算平方根
for_each(std::execution::par,coll.begin(), coll.end(),[] (auto& val) {val.sqrt = std::sqrt(val.value);});

并行算法 - 执行策略

总览

以下执行策略,分别是定义在 namespace std中的新类(sequenced_policyparallel_policyparallel_unsequenced_policy)的 constexpr对象。

执行策略含义
std::execution::seq顺序执行
std::execution::par并行化顺序执行
std::execution::par_unseq并行化乱序(矢量化)执行

标准库提供了新的类型特征 std::is_execution_policy<>,在泛型编程中检查模板参数是否是执行策略。

并行化乱序执行需要编译器/硬件的特殊支持,从而检测如何矢量化。

非并行化/并行化

  1. 并行化——多个线程执行
  2. 非并行化——单一线程

顺序、乱序

  1. 乱序:允许矢量化执行,不保证顺序地对元素执行操作。

    即存在可能:

    • 某个线程在执行完某一个元素的处理之前可能会切换到其他的元素。

    • 某个线程先执行多个元素的第一步处理,再回过头来对这些元素执行下一步处理。

  2. 顺序:不允许矢量化执行,顺序地对元素执行操作

    当某个线程对新的元素进行操作之前,它会先处理完它之前处理过的其他元素。

选择标准

benchmark测试结果,主要依赖于硬件、使用的 C++编译器、使用的 C++库(并行算法实际运行的方式是实现特定的)

没有通用的方法来判断什么场景什么时间值得使用并行算法。不能说多线程就一定比顺序执行好:启动和控制多线程也会消耗时间

理论上讲,如下判断依据可以作为参考:

  • 简单算法(每个元素计算耗时短),元素数量少。并行执行永远会更慢建议顺序执行 std::execution::seq 或 默认版本。

  • 复杂算法(每个元素计算耗时长),元素数量多。适合使用并行算法

    • 处理过程需要独立于其他元素的处理 —— 并行化顺序执行 std::execution::par
    • 处理过程不需要独立于其他元素的处理 —— 并行化乱序执行 std::execution::par_unseq

详细介绍

顺序执行 seq

std::execution::seq 指定顺序执行

  • 策略本身:

    • 单一线程执行
    • 单个线程对所有元素逐个执行操作。不允许矢量化执行,顺序地对元素执行操作——当某个线程对新的元素进行操作之前,它会先处理完它之前处理过的其他元素。
  • 与非并行化版本进行对比

    • 实际上,该策略非常类似不接受执行策略参数的非并行化版本
    • 但多一些约束条件:例如 for_each()不能返回值,所有的迭代器必须至少是前向迭代器
  • 提供该策略的目的:

    • 可只修改一个参数来要求顺序执行,而不是换用一个签名不同的函数。
并行化顺序执行 par

std::execution::par 指定并行化顺序执行

  • 策略本身:

    • 多个线程执行
    • 顺序执行:允许矢量化
  • 提供该策略的目的:

    • 比非并行化顺序执行,可能要快一些

    • 避免在以下情况中出现死锁或其它bug(与 par_unseq不同)

      执行了某个元素的第一步处理后必须在执行另一个元素的第一步处理之前执行这个元素接下来的处理步骤。

并行化乱序执行 par_unseq

std::execution::par_unseq 指定并行化乱序执行

  • 策略本身:
    • 多个线程执行
    • 乱序执行:允许矢量化
  • 提供该策略的目的:
    • 比非矢量化 顺序执行,可能要快一些

并行化乱序执行需要编译器/硬件的特殊支持来检测哪些操作如何矢量化。

并行算法 - 异常处理

当指定了执行策略后:

  • 处理元素的函数,因未捕获的异常而退出时,会调用 std::terminate()

  • 注意即使选择了顺序执行策略也会这样。

注意:存在并行算法本身抛出异常的可能性!

例如,申请并行执行所需的临时内存资源时失败了,会抛出 std::bad_alloc 异常。从而直接 std::terminate()

所以,使用非并行化版本的算法有时是更好的选择。

可以不使用并行算法

使用非并行算法可以提供以下好处:

  • 可以使用输入和输出迭代器。
  • 算法不会在遇到异常时 std::terminate()
  • 算法可以避免因为意外使用元素导致的副作用。
  • 算法可以提供额外的功能,例如 for_each()会返回传入的可调用对象,我们可能会需要该对象最终的状态

并行算法 - 限制

有限制的并行 STL算法

限制:返回类型 void、前向迭代器

for_each()

限制:前向迭代器

for_each_n() all_of(), and_of(), none_of() 
find(), find_if(), find_if_not() 
find_first_of() 
count(), count_if() 
mismatch() 
equal() 
is_partitioned() 
partial_sort_copy() 
includes() 
lexicographical_compare() 
fill_n() 
generate_n() 
reverse_copy() 
rotate_copy() 
copy(), copy_n(), copy_if() 
move() 
transform() 
replace_copy(), replace_copy_if() 
remove_copy(), remove_copy_if() 
unique_copy() 
partition_copy() 
merge() 
set_union(), set_intersection() 
set_differrnce(), set_symmetric_difference() 
inclusive_scan(), exclusive_scan() 
transform_inclusive_scan(), transform_exclusive_scan()

并行算法有哪些

原有算法

C++17之前,标准中不需要修改就可以并行运行的算法

find_end(), adjacent_find()
search(), search_n()(和“搜索器”一起使用时除外)
swap_ranges()
replace(), replace_if()
fill()
generate()
remove(), remove_if(), unique()
reverse(), rotate()
partition(), stable_partition()
sort(), stable_sort(), partial_sort()
is_sorted(), is_sorted_until()
nth_element()
inplace_merge()
is_heap(), is_heap_until()
min_element(), max_element(), min_max_element()

无并行版本的算法

  • 为了并行地运行 accumulate(),使用reduce() 或者transform_reduce()。
  • 为了并行地运行 partial_sum(),使用…scan()算法。
  • 为了并行地运行 inner_product(),使用transform_reduce()。
accumulate()
partial_sum()
inner_product()
search()(和“搜索器”一起使用时)
copy_backward(), move_backward()
sample(), shuffle()
partition_point()
lower_bound(), upper_bound(), equal_range()
binary_search()
is_permutation()
next_permutation(), prev_permutation()
push_heap(), pop_heap(), make_heap(), sort_heap()

17引入新算法

相关文章:

C++17并行化加速STL算法——std::execution

C17 并行化STL算法 文章目录 C17 并行化STL算法概念环境准备工具类 并行算法 - 使用并行算法 - 执行策略总览选择标准详细介绍顺序执行 seq并行化顺序执行 par并行化乱序执行 par_unseq 并行算法 - 异常处理可以不使用并行算法并行算法 - 限制并行算法有哪些原有算法17引入新算…...

从sumsub获取用户图片

已经拿到了imageid 然后从哪个接口可以获取图片文件呢&#xff1f; 根据您的问题,我可以为您提供以下信息: 一旦您获得了imageId,您可以使用以下几个API接口来获取图片文件: 获取文档图片: Get document images GET https://api.sumsub.com/resources/inspections/{inspection…...

DeepSeek + Mermaid编辑器——常规绘图

下面这张图出自&#xff1a;由清华大学出品的 《DeepSeek&#xff1a;从入门到精通》。 作为纯文本生成模型&#xff0c;DeepSeek虽不具备多媒体内容生成接口&#xff0c;但其开放式架构允许通过API接口与图像合成引擎、数据可视化工具等第三方系统进行协同工作&#xff0c;最终…...

ARM64 Trust Firmware [五 ]

本章介绍 ATF 中的 Runtime Service 是如何定义和被调用的。 要了解 SMC&#xff0c;必须从 SMC 指令本身开始&#xff0c;其指令如下图&#xff1a; 指令格式为&#xff1a;SMC #<imm>&#xff0c;从官方文档了解到该指令只能在 EL1 以及更高的异常等级上调用&#xff…...

Excel核心函数VLOOKUP全解析:从入门到精通

一、函数概述 VLOOKUP是Excel中最重要且使用频率最高的查找函数之一&#xff0c;全称为Vertical Lookup&#xff08;垂直查找&#xff09;。该函数主要用于在数据表的首列查找特定值&#xff0c;并返回该行中指定列的对应值。根据微软官方统计&#xff0c;超过80%的Excel用户在…...

KTransformers如何通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度?

KTransformers通过内核级优化、多GPU并行策略和稀疏注意力等技术显著加速大语言模型的推理速度&#xff0c;具体体现在以下几个方面&#xff1a; 内核级优化&#xff1a; KTransformers采用了高效的内核级优化技术&#xff0c;包括对Transformer模型中的关键操作进行优化。例如…...

审计级别未启用扩展模式导致查询 DBA_AUDIT_TRAIL 时 SQL_TEXT 列为空

如果查询 DBA_AUDIT_TRAIL 时发现 SQL_TEXT 列为空&#xff0c;但其他字段&#xff08;如 OS_USERNAME、USERNAME、TIMESTAMP 等&#xff09;有数据&#xff0c;可能是由于以下原因之一。以下是可能的原因及解决方法&#xff1a; 1. 审计级别未启用扩展模式 默认情况下&#x…...

微信小程序项目 video 组件失效问题,无法播放本地视频

问题与处理策略 问题描述 <video src"../../assets/video/test-video.mp4" controls style"width: 100%; height: 300px;"></video>在微信小程序项目中&#xff0c;上述 video 组件失效&#xff0c;视频无法加载&#xff0c;无法播放本地视频…...

若依-@Excel新增注解numberFormat

Excel注解中原本的scale会四舍五入小数&#xff0c;导致进度丢失 想要的效果 显示的时候保留两个小数真正的数值是保留之前的数值 还原过程 若以中有一個專門的工具类&#xff0c;用来处理excel的 找到EXCEL导出方法exportExcel()找到writeSheet,写表格的方法找到填充数据的方法…...

网络安全行业有哪些公司

只是简单做一下网络安全公司梳理&#xff0c;不作点评&#xff0c;下列排名不分先后。 一、常见的网络安全公司 1、天融信 天融信&#xff08;002212.SZ&#xff09;创始于1995年&#xff0c;是上市公司中成立最早的网络安全企业&#xff0c;亲历中国网络安全产业的发展历程…...

存储区域网络(SAN)管理

存储区域网络&#xff08;Storage Area Network&#xff0c;SAN&#xff09;采用网状通道&#xff08;Fibre Channel &#xff0c;简称FC&#xff09;技术&#xff0c;通过FC交换机连接存储阵列和服务器主机&#xff0c;建立专用于数据存储的区域网络。SAN提供了一种与现有LAN连…...

如何使用Spark SQL进行复杂的数据查询和分析

使用Spark SQL进行复杂的数据查询和分析是一个涉及多个步骤和技术的过程。以下是如何使用Spark SQL进行复杂数据查询和分析的详细指南&#xff1a; 一、准备阶段 环境搭建&#xff1a; 确保已经安装并配置好了Apache Spark环境。准备好数据源&#xff0c;可以是CSV文件、JSON…...

sass报错:[sass] Undefined variable. @import升级@use语法注意事项

今天创建vue3项目&#xff0c;迁移老项目代码&#xff0c;使用sass的时候发现import语法已经废弃&#xff0c;官方推荐使用use替换。 这里我踩了一个坑找半天的问题&#xff0c;原因是sass升级到1.85之后 定义变量前加上 - 就是表示变量私有&#xff0c;即使使用use导出 在新的…...

使用 SDKMAN! 在 Mac(包括 ARM 架构的 M1/M2 芯片)安装适配 Java 8 的 Maven

文章目录 1、安装 SDKMAN!2、安装 Maven:2.1、maven 3.9.62.2、maven 3.8.1 好的&#xff0c;这是使用 SDKMAN! 安装适配 Java 8 的 Maven 的步骤&#xff1a; 1、安装 SDKMAN! 前提条件: 安装 SDKMAN!: 如果你的系统上没有安装 SDKMAN!&#xff0c;请按照以下说明进行安装: c…...

anythingllm服务器部署+ollama+deepseek+实现本地知识库问答

一、docker安装anythingllm 1、拉取镜像 docker pull mintplexlabs/anythingllm:latest 2、创建db目录和配置文件并运行 anythingLLM 容器 export STORAGE_LOCATION/data/ai/wjh_team/anythingllm && \mkdir -p $STORAGE_LOCATION && \touch "$STORAG…...

深度学习04 数据增强、调整学习率

目录 数据增强 常用的数据增强方法 调整学习率 学习率 调整学习率 ​调整学习率的方法 有序调整 等间隔调整 多间隔调整 指数衰减 余弦退火 ​自适应调整 自定义调整 数据增强 数据增强是通过对训练数据进行各种变换&#xff08;如旋转、翻转、裁剪等&#xff09;&am…...

2023年全国职业院校技能大赛GZ073网络系统管理赛项赛题第10套模块A:网络构建

​有问题请留言或主页私信咨询 2023年全国职业院校技能大赛 GZ073网络系统管理赛项 赛题第10套 模块A&#xff1a;网络构建 ​ ​ **目 **录 任务清单 &#xff08;一&#xff09;基础配置 &#xff08;二&#xff09;有线网络配置 &#xff08;三&#xff09;无线…...

2023年河北省职业院校技能大赛网络系统管理赛项样题解法

​ 有问题请留言或主页私信咨询 配置文件有部分测试时的冗余配置无视即可。 解法只有大致解法&#xff0c;并不完整。请参考配置&#xff0c;自己补全 基础配置 1.所有交换机和无线控制器开启SSH服务&#xff0c;用户名密码分别为admin、admin1234&#xff1b;密码为明文类…...

vite+vue3开发uni-app时低版本浏览器不支持es6语法的问题排坑笔记

重要提示&#xff1a;请首先完整阅读完文章内容后再操作&#xff0c;以免不必要的时间浪费&#xff01;切记&#xff01;&#xff01;&#xff01;在使用vitevue3开发uni-app项目时&#xff0c;存在低版本浏览器不兼容es6语法的问题&#xff0c;如“?.” “??” 等。为了方便…...

Linux系统编程基础详解

Linux 系统详解 大纲 引言 Linux 的定义Linux 的历史与发展本文结构概述 Linux 的基本概念 Linux 的架构 内核与用户空间系统调用 Linux 的文件系统 文件与目录结构权限管理 Linux 的进程管理 进程与线程进程调度 Linux 的基本命令与操作 常用命令概述 文件与目录操作命令文…...

python打卡day49

知识点回顾&#xff1a; 通道注意力模块复习空间注意力模块CBAM的定义 作业&#xff1a;尝试对今天的模型检查参数数目&#xff0c;并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

多种风格导航菜单 HTML 实现(附源码)

下面我将为您展示 6 种不同风格的导航菜单实现&#xff0c;每种都包含完整 HTML、CSS 和 JavaScript 代码。 1. 简约水平导航栏 <!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport&qu…...

Mobile ALOHA全身模仿学习

一、题目 Mobile ALOHA&#xff1a;通过低成本全身远程操作学习双手移动操作 传统模仿学习&#xff08;Imitation Learning&#xff09;缺点&#xff1a;聚焦与桌面操作&#xff0c;缺乏通用任务所需的移动性和灵活性 本论文优点&#xff1a;&#xff08;1&#xff09;在ALOHA…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码

目录 一、&#x1f468;‍&#x1f393;网站题目 二、✍️网站描述 三、&#x1f4da;网站介绍 四、&#x1f310;网站效果 五、&#x1fa93; 代码实现 &#x1f9f1;HTML 六、&#x1f947; 如何让学习不再盲目 七、&#x1f381;更多干货 一、&#x1f468;‍&#x1f…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

数据结构第5章:树和二叉树完全指南(自整理详细图文笔记)

名人说&#xff1a;莫道桑榆晚&#xff0c;为霞尚满天。——刘禹锡&#xff08;刘梦得&#xff0c;诗豪&#xff09; 原创笔记&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 上一篇&#xff1a;《数据结构第4章 数组和广义表》…...

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅!

【把数组变成一棵树】有序数组秒变平衡BST,原来可以这么优雅! 🌱 前言:一棵树的浪漫,从数组开始说起 程序员的世界里,数组是最常见的基本结构之一,几乎每种语言、每种算法都少不了它。可你有没有想过,一组看似“线性排列”的有序数组,竟然可以**“长”成一棵平衡的二…...