(C++17) std算法之执行策略 execution

news2025/2/1 14:08:55

文章目录

  • 前言
  • Code测试
    • Code
    • 运行效果
  • msvc源码描述
    • 源码
    • std::sequenced_policy seq
    • std::parallel_policy par
    • std::parallel_unsequenced_policy par_unseq
    • std::unsequenced_policy unseq
  • END

前言

ref:算法库-执行策略 - cppreference.com

利用多核cpu加速算法在目前看来已经不是什么新鲜事了。在C++17中,推出了算法函数的执行策略,可以选择执行策略来优化算法的执行效果。(注意不是所有算法都支持)

目前到C++20,已经支持了四种执行策略。当然本文也仅仅是做简单的展示和描述,因此内部细节十分复杂不是几篇端文章就能看懂的。

标准策略执行策略类型(类)全局执行策略对象(常量)
C++17串行执行sequenced_policystd::execution::seq
C++17并行执行parallel_policystd::execution::par
C++17并行无序执行parallel_unsequenced_policystd::execution::par_unseq
C++20无序执行unsequenced_policystd::execution::unseq
功能特性测试标准功能特性
__cpp_lib_parallel_algorithm201603LC++17并行算法
__cpp_lib_execution201603LC++17执行策略
__cpp_lib_execution201902LC++20std::execution::unsequenced_policy

Code测试

Code

这里仅展示一个比较简单的小例子,仅做小参考。

#include <algorithm>
#include <ctime>
#include <execution>
#include <iostream>
#include <string>
#include <vector>

 /**
  * 辅助计时类
  */
class Timer {
    std::string str;
    clock_t     start;

public:
    Timer(const std::string& str) : str(str) {
        start = clock();
    }

    ~Timer() {
        clock_t end = clock();
        std::cout << str << " => " << (end - start) / 1000.0 << '\n';
    }
};

/**
 * 串行执行策略
 * class sequenced_policy;
 */
void test_sequenced_policy(std::vector<int> arr) {
    Timer timer("std::execution::seq");
    std::sort(std::execution::seq, arr.begin(), arr.end());
}

/**
 * 并行执行策略
 * class parallel_policy;
 */
void test_parallel_policy(std::vector<int> arr) {
    Timer timer("std::execution::par");
    std::sort(std::execution::par, arr.begin(), arr.end());
}

/**
 * 并行无序执行策略
 * class parallel_unsequenced_policy;
 */
void test_parallel_unsequenced_policy(std::vector<int> arr) {
    Timer timer("std::execution::par_unseq");
    std::sort(std::execution::par_unseq, arr.begin(), arr.end());
}

/**
 * 无序执行策略
 * class unsequenced_policy;
 */
void test_unsequenced_policy(std::vector<int> arr) {
#if __cpp_lib_execution >= 201902L
    Timer timer("std::execution::unseq");
    std::sort(std::execution::unseq, arr.begin(), arr.end());
#endif
}

int main() {
    // help data
    std::vector<int> arr;
    for (int i = 0; i < 3.0 * 100'000'00; i += 1) {
        arr.push_back(rand());
    }

    test_sequenced_policy(arr);
    test_parallel_policy(arr);
    test_parallel_unsequenced_policy(arr);
    test_unsequenced_policy(arr);
}

运行效果

使用编译器:vs2019 => _MSC_VER = 1929

这只是基于笔者本地的单词测试,仅作参考。

x86-Debug

std::execution::seq => 22.874
std::execution::par => 5.495
std::execution::par_unseq => 5.854
std::execution::unseq => 22.864

x86-Release

std::execution::seq => 1.249
std::execution::par => 0.258
std::execution::par_unseq => 0.253
std::execution::unseq => 1.201

x64-Debug

std::execution::seq => 8.705
std::execution::par => 2.371
std::execution::par_unseq => 2.402
std::execution::unseq => 8.737

x64-Release

std::execution::seq => 1.179
std::execution::par => 0.25
std::execution::par_unseq => 0.238
std::execution::unseq => 1.129

msvc源码描述

std::execution::sequenced_policy, std::execution::parallel_policy, std::execution::parallel_unsequenced_policy, std::execution::unsequenced_policy - cppreference.com

std::execution::seq, std::execution::par, std::execution::par_unseq, std::execution::unseq - cppreference.com

在以任何这些执行策略执行并行算法的过程中,若元素访问函数的调用因未捕获的异常退出,则调用 std::terminate,但实现可以定义以其他方式处理异常的额外执行策略。

