【C#】并行编程实战:使用 PLINQ(3)

news2024/7/6 18:35:44

        PLINQ 是语言集成查询(Language Integrate Query , LINQ)的并行实现(P 表示并行)。本章将继续介绍其编程的各个方面以及与之相关的一些优缺点。

        本文的主要内容为 PLINQ 中的组合并行和顺序 LINQ 查询、取消 PLINQ 查询、使用 PLINQ 进行并行编程时要考虑的事项和影响 PLINQ 性能的因素。

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


6、组合并行和顺序 LINQ 查询

        有时,我们可能会希望顺序执行运算符,这时就可以使用 AsSequential 方法强制 PLINQ 按顺序执行。一旦该方法用于任何并行查询,之后的运算符就会按照顺序执行

        这个示例已经在 2.2、顺序查询 里有所展示,这里就不再赘述。

如何:合并并行和顺序 LINQ 查询 | Microsoft Learn详细了解:如何:合并并行和顺序 LINQ 查询https://learn.microsoft.com/zh-cn/dotnet/standard/parallel-programming/how-to-combine-parallel-and-sequential-linq-queries

7、取消 PLINQ 查询

        可以使用 CancellationTokenSource 和 CancellationToken 类取消 PLINQ 查询。

        CancellationToken (取消令牌)将使用 WithCancellation 子语句传递到 PLINQ 查询,然后可以调用 CancellationToken.Cancel 方法取消查询操作。在取消之后,将抛出 OperationCanceledException 异常。

        代码示例如下:

        private void RunWithCancellationTokenSource()
        {
            //由外部设置最大并行度。
            int degreeOfParallelism = commonPanel.GetInt32Parameter();
            Debug.Log($"设置并行度为:{degreeOfParallelism}");

            //使用取消令牌
            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();

            var range = Enumerable.Range(1, 10000).AsParallel()
                .WithCancellation(cancellationTokenSource.Token)
                .WithDegreeOfParallelism(degreeOfParallelism)
                .Select(x =>x);

            try
            {
                range.ForAll(x =>
                {
                    if (x == 5)
                    {
                        cancellationTokenSource.Cancel();
                        Debug.Log("Cancel PLINQ !");
                    }
                    else
                    {
                        Debug.Log($"PLINQ Is Running : {x}");
                    }
                });
            }
            catch (AggregateException ex)
            {
                foreach (var item in ex.InnerExceptions)
                {
                    Debug.LogError(item.InnerException);
                }
            }
        }

        在我的电脑上运行结果如下:

         仍然执行了 64 次 Select 语句,并且最后抛出了异常:

         值得一提的是,如果将整段代码放到 Task.Run 语句里,则是不会抛出异常的,因为 TryCatch 是不会跨线程生效的。

8、使用 PLINQ 进行并行编程时要考虑的事项

        在大多数情况下,PLINQ 的性能比费并行同类产品 LINQ 要快得多。但是,它也存在一些性能开销,这与在并行化 LINQ 时进行的分区和合并有关。以下是使用 PLINQ 时需要考虑的一些事项:

  • 合并执行并不意味着一定更快并行化本身也需要开销,因此,除非你的源集合很大,或者操作需要大量的计算,否则按顺序执行这些操作更有意义。可以通过衡量顺序查询和并行查询的性能来做出明智的决定。

  • 避免涉及原子性的 I/O 操作在 PLINQ 内部应避免所有涉及写入文件系统、数据库、网络或共享内存位置的 I/O 操作。其原因在于,这些方法不是线程安全(Thread-Safe)的,因此使用他们可能会导致异常。一种解决方案是使用同步原语,但这也会大大降低性能。

  • 查询并不一定总是并行运行的PLINQ 中的并行化是由公共语言运行时(CLR)做出的决定。即便在查询中调用了 AsParallel 方法,它也不保证采用并行路径,同样有可能顺序运行。

