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

windows C++ 并行编程-PPL 中的取消操作(四)

并行模式库 (PPL) 中取消操作的角色、如何取消并行工作以及如何确定取消并行工作的时间。

运行时使用异常处理实现取消操作。 请勿在代码中捕捉或处理这些异常。 此外,还建议你在任务的函数体中编写异常安全的代码。 例如,可以使用获取资源即初始化 (RAII) 模式,以确保在任务体中引发异常时正确处理资源。

使用异常来取消并行工作

要取消并行工作树,使用取消标记和 cancel 方法比使用异常处理更有效。 取消标记和 cancel 方法由上向下取消任务和所有子任务。 相反,异常处理以自下而上的方式工作,并且必须在异常向上传播时单独取消每个子任务组。 异常处理主题介绍了并发运行时如何使用异常来传递错误。 但是,并非所有异常都表示错误。 例如,搜索算法可能在找到结果时取消其关联的任务。 但是,如上所述,在取消并行工作时,异常处理的效率比使用 cancel 方法低。

注意如非必要,建议你不要使用异常来取消并行工作。 取消标记和任务组 cancel 方法更高效且更不易出错。

当在传递给任务组的工作函数体中引发异常时,运行时存储该异常,并将该异常封送到等待任务组完成的上下文。 与 cancel 方法一样,运行时将放弃任何尚未启动的任务,并且不接受新任务。

第三个示例与第二个示例类似,只不过任务 t4 引发异常来取消任务组 tg2。 此示例使用 try-catch 块在任务组 tg2 等待其子任务完成时检查取消情况。 与第一个示例类似,这会导致任务组 tg2 进入已取消状态,但不会取消任务组 tg1。

structured_task_group tg2;// Create a child task.      
auto t4 = make_task([&] {// Perform work in a loop.for (int i = 0; i < 1000; ++i){// Call a function to perform work.// If the work function fails, throw an exception to // cancel the parent task.bool succeeded = work(i);if (!succeeded){throw exception("The task failed");}}         
});// Create a child task.
auto t5 = make_task([&] {// TODO: Perform work here.
});// Run the child tasks.
tg2.run(t4);
tg2.run(t5);// Wait for the tasks to finish. The runtime marshals any exception
// that occurs to the call to wait.
try
{tg2.wait();
}
catch (const exception& e)
{wcout << e.what() << endl;
}

第四个示例使用异常处理来取消整个工作树。 此示例在任务组 tg1 等待其子任务完成时,而不是任务组 tg2 等待其子任务完成时捕获异常。 与第二个示例类似,这会导致树中的两个任务组 tg1 和 tg2 都进入已取消状态。 

// Run the child tasks.
tg1.run(t1);
tg1.run(t2);
tg1.run(t3);   // Wait for the tasks to finish. The runtime marshals any exception
// that occurs to the call to wait.
try
{tg1.wait();
}
catch (const exception& e)
{wcout << e.what() << endl;
}

因为 task_group::wait 和 structured_task_group::wait 方法在子任务引发异常时引发,所以你没有从它们收到返回值。

取消并行算法

PPL 中的并行算法(如 parallel_for)基于任务组生成。 因此,你可以使用许多相同的技术来取消并行算法。

以下示例说明了几种取消并行算法的方法。

下面的示例使用 run_with_cancellation_token 函数调用 parallel_for 算法。 run_with_cancellation_token 函数采用一个取消标记作为参数并同步调用提供的工作函数。 因为并行算法基于任务生成,它们继承父任务的取消标记。 因此,parallel_for 可以响应取消。

// cancel-parallel-for.cpp
// compile with: /EHsc
#include <ppltasks.h>
#include <iostream>
#include <sstream>using namespace concurrency;
using namespace std;int wmain()
{// Call parallel_for in the context of a cancellation token.cancellation_token_source cts;run_with_cancellation_token([&cts]() {// Print values to the console in parallel.parallel_for(0, 20, [&cts](int n){// For demonstration, cancel the overall operation // when n equals 11.if (n == 11){cts.cancel();}// Otherwise, print the value.else{wstringstream ss;ss << n << endl;wcout << ss.str();}});}, cts.get_token());
}
/* Sample output:151617100185
*/