源码

笔者看过gcc 11.2.0的实现,是用函数直接返回true-or-false的方式来区分。

但是注释基本没没什么描述,因此就不展示了。

本代码于msvc中<execution>

可见这里其实是定义了四个类型标签。标准没有定义对象内部的属性,这里是msvc的实现问题。

这里主要可以直接根据msvc的人话注释来理解标签的有含义。

namespace execution {
    class sequenced_policy {
        // indicates support for only sequential execution, and requests termination on exceptions
    public:
        using _Standard_execution_policy   = int;
        static constexpr bool _Parallelize = false;
        static constexpr bool _Ivdep       = false;
    };

    inline constexpr sequenced_policy seq{/* unspecified */};

    class parallel_policy {
        // indicates support by element access functions for parallel execution with parallel forward progress
        // guarantees, and requests termination on exceptions
    public:
        using _Standard_execution_policy   = int;
        static constexpr bool _Parallelize = true;
        static constexpr bool _Ivdep       = true;
    };

    inline constexpr parallel_policy par{/* unspecified */};

    class parallel_unsequenced_policy {
        // indicates support by element access functions for parallel execution with weakly parallel forward progress
        // guarantees, and requests termination on exceptions
        //
        // (at this time, equivalent to parallel_policy)
    public:
        using _Standard_execution_policy   = int;
        static constexpr bool _Parallelize = true;
        static constexpr bool _Ivdep       = true;
    };

    inline constexpr parallel_unsequenced_policy par_unseq{/* unspecified */};

#if _HAS_CXX20
    class unsequenced_policy {
        // indicates support by element access functions for weakly parallel forward progress guarantees, and for
        // executing interleaved on the same thread, and requests termination on exceptions
        //
        // (at this time, equivalent to sequenced_policy except for the for_each family)
    public:
        using _Standard_execution_policy   = int;
        static constexpr bool _Parallelize = false;
        static constexpr bool _Ivdep       = true;
    };

    inline constexpr unsequenced_policy unseq{/* unspecified */};
#endif // _HAS_CXX20

} // namespace execution

std::sequenced_policy seq

  1. 执行策略类型,用作对并行算法重载消歧义的独有类型,并要求并行算法的执行可以不并行化。以此策略调用(通常以 std::execution::seq 指定)的并行算法中,元素访问函数的调用在调用方线程中是非确定顺序的。
/**
 * 串行策略
 * indicates support for only sequential execution
 * 指示仅支持顺序执行
 * and requests termination on exceptions
 * 并在异常时终止请求
 */
class sequenced_policy {
    // indicates support for only sequential execution, and requests termination on exceptions
public:
    using _Standard_execution_policy   = int;
    static constexpr bool _Parallelize = false;
    static constexpr bool _Ivdep       = false;
};

inline constexpr sequenced_policy seq{/* unspecified */};

std::parallel_policy par

  1. 执行策略类型,用作对并行算法重载消歧义的独有类型,并指示并行算法的执行可以并行化。以此策略调用(通常以 std::execution::par 指定)的并行算法中,元素访问函数的调用允许在调用方线程,或由库隐式创建的用以支持并行算法执行的线程中执行。任何执行于同一线程中的这种调用彼此间是非确定顺序的,
/**
 * 并行执行策略
 * indicates support by element access functions for parallel execution with parallel forward
 * progress guarantees
 * 指示元素访问函数支持并行执行,并保证并行向前进度
 * and requests termination on exceptions
 * 并在异常时终止请求
 */
class parallel_policy {
    // indicates support by element access functions for parallel execution with parallel forward
    // progress guarantees, and requests termination on exceptions
public:
    using _Standard_execution_policy   = int;
    static constexpr bool _Parallelize = true;
    static constexpr bool _Ivdep       = true;
};

inline constexpr parallel_policy par{/* unspecified */};

std::parallel_unsequenced_policy par_unseq

  1. 执行策略类型,用作对并行算法重载消歧义的独有类型,并指示并行算法的执行可以并行化、向量化,或在线程间迁移(例如用亲代窃取式调度器)。以此策略调用的并行算法中,容许在未指定线程中以无序方式来执行元素访问函数调用,并相对于各个线程中的另一调用间无顺序。