9、影响 PLINQ 性能的因素

        PLINQ 的主要目的是通过拆分任务并按并行方式执行来加速查询执行的。但是,有很多因素都会影响 PLINQ 的性能。其中包括与分块有关的同步开销,以及调度和收集线程结果的开销。

        在理想的并行场景中,线程不必共享状态,也不必担心执行顺序。

9.1、并行度

        由于 TPL 确保多个任务可以在多个内核上同时执行,因此我们可以使用更多数量的内核,从而显著提高性能。性能的提高可能不会是指数级的,并且在调整性能时,我们也应该尝试在具有多个内核的不同系统上运行比较结果。

9.2、合并选项

        在某些应用场景中,结果经常变化,并且用户希望尽快看到结果而无需等待。在这些情况下,合并选项可以显著改善用户体验。PLINQ 默认选项是缓冲结果(AutoBuffered),然后将其合并以返回用户。我们可以通过选择适当的合并选项来修改此行为。

9.3、分区类型

        我们应始终检查分区的工作项目是否平衡。对于不平和的工作项目,可以引入自定义分区以提高性能。

PLINQ 和 TPL 的自定义分区程序 | Microsoft Learn详细了解:PLINQ 和 TPL 的自定义分区程序https://learn.microsoft.com/zh-cn/dotnet/standard/parallel-programming/custom-partitioners-for-plinq-and-tpl        PS:我个人认为自定义分区程序是一个很重要的功能点,但是上一章并没有详细深入地讲解,我也没有仔细学习这部分。我不知道后面的章节是否会详细讲解自定义分区,如果没有的话,我会考虑单独开一章来学习一下如何编写自定义分区程序。

如何:实现动态分区 | Microsoft Learn详细了解:如何实现动态分区https://learn.microsoft.com/zh-cn/dotnet/standard/parallel-programming/how-to-implement-dynamic-partitions

9.4、确定是保持顺序还是转向并行

        我们应该始终计算出每个工作项以及整个操作的整体计算成本,以便可以决定是保持顺序执行还是转向并行。由于分区、调度等产生的额外开销,并行查询不一定是最快的。

        计算成本的公式:

        计算成本 = 执行1个工作项目的而成本 * 工作项目的总数 + 并行开销

        PLINQ 决定是采用顺序执行还是并行执行取决于查询中运算符的组合。

        可以参考使用并发可视化工具来辅助性能衡量:

并发可视化工具 - Visual Studio (Windows) | Microsoft Learn使用并发可视化工具查看多线程应用中显示线程计时的图形,从而帮助你解决性能问题。https://learn.microsoft.com/zh-cn/visualstudio/profiling/concurrency-visualizer?view=vs-2022

9.5、操作顺序

        PLINQ 可为无序集合提供更好的性能,因为使集合按照有序方式执行是会产生性能成本的。该性能成本包括分区、调度和收集结果,以及调用 GroupJoin 和过滤器。

        简单地说,就是能无序就无序,尽量不要使用类似 AsOrdered 的顺序执行方法。

9.6、使用 ForAll

        调用 ToList 、 ToArray 或在循环中枚举结果时,实际上是强制 PLINQ 将来自所有并行线程的结果合并为单个数据结构,这也会产生性能开销。因此,如果只想对一组项目执行某些操作,最好使用 ForAll 方法。

9.7、强制并行

        PLINQ 不保证每次都以并行方式执行,我们可以使用 WithExecutionMode 来对此进行控制。示例代码如下:

        private void ForceToParallel()
        {
            var range = Enumerable.Range(1, 10);
            var squares = range.AsParallel()
                .WithExecutionMode(ParallelExecutionMode.ForceParallelism)
                .Select(x => x * x)
                .ToList();

            squares.ForEach(x =>
            {
                Debug.Log(x);
            });
        }

PS :WithExecutionMode 会被 AsOrderd 之类的函数给覆盖掉。