下面的示例使用 concurrency::structured_task_group::run_and_wait 方法来调用 parallel_for 算法。 structured_task_group::run_and_wait 方法等待提供的任务完成。 structured_task_group 对象可让工作函数取消该任务。

// To enable cancelation, call parallel_for in a task group.
structured_task_group tg;task_group_status status = tg.run_and_wait([&] {parallel_for(0, 100, [&](int i) {// Cancel the task when i is 50.if (i == 50){tg.cancel();}else{// TODO: Perform work here.}});
});// Print the task group status.
wcout << L"The task group status is: ";
switch (status)
{
case not_complete:wcout << L"not complete." << endl;break;
case completed:wcout << L"completed." << endl;break;
case canceled:wcout << L"canceled." << endl;break;
default:wcout << L"unknown." << endl;break;
}输出:
The task group status is: canceled.

下面的示例使用异常处理来取消 parallel_for 循环。 运行时将异常封送到调用上下文。

try
{parallel_for(0, 100, [&](int i) {// Throw an exception to cancel the task when i is 50.if (i == 50){throw i;}else{// TODO: Perform work here.}});
}
catch (int n)
{wcout << L"Caught " << n << endl;
}输出:
Caught 50

下面的示例使用一个布尔型标志来协调 parallel_for 循环中的取消。 每个任务都运行,因为此示例不使用 cancel 方法或异常处理来取消整个任务集。 因此,这种技术的计算开销可能比取消机制大。

// Create a Boolean flag to coordinate cancelation.
bool canceled = false;parallel_for(0, 100, [&](int i) {// For illustration, set the flag to cancel the task when i is 50.if (i == 50){canceled = true;}// Perform work if the task is not canceled.if (!canceled){// TODO: Perform work here.}
});

每个取消方法都有其他方法所没有的优点。 请选择适合你的特定需求的方法。

何时不使用取消

当一组相关任务中的每个成员可以及时退出时,使用取消是恰当的。 但是,在某些情况下取消可能不适合你的应用程序。 例如,由于任务取消是协作性的,如果任何单个任务被阻止,则无法取消整个任务集。 例如,如果一个任务尚未开始,但它取消阻止另一个活动任务,则在任务组已取消时,它将不能启动。 这会导致应用程序中发生死锁。 可能不适合使用取消的另一个示例是任务被取消,但其子任务会执行重要操作(如释放资源)。 因为在取消父任务时整个任务集也会被取消,所以将无法执行此操作。

相关文章:

windows C++ 并行编程-PPL 中的取消操作(四)

并行模式库 (PPL) 中取消操作的角色、如何取消并行工作以及如何确定取消并行工作的时间。 运行时使用异常处理实现取消操作。 请勿在代码中捕捉或处理这些异常。 此外&#xff0c;还建议你在任务的函数体中编写异常安全的代码。 例如&#xff0c;可以使用获取资源即初始化 (RA…...

【数据结构】字符串与JSON字符串、JSON字符串及相应数据结构(如对象与数组)之间的相互转换

前言&#xff1a; 下面打印日志用的是FastJSON依赖库中的 Log4j2。依赖&#xff1a; <!-- Alibaba Fastjson --> <dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.80</version> …...

LeetcodeTop100 刷题总结(一)

LeetCode 热题 100&#xff1a;https://leetcode.cn/studyplan/top-100-liked/ 文章目录 一、哈希1. 两数之和49. 字母异位词分组128. 最长连续序列 二、双指针283. 移动零11. 盛水最多的容器15. 三数之和42. 接雨水&#xff08;待完成&#xff09; 三、滑动窗口3. 无重复字符的…...

Next-ViT: 下一代视觉Transformer,用于现实工业场景中的高效部署

摘要 由于复杂的注意力机制和模型设计&#xff0c;大多数现有的视觉Transformer&#xff08;ViTs&#xff09;在实际的工业部署场景中&#xff0c;如TensorRT和CoreML&#xff0c;无法像卷积神经网络&#xff08;CNNs&#xff09;那样高效运行。这提出了一个明显的挑战&#x…...

C++知识点示例代码助记

C语言设计期末知识点附示例代码。 1. 基础语法 变量和数据类型&#xff1a; int a 10; // 整型 float b 5.25f; // 单精度浮点型 double c 5.25; // 双精度浮点型 char d A; // 字符型 bool e true; // 布尔型 const int PI 3.14; // 常量输入输出&…...

Java 入门指南:JVM(Java虚拟机)垃圾回收机制 —— 垃圾回收算法

文章目录 垃圾回收机制垃圾判断算法引用计数法可达性分析算法虚拟机栈中的引用&#xff08;方法的参数、局部变量等&#xff09;本地方法栈中 JNI 的引用类静态变量运行时常量池中的常量 垃圾收集算法Mark-Sweep&#xff08;标记-清除&#xff09;算法Copying&#xff08;标记-…...

苍穹外卖Day01-2

导入接口文档 yApi接口管理平台http://api.doc.jiyou-tech.com/ 创建项目 导入接口文件 导入结果界面 Swagger 介绍 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面。 官网&#xff1a;ht…...

软考中级软件设计师——数据结构与算法基础学习笔记

软考中级软件设计师——数据结构与算法基本概念 什么是数据数据元素、数据项数据结构逻辑结构物理结构&#xff08;存储结构&#xff09; 算法什么是算法五个特性算法效率的度量时间复杂度空间复杂度 什么是数据 数据是信息的载体&#xff0c;是描述客观事物属性的数、字符及所…...

虚幻引擎 | (类恐鬼症)玩家和NPC语音聊天(中)

虚幻引擎 | &#xff08;类恐鬼症&#xff09;玩家和NPC语音聊天-CSDN博客 上篇偏重实现步骤&#xff0c;中篇偏重理解校准和降低延迟&#xff0c;下篇加入上下文背景array和设置口音 TTS通用参数 ————————————————————————————————————…...

整流电路的有源逆变工作状态

目录 1. 逆变的概念 2. 有源逆变的条件 3. 电流电路的概念 4. 产生逆变的条件 5. 三相桥式全控整流电路的有源逆变工作状态 6. 逆变角的概念 7. 逆变失败的原因 8. 最小逆变角的限制 整流电路的有源逆变状态是指通过控制整流器&#xff0c;使其将直流电源的能量反向送回…...

Android 签名、空包签名 、jarsigner、apksigner

jarsigner是JDK提供的针对jar包签名的通用工具, 位于JDK/bin/jarsigner.exe apksigner是Google官方提供的针对Android apk签名及验证的专用工具, 位于Android SDK/build-tools/SDK版本/apksigner.bat jarsigner&#xff1a; jarsigner签名空包执行的命令&#xff1a; jar…...

java基础(小技巧)

文章目录 一、日志输出二、字符串拼接三、日期比较四、常用注解五、Lombok的原理 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、日志输出 之前使用的方式。在要使用的类里面定义日志类&#xff1a; private static Logger logger LoggerFactory…...

Android Studio 安装配置教程(Windows最详细版)

目录 前言 Android Studio 下载 Android Studio 安装 Android Studio 使用 一、创建默认项目&#xff08;Compose&#xff09; 二、创建常规项目 三、使用ViewBinding 四、查看Gradle版本、SDK版本、JDK版本 ① Gradle版本 ② SDK版本 ③ JDK版本 前言 Android开发…...

Cesium绘制可编辑线

Cesium 第一章 绘制可编辑线 Screen-2024-09-17-202059的副本 文章目录 Cesium一、绘制线二、编辑线三、使用 一、绘制线 1、方法 //场景相机控制viewer.scene.screenSpaceCameraController.enableRotate false; //cesium相机控制 绘制和编辑时 禁止转动场景// 鼠标样式修改…...

【算法】差分思想:强大的算法技巧

&#x1f4e2;博客主页&#xff1a;https://blog.csdn.net/2301_779549673 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01; &#x1f4e2;本文由 JohnKi 原创&#xff0c;首发于 CSDN&#x1f649; &#x1f4e2;未来很长&#…...

微软开源项目 Detours 详细介绍与使用实例分享

目录 1、Detours概述 2、Detours功能特性 3、Detours工作原理 4、Detours应用场景 5、Detours兼容性 6、Detours具体使用方法 7、Detours使用实例 - 使用Detours拦截系统库中的UnhandledExceptionFilter接口,实现对程序异常的拦截 C++软件异常排查从入门到精通系列教程…...

Numba基础

1. Numba 基础 1.1 什么是 Numba&#xff1f; Numba 是一个 JIT 编译器&#xff0c;用于加速数值计算。它通过即时编译技术&#xff0c;将 Python 代码在运行时编译为机器代码&#xff0c;极大地提升执行速度&#xff0c;特别适合循环和矩阵操作等密集型计算。 2. Numba 基本…...

[JAVA]介绍怎样在Java中通过字节字符流实现文件读取与写入

一&#xff0c;初识File类及其常用方法 File类是java.io包下代表与平台无关的文件和目录&#xff0c;程序中操作文件和目录&#xff0c;都可以通过File类来完成。 通过这个File对象&#xff0c;可以进行一系列与文件相关的操作&#xff0c;比如判断文件是否存在&#xff0c;获…...

oracle停止当前运行的JOB或kill会话

在Oracle中&#xff0c;可以使用DBA_SCHEDULER_JOBS视图来查找当前正在运行的作业&#xff08;job&#xff09;&#xff0c;并使用DBMS_SCHEDULER.STOP_JOB过程来停止它们 SELECT JOB_NAME, STATE FROM DBA_SCHEDULER_JOBS WHERE STATE RUNNING; SELECT * FROM DBA_SCHEDULE…...

SpringBoot 消息队列RabbitMQ 消息可靠性 数据持久化 与 LazyQueue

介绍 在默认情况下&#xff0c;RabbitMQ会将接收到的信息保存在内存中以降低消息收发的延迟 一旦MO宕机&#xff0c;内存中的消息会丢失内存空间有限&#xff0c;当消费者故障或处理过慢时&#xff0c;会导致消息积压&#xff0c;引发MQ阻塞 在消息队列运行的过程中&#xf…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈

在日常iOS开发过程中&#xff0c;性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期&#xff0c;开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发&#xff0c;但背后往往隐藏着系统资源调度不当…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

【JVM】Java虚拟机(二)——垃圾回收

目录 一、如何判断对象可以回收 &#xff08;一&#xff09;引用计数法 &#xff08;二&#xff09;可达性分析算法 二、垃圾回收算法 &#xff08;一&#xff09;标记清除 &#xff08;二&#xff09;标记整理 &#xff08;三&#xff09;复制 &#xff08;四&#xff…...

windows系统MySQL安装文档

概览&#xff1a;本文讨论了MySQL的安装、使用过程中涉及的解压、配置、初始化、注册服务、启动、修改密码、登录、退出以及卸载等相关内容&#xff0c;为学习者提供全面的操作指导。关键要点包括&#xff1a; 解压 &#xff1a;下载完成后解压压缩包&#xff0c;得到MySQL 8.…...

云原生周刊:k0s 成为 CNCF 沙箱项目

开源项目推荐 HAMi HAMi&#xff08;原名 k8s‑vGPU‑scheduler&#xff09;是一款 CNCF Sandbox 级别的开源 K8s 中间件&#xff0c;通过虚拟化 GPU/NPU 等异构设备并支持内存、计算核心时间片隔离及共享调度&#xff0c;为容器提供统一接口&#xff0c;实现细粒度资源配额…...

Qt的学习(二)

1. 创建Hello Word 两种方式&#xff0c;实现helloworld&#xff1a; 1.通过图形化的方式&#xff0c;在界面上创建出一个控件&#xff0c;显示helloworld 2.通过纯代码的方式&#xff0c;通过编写代码&#xff0c;在界面上创建控件&#xff0c; 显示hello world&#xff1b; …...