/**
 * 并行无序执行策略
 * indicates support by element access functions for parallel execution with weakly parallel
 * forward progress guarantees
 * 指示元素访问函数支持并行执行,并提供弱并行向前进度保证
 * and requests termination on exceptions
 * 并在异常时终止请求
 * (at this time, equivalent to parallel_policy)
 * (此时,相当于并行策略)
 */
class parallel_unsequenced_policy {
    // indicates support by element access functions for parallel execution with weakly parallel
    // forward progress guarantees, and requests termination on exceptions
    //
    // (at this time, equivalent to parallel_policy)
public:
    using _Standard_execution_policy   = int;
    static constexpr bool _Parallelize = true;
    static constexpr bool _Ivdep       = true;
};

inline constexpr parallel_unsequenced_policy par_unseq{/* unspecified */};

std::unsequenced_policy unseq

  1. 执行策略类型,用作对并行算法重载消歧义的独有类型,并指示可将算法的执行向量化,例如在单个线程上使用操作多个数据项的指令执行。
#if _HAS_CXX20
/**
 * 无序执行策略
 * indicates support by element access functions for weakly parallel forward progress guarantees
 * 指示元素访问函数支持弱并行向前进度保证
 * and for executing interleaved on the same thread
 * 支持在同一线程上交错执行
 * and requests termination on exceptions
 * 以及在异常时终止请求
 * (at this time, equivalent to sequenced_policy except for the for_each family)
 * (此时,相当于sequenced_policy,除了for_each一类)
 */
class unsequenced_policy {
    // indicates support by element access functions for weakly parallel forward progress
    // guarantees, and for executing interleaved on the same thread, and requests termination on
    // exceptions
    //
    // (at this time, equivalent to sequenced_policy except for the for_each family)
public:
    using _Standard_execution_policy   = int;
    static constexpr bool _Parallelize = false;
    static constexpr bool _Ivdep       = true;
};

inline constexpr unsequenced_policy unseq{/* unspecified */};
#endif  // _HAS_CXX20

END

关注我,学习更多C/C++,算法,计算机知识

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1555530.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot+MybatisPlus+EasyExcel实现文件导入数据

记录一下写Excel文件导入数据所经历的问题。 springboot提供的文件处理MultipartFile有关方法&#xff0c;我没有具体看文档&#xff0c;但目测比较复杂&#xff0c; 遂了解学习了一下别的文件上传方法&#xff0c;本文第1节记录的是springboot原始的导入文件方法写法&#xf…

论文阅读-《Lite Pose: Efficient Architecture Design for 2D Human Pose Estimation》

摘要 这篇论文主要研究了2D人体姿态估计的高效架构设计。姿态估计在以人为中心的视觉应用中发挥着关键作用&#xff0c;但由于基于HRNet的先进姿态估计模型计算成本高昂&#xff08;每帧超过150 GMACs&#xff09;&#xff0c;难以在资源受限的边缘设备上部署。因此&#xff0…

vue的创建、启动以及目录结构详解

vue的创建、启动以及目录结构详解目录 一. vue项目的创建 二. vue的目录结构 三. src的目录结构 四. vue项目的启动 4.1 方法1 4.2 方法2 一. vue项目的创建 创建一个工程化的Vue项目&#xff0c;执行命令&#xff1a;npm init vuelatest 注意&#xff1a;如果你在这个目…

【Python基础教程】3 . 算法的时间复杂度

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;python基础教程 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、…

[每周一更]-第91期:认识AMD的CPU

这一章来认识下AMD,说起AMD&#xff0c;从我上大学那时候&#xff0c;就选购的AMD 速龙系列&#xff0c;生活拮据的情况下&#xff0c;拉着室友去郑州电子城&#xff0c;在跟奸商老板的拉扯下&#xff0c;斥资2000购入一个无显卡 的台式机&#xff08;实在是资金有限&#xff0…

【Spring源码】WebSocket做推送动作的底层实例

一、前瞻 Ok&#xff0c;开始我们今天的对Spring的【模块阅读】。 那就挑Web里的WebSocket模块&#xff0c;先思考下本次阅读的阅读线索&#xff1a; WebSocket在Spring里起到什么作用这个模块采用了什么设计模式我们都知道WebSocket可以主动推送消息给用户&#xff0c;那做推…

小程序中使用less

在vscode中安装插件 找到左下角齿轮的设置&#xff0c;点击右边图标&#xff0c;进入“settings.json” 加上以下代码配置 "less.compile":{"outExt": ".wxss"}

在.Net6中用gdal实现第一个功能