10、本章小节

        本章介绍了有关 PLINQ 的基础知识,然后讨论了如何使用 PLINQ 编写并行查询。这一章节其实很有用了,因为针对列表的操作在工作中是经常用到的。大部分情况下,列表中的小操作耗时并不多,但是遍历量太大在主线程扛不住,此时用并行查询是最好的。

        当然,何时使用并行,何时顺序,需要大家在工作中实际检验。

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

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

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

相关文章

Azure AD混合部署,实现在本地AD同步到AAD上面

一、前期准备 1、进入 Azure云 注册一个账号 云计算服务 | Microsoft Azure 2、进入 AAD 管理后台 Microsoft Azure 3、创建一个新的租户 4、添加自定义域名,这里要做下验证,所以你要有个线上的域名 5、创建一个全局管理员 6、登陆本地AD,创…

第133页的gtk+编程例子——计算器应用改写网上的例子

第133页的gtk编程例子——计算器应用改写网上的例子 来源:《GTK的计算器》 https://blog.csdn.net/zhouzhouzf/article/details/17097999 重点在于它的设计思路是比较巧妙的,能够处理多种情况,比较容易理解,也感到人类的思想是非…

Java进程ProcessBuilder类的介绍及使用,ProcessBuilder调用外部程序执行shell命令Linux命令

目录 ProcessBuilder类的介绍及使用 【前言】 【正文】 --构造方法-- --常用方法-- --使用技巧-- --调用本地Shell命令,实例-- 【总结】 【注意】 ProcessBuilder类的介绍及使用 【前言】 在做一个项目的时候需要用到运行时动态执行JAVA命令,一…

常用数据聚类算法总结记录与代码实现[K-means/层次聚类/DBSACN/高斯混合模型(GMM)/密度峰值聚类/均值漂移聚类/谱聚类等]

本文的主要目的是总结记录日常学习工作中常用到的一些数据聚类算法,对其原理简单总结记录,同时分析对应的优缺点,以后需要的时候可以直接翻看,避免每次都要查询浪费时间,欢迎补充。 聚类算法是一种无监督学习的方法&am…

chrales过期重装或使用途中的踩坑记录及使用方法

