三分钟总览微软任务并行库TPL

简介: 今天探讨下我对.NET并行编程库Task Parallel Library的理解,开足马力,准备压榨CPU了。

技术背景


硬件线程和软件线程


多核处理器带有一个以上的物理内核:物理内核是真正的独立处理单元,多个物理内核使得多条指令能够同时并行运行。


硬件线程也称为逻辑内核,一个物理内核可能会使用超线程技术提供多个硬件线程,所以一个硬件线程并不代表一个物理内核。


程序通过Environment.ProcessorCount 得到的就是逻辑内核(本人的机器是i5-5300U 虚拟4核), Windows中每个运行的程序都是一个进程,每一个进程都会创建并运行一个或多个线程,这些线程称为软件线程,硬件线程就像是一条泳道,而软件线程就是在其中游泳的人。


并行场


.NET引入的Task Parallel Library(任务并行库,TPL),动态地扩展并发度,以最有效的方式使用所有可用的处理器。


另外TPL支持分区工作、支持基于ThreadPool调度、支持取消异步操作、支持状态管理。

通过TPL专注与让程序完成你业务意义上的任务,同时最大限度的提高程序性能。


TPL同时支持数据并行、任务并行和流水线Dataflow


1.数据并行:有大量数据需要处理,并且必须对每一份数据执行同样的操作;


2.任务并行:通过任务并发运行不同的操作;


3.流水线:任务并行和数据并行的结合体(需要引入System.Threading.Tasks.Dataflow组件库)


其中1、3 已经在上文演示,本文就随手拿数据并行、任务并行聊一聊。


编程实践


1. 数据并行


找到100000以内素数的个数


上文[共享内存并发模型],代码可做如下优化:


由每个线程独立计算线程内迭代产生的素数和,最后再对几个和求和


using System;
using System.Threading.Tasks;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
/// <summary>
/// 利用并行编程库Parallel,计算100000内素数的个数
/// </summary>
namespace Paralleler
{
    class Program
    {
        static void Main(string[] args)
        {
            Stopwatch sw = new Stopwatch();
            sw.Start();
            ShareMemory();
            sw.Stop();
            Console.WriteLine($"优化后的共享内存并发模型耗时:{sw.Elapsed}");
        }
        static void ShareMemory()
        {
            var sum = 0;
            Parallel.For(1, 100000 + 1, () => 0, (x, state, local) =>
            {
                var f = true;
                if (x == 1)
                    f = false;
                for (int i = 2; i <= x / 2; i++)
                {
                    if (x % i == 0)  // 被[2,x/2]任一数字整除,就不是质数
                        f = false;
                }
                if (f == true)
                    local++;
                return local;
            },
                 local =>
                 {
                     Interlocked.Add(ref sum, local);
                 }
               );
            Console.WriteLine($"1-100000内质数的个数是{sum}");
        }
    }
}


参数1,2 表示数据并行要操作的对象;


参数3localInit表示某线程内迭代的初始值,将会作为参数4body委托的第3个参数,只在线程第一次使用;


参数4body表示每个迭代都需要经历的执行体, 这里以线程为单元处理迭代;


2. 任务并行


 让许多方法并行运行的最简单的方法就是使用Parallel类的Invoke方法,Invoke方法接受一个Action的参数组


void  System.Threading.Tasks.Parallel.Invoke(WatchMovie, HaveDinner, ReadBook, WriteBlog);


这段代码会创建指向每一个方法的委托。


没有特定的执行顺序


Parallel.Invoke方法只有在4个方法全部完成之后才会返回。它至少需要4个硬件线程才足以让这4个方法并发运行。


但并不保证这4个方法能够同时启动运行,如果一个或者多个内核处于繁忙状态,那么底层的调度逻辑可能会延迟某些方法的初始化执行。


捕捉并行循环中发生的异常


当并行迭代中调用的委托抛出异常,这个异常没有在委托中被捕获到时,就会变成一组异常,新的System.AggregateException负责处理这一组异常。

