【C#】并行编程实战:实现数据并行(3)

news2024/12/23 21:01:54

        本章继续学习实现数据并行,本文主要介绍取消循环。

        本教程对应学习工程:魔术师Dix / HandsOnParallelProgramming · GitCode        


4、取消循环

        在顺序循环中,可以使用 break 来跳出循环,而在并行循环的情况下,由于他们在多个线程上执行,因此无法使用 break 和 continue 关键字。

4.1、ParallelLoopState.Break

        测试代码如下,这里我们把最大并行度设置为2 :

        private void CancelByParallelBreak()
        {
            int length = commonPanel.GetInt32Parameter();
            var L = TestFunction.GetTestList(length);            
            //设置最大并行度为2
            var options = new ParallelOptions { MaxDegreeOfParallelism = 2 };
            var result = Parallel.ForEach(L, options, (i, state) =>
            {
                Debug.Log(L[i]);
                state.Break();//跳出循环
                Debug.Log($"Run Parallel Break At {Task.CurrentId}");
            });
            Debug.Log($"CancelByParallelBreak End!  : {result.IsCompleted} | {result.LowestBreakIteration}");
        }

        此时,我们看到打印结果如下:

         两个线程,各自打印了1次就中断了,并且结果返回的 IsCompleted 为 False。

        当任何处理器遇到 Break()方法时,它将在 ParallelLoopState 对象的 LowestBreakIteration 属性中设置一个迭代数,这将成为迭代的最大次数或可以执行的最后一次迭代。其他所有任务将继续迭代,直至达到此次数。

        因此,我们把代码做部分修改:

……
Debug.Log($"Log {L[i]} At :{Task.CurrentId}");
if (L[i] == 0)
{
    state.Break();
    Debug.Log($"Run Parallel Break At {Task.CurrentId}");
}
……

        这里我们在其中一个线程中设置为值为 0,也就是在第一次循环中就中断循环。但得到的打印结果却有所不同:

         可以看到,另一个线程执行了3次才中断循环。

4.2、ParallelLoopState.Stop

        同样上述的方法,同样将并行度设置为2,我们把 Break 改成 Stop:

        private void CancelByParallelStop()
        {
            int length = commonPanel.GetInt32Parameter();
            var L = TestFunction.GetTestList(length);
            var options = new ParallelOptions { MaxDegreeOfParallelism = 2 };
            var result = Parallel.ForEach(L, options, (i, state) =>
            {
                Debug.Log($"Log {L[i]} At :{Task.CurrentId}");

                if (L[i] == 0)
                {
                    state.Stop();
                    Debug.Log($"Run Parallel Stop At {Task.CurrentId}");
                }
            });
            Debug.Log($"CancelByParallelStop End!  : {result.IsCompleted} | {result.LowestBreakIteration}");
        }

        打印结果如下:

 

4.3、CancellationToken

        和正常任务一样,也可以使用 CacellationToken 类来取消迭代。当取消令牌时,循环将完成当前并行运行的迭代,但不会开始新的迭代。现有迭代完成后,并行循环将抛出 OperationCanceledException 。代码示例如下:

        private void CancelByParallelCancellationToken()
        {
            int length = commonPanel.GetInt32Parameter();
            var L = TestFunction.GetTestList(length);

            //将取消令牌设置为运行参数
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            var options = new ParallelOptions
            {
                MaxDegreeOfParallelism = 2,
                CancellationToken = cancellationTokenSource.Token
            };

            //开始运行循环
            Debug.Log($"Start Run Parallel.ForEach : {length}");
            Task.Run(() =>
            {
                var result = Parallel.ForEach(L, options, (i, state) =>
                 { 
                     //等待 100 ms
                     Thread.Sleep(100);                     
                     Debug.Log($"Log {L[i]} In Task :{Task.CurrentId}");                    
                 });
                Debug.Log($"Parallel.ForEach End  : {result.IsCompleted} | {result.LowestBreakIteration}");
            });

            //等待250 ms 后取消循环
            Task.Run(async () =>
            {
                await Task.Delay(250);
                cancellationTokenSource.Cancel();
                Debug.Log("Cancel Token !");
            });
        }

        同样的,并行度为2。但这次代码上做了修改:之前的代码其实会在主线程同步,这次我们放到 Task 中执行循环任务,并且每打印一个值等待100ms。之后取消令牌也是在 Task 中执行,等待250ms 之后取消。

        直接从代码上来推理,上述循环在打印了到第3次(200ms开始,300ms 结束)时,在 Sleep 的过程中,就已经取消任务了。由于已经安排的任务仍然会执行,因此第3次打印会生效,但第四次打印则不会执行:

         可见打印结果和预期一致。

        但值得注意的是:Parallel.ForEach End 这一行打印(24行)并没有打印出来!也就是取消令牌是直接取消了整个线程,而不是单单取消了循环


        未完待续。

        本教程对应学习工程:魔术师Dix / HandsOnParallelProgramming · GitCode        

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

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

