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

         本章继续学习实现数据并行,本文主要介绍并行循环中的线程存储。这也是本章节的最后一篇。

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


5、了解并行循环中的线程存储

        默认情况下,所有并行循环都可以访问全局变量。但是,访问全局变量是有同步开销的,因此,尽可能使用线程内局部变量是有意义的。在并行循环中,可以创建和使用线程局部变量(Thread Local Varable,也称为线程本地变量)或分区局部变量(Partition Local Variable,也称分区本地变量)。

5.1、线程局部变量(Thread Local Varable)

        这里用到了一个 Parallel.For 的一个重载:

Parallel.For 方法 (System.Threading.Tasks) | Microsoft Learn执行 for 循环,其中可能会并行运行迭代。 icon-default.png?t=N5K3https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.parallel.for?view=netstandard-2.1#system-threading-tasks-parallel-for-1(system-int64-system-int64-system-threading-tasks-paralleloptions-system-func((-0))-system-func((system-int64-system-threading-tasks-parallelloopstate-0-0))-system-action((-0)))        示例代码如下:

        private void RunByThreadLocalVarable()
        {
            var options = new ParallelOptions { MaxDegreeOfParallelism = 3 };//最大并行度3
            Parallel.For(0, 11, options,//从0开始循环,循环11次(到10结束)
                () => 100,//第一次循环时的初始值
                (i, loop, ret) =>
                {
                    ret += i;
                    return ret;//返回给下一次循环的值
                }, TestFunction.OnTaskFinish);//最后运行完成的回调
        }

        迭代里面的方法很简单,就是单纯地累加。从0加到10,显然就是55。但是我们给每次循环的初始值是100,也就是每次迭代开始,就会从100开始计数。然后最大并行度为3,也就是最多会有 3 次线程并行。根据上述代码,我们人脑编译一下,运行结果应该是 100+100+100+55=355 (如果并行了3次)。

        跑一下代码:

         结果为 :134+100+121=355,与理论相同。

5.2、分区局部变量(Partition Local Variable)

        分区局部变量与线程局部变量类似,区别在于其可以用于分区,这次用到的重载是这个:

Parallel.ForEach 方法 (System.Threading.Tasks) | Microsoft Learn执行 foreach(在 Visual Basic 中为 For Each )操作,其中可能会并行运行迭代。 icon-default.png?t=N5K3https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.parallel.foreach?view=netstandard-2.1#system-threading-tasks-parallel-foreach-2(system-collections-concurrent-partitioner((-0))-system-threading-tasks-paralleloptions-system-func((-1))-system-func((-0-system-threading-tasks-parallelloopstate-1-1))-system-action((-1)))        这次需要加一个 Partitioner 的测试代码:

using System.Collections.Concurrent;
using System.Collections.Generic;
using UnityEngine;

namespace HOPP.Ch03
{
    /// <summary>
    /// 测试用分区局部变量
    /// </summary>
    public class PartitionerTest : Partitioner<List<int>>
    {

        //这里共享一个列表,以观察线程竞争
        private List<int> L = new List<int>();

        public override bool SupportsDynamicPartitions => true;

        //这个方法在此示例中没有被调用过
        public override IList<IEnumerator<List<int>>> GetPartitions(int partitionCount)
        {
            Debug.Log($" GetPartitions {L.Count} | {partitionCount}");
            for (int i = 0; i < 10; i++)
                L.Add(i);
            return (IList<IEnumerator<List<int>>>)L;
        }

        //迭代:每次调用就添加一个值;
        public override IEnumerable<List<int>> GetDynamicPartitions()
        {
            Debug.Log($"GetDynamicPartitions Start: {L.Count}");
            for (int i = 0; i < 10; i++)
            {
                L.Add(i);
                Debug.Log("Add Value : " + i);
                //Debug.Log($" GetDynamicPartitions {L.Count} ");
                yield return L;
            }

            Debug.Log($" GetDynamicPartitions  Last: {L.Count} ");
            yield return L;
        }

    }
}

Partitioner表示将数据源拆分为多个分区的特定方式。 icon-default.png?t=N5K3https://learn.microsoft.com/zh-cn/dotnet/api/system.collections.concurrent.partitioner-1?view=netstandard-2.1        之后我们开始调用:

        private void RunByPartitionLocalVarable()
        {
            var partitioner = new PartitionerTest();
            var options = new ParallelOptions { MaxDegreeOfParallelism = 3 };//最大并行度3
            Parallel.ForEach(partitioner,
                options,
                () => 0,//第一次迭代时的初始值
                (L, loop, ret) =>
                {
                    //每次都将列表中的值汇总
                    ret = 0;
                    foreach (var item in L)
                        ret += item;
                    return ret;//返回给下一次循环的值
                }, TestFunction.OnTaskFinish);//最后运行完成的回调
        }

        可以想象的是,因为线程竞争,所以3次并行的结果都会有所差别,实际也是如此。我们直接看最后的结果打印:

         2个线程同步执行完成,打印出了结果105,最后一个线程结果135,最后一个完成。