相关文章
|
移动开发 JavaScript
mpvue项目(组件)迁移指南、示例及资源汇总
首先,为什么要从mpvue转uni-app?因为uni-app对vue语法支持更全面(如支持过滤器)、性能更高、支持平台更多(支持H5和App)。这里有详细的评测https://juejin.im/post/5ca1736af265da30ae314248 然后进入正题。
2441 0
|
12天前
|
缓存 运维 Linux
保姆级python项目离线部署服务器教程只需这一篇就够了(建议收藏)
这篇文章提供了详尽的Python项目在离线Linux(CentOS)服务器上的部署教程。作者首先介绍了环境背景,强调了无网络环境和使用有网络的CentOS虚拟机准备安装包的重要性。教程分为两部分:外网环境搭建和内网离线安装。在外网环境中,包括下载Python 3.9.0安装包、传输至服务器、安装依赖包,并使用pip3下载项目所需依赖。内网安装则涉及依赖包的复制和Python环境的同样步骤。最后,作者分享了运行项目的命令,并总结了离线安装的整个流程,提醒读者注意可能出现的问题。
保姆级python项目离线部署服务器教程只需这一篇就够了(建议收藏)
|
3月前
|
JSON JavaScript 前端开发
Danfo.js专题 - 附:Dnotebook(Danfo Notebook)单机资源与汉化文档
Danfo.js专题 - 附:Dnotebook(Danfo Notebook)单机资源与汉化文档
51 0
|
存储 搜索推荐 数据可视化
|
JavaScript 定位技术 API
学会在Vue项目中插入高德地图JS API与地图的相关设置,看这一篇就够了~(保姆级精简教学)
学会在Vue项目中插入高德地图JS API与地图的相关设置,看这一篇就够了~(保姆级精简教学)
1369 0
学会在Vue项目中插入高德地图JS API与地图的相关设置,看这一篇就够了~(保姆级精简教学)
|
SQL 消息中间件 存储
一份平民化的应用性能优化检查列表(完整篇)
1.总原则 一些正确但稍显废话的原则,但能指导后面每个章节的优化,所以还是要啰嗦一次。 可扩展性架构,堆机器能不能解决问题是最最优先考虑的问题 去中心化的点对点通信,优于通过中心代理的通信 池化的长连接,优于短连接 二进制数据,优于文本数据 尽量减少交互,一次调用的粗粒度聚合接口 优于 多次调用的细粒度接口 尽量减少交互,批量接口优于循环调用 尽量只交互必要的数据 尽量就近访问 尽量使用缓存 总是设定超时 在合适的场景,并行化执行 在合适的场景,异步化执行 2.环境准备 保证符合自家各种规范(没有的话赶紧回家写一个),尤其线下压测服务器的配置要与生产环境一致。 2.1 操作系统 自家
121 0
|
弹性计算 运维 监控
十分钟上线- CodeIgniter 项目迁移到函数计算
阿里云函数计算 Function Compute(FC),旨在帮助用户采用弹性伸缩、动态分配资源的方式,来执行业务函数。让用户无需购买部署服务器,无需考虑业务负载,就能快速搭建可处理高并发的后台服务。
十分钟上线- CodeIgniter 项目迁移到函数计算
|
Serverless 文件存储 PHP
十分钟上线-CodeIgniter项目迁移到函数计算
前言 阿里云函数计算 Function Compute(FC),旨在帮助用户采用弹性伸缩、动态分配资源的方式,来执行业务函数。让用户无需购买部署服务器,无需考虑业务负载,就能快速搭建可处理高并发的后台服务。
1199 0
|
Android开发 iOS开发 异构计算
如何快速定位Android端GPU问题之工具介绍
## GAPID ```GAPID```是```Google```下的一个开源库,可用于记录发送给GPU的API调用及渲染状态检查,目前主要用于Android端,对OpenGL ES及Vulkan的支持最完善,使用此工具可以协助定位排查端上OpenGL ES的渲染效果、渲染状态及错误、渲染绑定的shader等资源,同时可以即时修改渲染每步中的变量值并查看新的渲染效果。 ## 下载安装
2404 0
|
搜索推荐 Web App开发 开发工具
V8引擎发布7.0正式版,支持WebAssembly线程预览、优化数组排序算法
该版本将会在几周内与Chrome 70稳定版一起发布,在此之前一直作为Beta版本与Chrome进行联调测试。V 7.0包涵了许多对开发人员很有帮助的新功能。本文带你一起了解其中的一些亮点。
1175 0