目录 一、创建.NET6的控制台应用程序 二、加载Gdal插件 三、编写程序 一、创建.NET6的控制台应用程序 二、加载Gdal插件 Gdal的资源可以经过NuGet包引入。右键单击项目名称&#xff0c;然后选择 "Manage NuGet Packages"&#xff08;管理 NuGet 包&#xff09;。N…

揭秘情绪识别:如何让AI读懂你的心声?

最近我在研究大语言模型&#xff0c;想用它来给样本打分。 起初&#xff0c;我尝试让模型用1到5分来评分&#xff0c;但它总是极端地给出最低分或最高分&#xff0c;评分缺乏中间地带。 于是我换了个方法&#xff0c;不再用数字&#xff0c;而是用描述性的词语&#xff0c;比…

《让你的时间多一倍》逃离时间陷阱,你没有自己想的那么懒 - 三余书屋 3ysw.net

让你的时间多一倍 今天我们来阅读法比安奥利卡尔的作品《让你的时间多一倍》。或许你会心生疑虑&#xff0c;这本书是否又是一本沉闷的时间管理指南&#xff1f;但我要告诉你的是&#xff0c;尽管时间管理这个话题已经为大众所熟知&#xff0c;这本书却为我们揭示了一个全新的…

php将网页用wkhtmltoimage内容生成为图片

php架构ThinkPHP6 1. 安装 knp-snappy架构 composer require knplabs/knp-snappy use Knp\Snappy\Image; use Illuminate\Support\Facades\Storage;// 生成图片 /user/local/bin/wkhtmltoimage为你的wkhtmltoimage的位置。 $snappy new Image(/usr/local/bin/wkhtmltoimage…

EXCEL VBA根据表数据写入数据库中

EXCEL VBA根据表数据写入数据库中 Option Explicithttps://club.excelhome.net/thread-1687531-1-1.htmlSub UpdateAccess()Const adStateOpen 1Dim vData, i As Variant, j As LongDim AccessTable As String, ExcelTable As String, ExcelFile As String, AccessFile As Str…

【JavaWeb】Day27.Web入门——Tomcat介绍

目录 WEB服务器-Tomcat 一.服务器概述 二.Web服务器 三.Tomcat- 基本使用 1.下载 2.安装与卸载 3.启动与关闭 4.常见问题 四.Tomcat- 入门程序 WEB服务器-Tomcat 一.服务器概述 服务器硬件&#xff1a;指的也是计算机&#xff0c;只不过服务器要比我们日常使用的计算…

HarmonyOS 应用开发之启动/停止本地PageAbility

启动本地PageAbility PageAbility相关的能力通过featureAbility提供&#xff0c;启动本地Ability通过featureAbility中的startAbility接口实现。 表1 featureAbility接口说明 接口名接口描述startAbility(parameter: StartAbilityParameter)启动Ability。startAbilityForRes…

vite vue3 import.meta.glob动态路由

在Vite中使用Vue 3&#xff0c;你可以使用import.meta.glob来导入目录下的多个Vue组件&#xff0c;并自动生成路由。以下是一个简单的例子&#xff1a; router/index.js // router/index.js import { createRouter, createWebHistory } from vue-router;// 自动导入views目录下…

【51单片机入门记录】定时器/计数器

目录 一、定时器/计数器概述 &#xff08;1&#xff09;实现定时功能的几种方法 &#xff08;2&#xff09;定时器和计数器的区别 &#xff08;3&#xff09;基本概念 二、定时器/计数器相关寄存器 &#xff08;1&#xff09;控制寄存器TCON&#xff08;可位寻址&#xf…

软考高级软件架构师:数字签名技术概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【C++】多态的原理

目录 一、虚函数表 1、虚函数表的定义 2、虚函数表特性 3、虚表的打印 二、多态的原理 三、多态的相关问题 1、指针偏移问题 2、输出的程序是什么&#xff1f; 3、输出的程序是什么&#xff1f; 【前言】 上一篇我们学习了多态的基础知识&#xff0c;这一篇我将带着大…

InputStreamReader类详解

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java SE相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

刷题之动态规划

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;开始刷动态规划的题目了&#xff0c;要特别注意初始化的时候给什么值。 动态规划5个步骤 状态表示 &#xff1a;dp数组中每一个下标对应值的含义是什么->dp[i]表示什么状态转移方程&#xff1a; dp[i] 等于什么1 和 2 是…