1、背景 我的是证书过期了,提示无网络。 1. 重新下载 安装(或者 不需要重新下载安装,用已有的就可以) 2. 重新进行配置 3. (关键)检查电脑上的 证书过期时间 4. (关键)检查手机上的证书过期时间 5. (手机配置好后,点开链接显示无网络&#…

Android:简单登录界面

一、前言&#xff1a;这个登陆界面我前前后后写了差不多一个星期&#xff0c;主要有密码登录、验证码登录、键盘自动隐藏、忘记密码、新建密码等功能&#xff0c;你们可以自己研究一下&#xff01; 二、上代码&#xff1a; 资源文件 1.在value包下面添加一个dimens.xml <…

对性能测试评估分析优化市场的反思

目录 前言&#xff1a; 性能市场的现状 性能测试人员的价值体现 年龄和加班 性能行业的出路 前言&#xff1a; 性能测试评估分析和优化是一个关键的环节&#xff0c;它可以帮助我们了解系统的性能瓶颈和潜在问题&#xff0c;并提出相应的优化方案。在市场竞争激烈的环境下…

Cesium 实战 - AGI_articulations 扩展:模型自定义关节动作

Cesium 实战 - AGI_articulations 扩展&#xff1a;模型自定义关节动作 简要概述两种方式实现模型组件动作模型添加关节&#xff08;articulations&#xff09;1.导入模型&#xff08;J15.glb&#xff09;2.查看模型内部组件信息&#xff08;名称&#xff09;4.将需要J15.glb复…

Docker常见命令(以备不时之需)

参考官网&#xff1a;https://docs.docker.com/engine/reference/commandline/cli/ 帮助启动类命令 启动docker&#xff1a; systemctl start docker 停止docker&#xff1a; systemctl stop docker 重启docker&#xff1a; systemctl restart docker 查看docker状态&…

架构训练营笔记系列:面向复杂度的设计

面向复杂度的设计 DDD 是可扩展架构的设计技巧&#xff0c;不是架构方法论。不关注高性能、高可靠。 架构本质&#xff1a;为了降低软件系统复杂度 怎么做架构设计 &#xff1f;思路是分析系统需求找到系统复杂的地方&#xff0c;然后设计方案。 复杂度相关有哪些&#xff1…

Unity的PostProcessing后处理使用介绍

大家好&#xff0c;我是阿赵。 上一篇文章说了Unity的PostProcessing后处理有bug并提供了解决办法&#xff0c;这里顺便介绍一下PostProcessing的用法。 一、安装 打开PackageManager&#xff0c;然后搜索Post&#xff0c;应该就能看到左边出现搜索结果&#xff0c;选择&…

一个人的面相能直接反映其个性与命运

中国传统文化&#xff0c;博大精深&#xff0c;面相学只是其中一种。 在古代&#xff0c;面相学却是一门非常实用的学科&#xff0c; 尤其是经过了一代代人的发展&#xff0c;面相学得到了完善之后&#xff0c;他的准确性往往会超过现代人的预料。相由心生&#xff0c;面相是对…

用户端App 测试方法与技术

目录&#xff1a; app测试体系app项目测试流程app结构讲解app测试设计思路app常见bug解析常用模拟器使用android开发者选项安装mumu模拟器adb命令介绍adb环境搭建与配置adb与设备交互adb安装卸载应用adb命令启动页面adb命令清缓存adb文件传输adb日志操作adb命令操作Android设备…

DRF+Vue.JS前后端分离项目实例(下) --- Vue.js 前端实现代码

本文上篇请 点击阅读 1. 需求说明 本文以学生信息查询功能为例&#xff0c;采用前后端分离架构&#xff0c;后端提供RESTFul 接口&#xff0c;前端代码用Vue.js Bottstrap实现。 1.1 本例要求提供如下查询功能&#xff1a; 列表查询、单条查询 添加学生信息 更改学生信息 删…

在线试用Stable Diffusion生成可爱的图片

文章目录 一、 Stable Diffusion 模型在线使用地址&#xff1a;二、模型相关版本和参数配置&#xff1a;三、图片生成提示词与反向提示词&#xff1a;提示词1提示词2提示词3提示词4提示词5 一、 Stable Diffusion 模型在线使用地址&#xff1a; https://inscode.csdn.net/insc…

python 读取npy文件

import numpy as np test np.load("I:/软件/mask.npy") print(test) 如下图所示&#xff1a;

Web3 智能合约通过数组方式存储更多学生数据

之前的文章 Web3 在Truffle项目中编写出自己的第一个solidity智能合约带大家写了一个相对捡漏的智能合约 这样 每次 我们set 后 都会将原来的数据覆盖掉了 那么 有些人可能会想 那我们弄个数组 将新的数据全部加到数组里不就行了吗&#xff1f; 这个想法其实就很不错 我们可以…

数据结构与算法--javascript(持续更新中...)

一. 概论 1. 数据结构 队列&#xff1a;一种遵循先进先出 (FIFO / First In First Out) 原则的一组有序的项&#xff1b;队列在尾部添加新元素&#xff0c;并从头部移除元素。最新添加的元素必须排在队列的末尾。&#xff08;例如&#xff1a;去食堂排队打饭&#xff0c;排在前…

JsonView下载安装

文章目录 一、JsonView概述二、JsonView下载三、JsonView安装四、JsonView测试 一、JsonView概述 SONView是一款非常好用的Json格式查看器。在日常开发调试中经常会遇到Json格式的数据需要解析阅读&#xff0c;但Json格式数据阅读性极差&#xff0c;JSONView可以帮我们解决Jso…