相关文章

Unity协程

unity提供了一种类似“多段代码并行执行”的功能,即协程。 我们在定义一个协程的时候,需要遵循类似这样的语法 IEnumerator(枚举器接口) namespace System.Collections {public interface IEnumerator{object Current { get; }/…

卷积神经网络--猫狗系列【VGG16】

数据集:【文末】 ​ 数据集预处理 定义读取数据辅助类(继承torch.utils.data.Dataset) import osimport PILimport torchimport torchvisionimport matplotlib.pyplot as pltimport torch.utils.dataimport PIL.Image # 数据集路径train_p…

哈希桶的增删查改简单实现

个人简单笔记。 目录 闭散列 开散列 插入 删除 查找 改变 什么是哈希桶呢?这是一个解决哈希数据结构的一种解决方法,在STL中的unorder_map与unorder_set的底层结构就是使用它来实现的。 闭散列 首先我们知道,哈希映射表是依据数组下…

CSS画特殊边框

例如如图所示边框 .card-middle {width: 672px;height: 486px;border: 1px solid #5fadec;border-radius: 5px;position: relative; }.card-middle::before {content: ;position: absolute;top: -4px;left: -4px;width: 680px;height: 448px;border: 25px solid transparent;b…

【Python】PIL.Image转QPixmap后运行异常的个人解决方法

问题场景: PIL.Image图片,直接调用PIL.Image.toqpixmap()转成QPixmap后,不会立即报错,   但后续使用该QPixmap时(包括但不仅限于使用QLabel.setPximap()、QPixmap.save())将立即出现异常 不知道是我关键词不对,还是只…

【数据结构与算法】文学语言助手(C\C++)

实践要求 1. 问题描述 文学研究人员需要统计某篇英文小说中某些形容词的出现次数和位置。试写一个实现这一目标的文字统计系统,称为"文学研究助手"。 2. 基本要求 英文小说存于文本文件中。待统计的词汇集合要一次输入完毕,即统计工作必需在…

linux常用命令介绍 06 篇——Linux查看目录层级结构以及创建不同情况的层级目录

linux常用命令介绍 06 篇——Linux查看目录层级结构以及创建不同情况的层级目录 1. 前言1.1 Linux常用命令其他篇1.2 关于tree简介 2. 安装并使用 tree2.1 安装tree2.1.1 方式1:yum安装2.1.2 方式2:下载安装包安装2.1.2.1 下载安装包2.1.2.2 解压安装2.1…

transformer入坑指南

*免责声明: 1\此方法仅提供参考 2\搬了其他博主的操作方法,以贴上路径. 3* 场景一: Attention is all you need 场景二: VIT 场景三: Swin v1 场景四: Swin v2 场景五: SETR 场景六: TransUNet 场景七: SegFormer 场景八: PVT 场景九: Segmeter … 场景一:Attention…

Spring Boot 中的 Spring Cloud Ribbon:什么是它,原理及如何使用

Spring Boot 中的 Spring Cloud Ribbon:什么是它,原理及如何使用 在分布式系统中,服务之间的通信是非常重要的。在大型的分布式系统中,有许多服务需要相互通信,而这些服务可能会部署在多个服务器上。为了实现服务之间…

超详细Redis入门教程——Redis分布式系统

前言 本文小新为大家带来 Redis分布式系统 相关知识,具体内容包括数据分区算法(包括:顺序分区,哈希分区),系统搭建与运行(包括:系统搭建,系统启动与关闭)&…

把 OpenGrok search 上的Android 开源代码扒下来

1、下载工具 wget (window10版本)以及配置环境变量 工具我会上传到本篇博客的“代码包”区域,可以自行下载! 当然如果可以访问如下链接的话,也可以在这个地址自行下载一个比较新的版本即可!GNU Wget 1.21.…

Web服务器群集:LVS+Keepalived高可用群集

目录 一、理论 1.Keepalived 2.VRRP协议(虚拟路由冗余协议) 3.部署LVSKeepalived 高可用群集 二、实验 1.LVSKeepalived 高可用群集 三、问题 1.备服务器网卡启动报错 四、总结 一、理论 1.Keepalived (1)简介 Keepal…

【动态规划算法】-第一题:1137.第N个斐波那契数

💖作者:小树苗渴望变成参天大树 🎉作者宣言:认真写好每一篇博客 🎊作者gitee:gitee 如 果 你 喜 欢 作 者 的 文 章 ,就 给 作 者 点 点 关 注 吧! 文章目录 前言 前言 各位友友们&#xff0c…

element之el-table合并列功能

目标效果如下&#xff1a; 实现代码如下&#xff1a; html部分&#xff1a; <!--定义表格组件,用组件自带的span-method属性定义合并列的方法--> <el-table :data"tableData" :span-method"spanRow"><el-table-column prop"RegionNa…

在proteus中仿真arduino驱动点阵屏matrix-led

我们都知道&#xff0c;如果我们仅仅在某个时间段点亮一个数码管是没有任何困难的&#xff0c;但如果我们点亮多个数码管就会出现问题&#xff0c;因为多个数码管都使用着同样的端口来控制数码管的各个段的亮灭。所以&#xff0c;就会用上一个很重要的方法&#xff0c;对&#…

使用javaScript脚本生成openFoam网格

简介 OpenFoam的首选网格生成器是blockMesh。blockMesh可以根据blockMeshDict这个字典中的信息生成openFoam网格。但是有时候需要修改网格&#xff0c;而网格中的几何点之间又存在约束关系&#xff0c;如果手动修改blockMeshDict那么工作量将是巨大的&#xff0c;所以有必要使…

有没有免费提取音频的软件,分享几个给大家!

在日常生活中&#xff0c;我们经常遇到需要从视频中提取音频的情况&#xff0c;无论是为了制作音频片段、录制语音笔记还是进行后期编辑。本文将介绍三种免费提取音频的方法&#xff0c;分别是记灵在线工具、PR&#xff08;Adobe Premiere Pro&#xff09;和剪映。通过这些方法…

【Vue3】学习笔记-自定义hook函数

概念 什么是hook? 本质是一个函数&#xff0c;把setup函数中使用的Composition API进行了封装。 类似于vue2.x中的mixin。(但是mixins会组件的配置项覆盖。vue3使用了自定义hooks替代mixnins&#xff0c;hooks本质上是函数&#xff0c;引入调用。) 自定义hook的优势: 复用代…

PPU (power policy unit)

写在前边 最近在做低功耗验证&#xff0c;项目中涉及到PPU这一块儿&#xff0c;在家查了好久资料&#xff0c;发现能找到的有价值的文章真的好少&#xff0c;机缘巧合之下&#xff0c;让我找到下边总结&#xff0c;分享出来&#xff0c;希望对和我有相同境遇的小伙伴带来帮助&a…

每周学点数学 2:概率论基础1

泊松分布、正态分布、二项分布 文章目录 1.概率论学习中的重难点2.主要工具介绍1. Python2. MATLAB3. R4. Octave5. Microsoft Excel6. 统计软件 3.理论内容概览&#xff08;前两点&#xff09;1. 概率2. 概率分布 注&#xff1a;本文适用于在在数学建模的应用中&#xff0c;回…