本章总结

        本章详细介绍了使用任务并行库(TPL)实现数据并行的方式。

        这一章的实用性也很强了,而且已经开始涉及到数据的处理,但是这里还没有讲如何处理线程竞争的问题。不过通过这一章的学习,相信大家对多线程的运行模式已经有了更为深刻的理解。

        虽然本章提到了怎么分区,但是并没有很深入。要用好各种分区、局部变量策略,还需要继续深入学习。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

香橙派4和树莓派4B构建K8S集群实践之八: TiDB

目录 1. 说明 2. 准备工作 3. 安装 3.1 参考Tidb官方 v1.5安装说明 3.2 准备存储类 3.3 创建crd 3.4 执行operator 3.5 创建cluster/dashboard/monitor容器组 3.6 设置访问入口(Ingress & Port) 4. 装好后的容器状况 5. 遇到的问题 6. 参考 1. 说明 建立TiDB…

全志F1C200S嵌入式驱动开发(串口驱动)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 对于uboot、kernel和rootfs来说,他们的串口输出一般都是uart0。一般这么做,是没有问题的。只不过我们自己买的这块f1c200s电路板,设计者把uart转ttl的接口,改接到了uart1上面。…

微信小程序下拉选择

微信小程序中下拉框选择一般的交互方式有以下两种 直接下拉选择点击选择框后&#xff0c;弹出浮层进行选择 下边分别介绍两种方式的实现。在微信小程序中&#xff0c;这两种实现都需要修改三个文件 js 文件&#xff1a;下拉选择逻辑的具体实现 wxml 文件&#xff1a;下拉组件…

1、linux中安装tomcat

1、创建目录 cd /opt ls mkdir tomcat 2、将文件拖入tomcat目录中 3、解压安装包 cd /opt/tomcat ls tar -zxvf apache-tomcat-8.5.59.tar.gz 4、启动tomcat cd /opt/tomcat/apache-tomcat-8.5.59/bin ./startup.sh 5、在linux中访问 http://localhost:8080/ 6、开放端口 …

生成式AI管理规则落地 大模型后时代到来

国家网信办等七部门联合颁布的《生成式人工智能服务管理暂行办法》&#xff0c;给中国生成式AI产业树立了发展规范。 这份监管文件的用意并不止于管控&#xff0c;还用大量的笔墨传递出推动产业发展的原则&#xff0c;尤其强调“鼓励生成式人工智能技术在各行业、各领域的创新…

基于springboot,vue网上订餐系统

开发工具&#xff1a;IDEA 服务器&#xff1a;Tomcat9.0&#xff0c; jdk1.8 项目构建&#xff1a;maven 数据库&#xff1a;mysql5.7 前端技术 &#xff1a;VueElementUI 服务端技术&#xff1a;springbootmybatisredis 本系统分用户前台和管理后台两部分&#xff0c;项…

Docker(三)之容器管理工具 Docker生态架构及部署

容器管理工具Docker生态架构及部署 一、Docker生态架构 1.1 Docker Containers Are Everywhere 1.2 生态架构 1.2.1 Docker Host 用于安装Docker daemon的主机&#xff0c;即为Docker Host&#xff0c;并且该主机中可基于容器镜像运行容器。 1.2.2 Docker daemon 用于管理…

ASP.NET Website 项目 .NET Framework 4.0 ~ .NET Framework 4.8支持c#哪些版本(Website)

本文讲的是Website网站项目&#xff0c;由于维护老项目Website .net framework4.0&#xff0c;遇到c#6.0语法不支持。便做了点记录 ASP.NET Website 项目 .NET Framework 4.0、 .NET Framework 4.5、 .NET Framework 4.6、 .NET Framework 4.8都支持c#哪些版本&#xff1f; 下面…

【SQL】Your password has expired. To log in you must change it.......

在配置SQL的编辑器的时候&#xff0c;连接过程出现了如下的错误&#xff1a; Your password has expired. To log in you must change it using a client that supports expired passwords.当连接到 SQL 时&#xff0c;如果出现 “Your password has expired. To log in you m…

SpringBoot+React学科竞赛管理系统 附带详细运行指导视频

文章目录 一、项目演示二、项目介绍三、运行截图四、主要代码 一、项目演示 项目演示地址&#xff1a; 视频地址 二、项目介绍 项目描述&#xff1a;这是一个基于SpringBootReact框架开发的学科竞赛管理系统。首先&#xff0c;这是一个前后端分离的项目&#xff0c;代码简洁…

Mars3d采用ellipsoid球实现模拟地球旋转效果

1.Mars3d采用ellipsoid球实现模拟地球旋转效果 2.开始自选装之后&#xff0c;模型一直闪烁 http://mars3d.cn/editor-vue.html?idgraphic/entity/ellipsoid 3.相关代码&#xff1a; import * as mars3d from "mars3d"export let map // mars3d.Map三维地图对象 …

MATLAB | 爱心图例与精致半透明圆角图例

本文中全部示意图均为本人自制&#xff0c;传播时请注明出处。 写了点小成品函数&#xff0c;比如如何绘制饼图时把图例上的图标变成心形&#xff1a; 比如如何自制半透明圆角图例&#xff1a; 依旧先讲原理再给出这俩代码哈&#xff1a; 1 原理讲解-图形对象 封闭四边形对…

Vue项目搭建过程

Vue项目搭建过程 1、安装NodeJs 1.1 下载安装包 在 http://nodejs.cn/download/ 上下载64位安装包&#xff0c;然后进行安装&#xff0c;和普通软件的安装一样。 C:\Users\Administrator>node -v v16.13.1C:\Users\Administrator>npm -v 8.5.51.2 安装cnpm # 安装cn…

DNS 是如何影响你冲浪速度的?

本文详细介绍了 DNS 相关知识&#xff0c;包括 DNS 工作原理、如何提升域名解析速度、以及 DNS 记录与报文等内容。 1. 域名与域名服务器 在日常上网过程中&#xff0c;出于好记的原因&#xff0c;人们更喜欢在浏览器中输入网站的域名&#xff0c;而不是 IP 地址。比如想要访问…

CV常用注意力机制总结

本文总结了近几年CV领域常用的注意力机制&#xff0c;包括&#xff1a;SE&#xff08;Squeeze and Excitation&#xff09;、ECA&#xff08;Efficient Channel Attention&#xff09;、CBAM&#xff08;Convolutional Block Attention Module&#xff09;、CA&#xff08;Coor…

切换.net Framework 版本后,出现NuGet 包是使用不同于当前目标框架的目标框架安装的,可能需要重新安装

问题现象&#xff1a; 由于添加新的dll文件&#xff0c;依赖的.NET Framework版本与当前的不一致&#xff0c;在vs 中切换了目标框架版本后&#xff0c;运行程序&#xff0c;出现以下的warnning信息&#xff1a; 一些 NuGet 包是使用不同于当前目标框架的目标框架安装的&#…

MacOS系统(M1/M2)安装AI绘画StableDiffusion保姆级教程

TOC 安装完成后&#xff0c;推荐阅读这篇教程&#xff1a;AI绘画&#xff1a;Stable Diffusion 终极炼丹宝典&#xff1a;从入门到精通 实操环境&#xff1a; macOS 13 Arm64&#xff08;建议12以上的系统使用&#xff09; Apple M1 先来看几个样例&#xff1a; AI绘画S…

SDN系统方法 | 1. 概述

随着互联网和数据中心流量的爆炸式增长&#xff0c;SDN已经逐步取代静态路由交换设备成为构建网络的主流方式&#xff0c;本系列是免费电子书《Software-Defined Networks: A Systems Approach》的中文版&#xff0c;完整介绍了SDN的概念、原理、架构和实现方式。原文: Softwar…

MongoDB负载均衡集群监控

对负载均衡的集群监控&#xff0c;不仅仅集中在对集群所有的资源、服务等进行监控&#xff0c;还要兼顾整体逻辑。以MongoDB高可用负载均衡集群为例&#xff0c;对逻辑层面的监控&#xff0c;就是模拟用户行为&#xff0c;访问集群数据&#xff0c;判断运行状态是否正常。 Mong…

数据库用户管理

数据库用户管理 一、创建&#xff1a; 1.新建用户&#xff1a; CREATE USER 用户名来源地址 [IDENTIFIED BY [PASSWORD] 密码];‘用户名’&#xff1a;指定将创建的用户名. ‘来源地址’&#xff1a;指定新创建的用户可在哪些主机上登录&#xff0c;可使用IP地址、网段、主机…