使用.NET并行任务库(TPL)与并行Linq(PLINQ)充分利用多核性能
最近比较闲,(项目要转Java被分到架构组,边缘化人员,无所事事 哈哈哈哈)
记录一下前段时间用到的.NET框架下采用并行策略充分利用多核CPU进行优化的一个方法
起因是项目中有个结算的方法,需要汇总一个月的数据在内存中进行计算,统计,分组 ,然后产生新的数据
在某个客户那部署后发现,这个方法执行的效率很低,监控发现数据从数据库查询出来 很快(因为数据库单独一台服务器)
然后通过top查看服务器的CPU就跑到了100%.内存正常,查了下CPU的型号 emm...很烂 但是好在核心很多(毕竟服务器级的U)..
查看服务器核心数 是在16个. Linux用top命令看的话,理论上CPU跑到1600%才算吃满,但是程序只吃了单个核.
等于1人干活 15人在吃瓜呀...如图:

然后查看了代码,发现结算的计算这一块代码是在单个foreach中进行顺序计算,所以决定用.NET提供的并行任务库(TPL)进行优化.
优化完成后,从之前的结算直接导致线程超时异常 变成 大概在20秒左右就结算完成.获得了巨大的提升.
1 .NET 中的并行编程简介
在硬件发展迅速的今天.有太多的个人电脑和服务器级CPU都拥有多个 CPU 内核,为了方便多个线程能够同时执行。 充分利用硬件,就可以利用并行编程对代码进行并行化,以将工作分摊在多个处理器上。
以前,并行化需要自行开启子线程,维护锁等各种繁琐操作。但是从 .NET Framework 4 中引入的TPL简化了并行开发。 我们只需要通过简单的修改,就可以编写高效、细化且可伸缩的并行代码,而不必直接处理线程或线程池。
下图是官方文档的截图,简单的说明了 .NET 中的并行编程体系结构:
我们可以看到Parallel 就是在线程处理上加了一层封装好的算法,让我们处理并行多线程更简单

2. 并行任务库(TPL)
任务并行库 (TPL) 是 System.Threading 和 System.Threading.Tasks 空间中的一组公共类型和 API。
TPL 的目的是通过简化将并行和并发添加到应用程序的过程来提高开发人员的工作效率。
TPL 动态缩放并发的程度以最有效地使用所有可用的处理器。
此外,TPL 还处理工作分区、ThreadPool 上的线程调度、取消支持、状态管理以及其他低级别的细节操作。
通过使用 TPL,你可以在将精力集中于程序要完成的工作,同时最大程度地提高代码的性能。
(以上来自于官方文档,我觉得已经讲的很详细了)
那么接下来,我们就编写一个并行任务的示例,来看看效果:
首先,并行任务库提供了两个方法 一个Parallel.ForEach 一个Parallel.For 用法都差不多,这里我们用Parallel.For做实验
先创建两个方法,代码如下:
//创建顺序执行方法
static List<dynamic> AddModelSequential(int modelCount)
{
var list = new List<dynamic>();
//为了增加循环复杂性,里面嵌套一个循环
for (int i = 0; i < modelCount; i++)
{
int f = 0;
for (int j = 0; j < 5000; j++)
{
f++;
}
list.Add(new { bbb = i, aaa = "1", ccc = f });
}
return list;
}
//创建并行执行方法
static List<dynamic> AddModelParallel(int modelCount)
{
var list = new List<dynamic>();
Parallel.For(0, modelCount, i =>
{
int f = 0;
//为了增加循环复杂性,里面嵌套一个循环
for (int j = 0; j < 5000; j++)
{
f++;
}
list.Add(new { bbb = i, aaa = "1",ccc= f});
});
return list;
}
接着执行两个方法,都跑10W条数据,并记录执行时间.如下:
static void Main(string[] args)
{ Console.Error.WriteLine("执行顺序循环...");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start(); AddModelSequential(1000000);
stopwatch.Stop();
Console.Error.WriteLine("顺序循环时间(毫秒): {0}",
stopwatch.ElapsedMilliseconds); stopwatch.Reset();
Console.Error.WriteLine("执行并行循环...");
stopwatch.Start();
AddModelSequential(100000);
stopwatch.Stop();
Console.Error.WriteLine("并行循环时间(毫秒): {0}",
stopwatch.ElapsedMilliseconds);
Console.ReadLine();
}
本人是I9 12代CPU 逻辑处理器有20个,得到结果如图:

性能提升20倍..
由于在开发机上跑的东西比较多,对于CPU的使用情况,监控不是很清楚,我们掏出..阿里云99元包邮的2核2G的服务器..来看看效果.

我们可以明显看到在2核机上 性能大概也有接近一倍的提升
通过top命令,可以明显的监听到CPU的使用情况
在跑第一个循环的时候,CPU 100%,单核吃满,如图:

跑第二个循环的时候,第2颗CPU就开始参与进来了,如图:

所以在合适的情况下(注意,这里是合适的情况)
程序中采用并行任务库充分的利用服务器的多核性能可以使运行效率有很大的提升.
3. 并行PLINQ
PLINQ 是 LINQ 的一组扩展
它允许在运行代码的计算机上使用多个处理器或内核对支持 IEnumerable<T> 接口的集合并行执行查询。
这可以显著减少处理大型数据集或执行复杂计算所需的时间
注意,这里可以看到 PLINQ只支持 IEnumerable的接口,所以linq to sql时的表达式树是不支持的,如果使用则会导致全表查询到内存中
使用方式也很简单,在数据集处理之前加上AsParallel方法即可,如下:
//LINQ
var results = from item in dataSource
where item.SomeCondition()
select item.SomeTransformation();
//PLINQ
var parallelResults = from item in dataSource.AsParallel()
where item.SomeCondition()
select item.SomeTransformation();
PLINQ的使用场景比较特殊,目前demo中我还没反映出来比LINQ要快(甚至LINQ比PLINQ要快很多).
所以我们在用的时候一定要考虑到以下几点:
- 并不总是更快:虽然 PLINQ 可以说是可以提高某些复杂查询的性能,但并非所有操作都会有明显收益。线程管理和同步产生的开销有时会使 PLINQ 查询比其顺序查询慢,尤其是对于小型数据集或计算复杂度较低的操作。
- 开销:并行化会带来开销,例如任务调度和线程之间的切换。对非 CPU 密集型的小型集合或操作,这些开销可能会抵消并行化的好处,从而使 PLINQ 查询比标准 LINQ 查询慢。
- 排序:默认情况下,PLINQ 不保证结果的顺序。如果排序很重要,则可以使用 AsOrdered 或 OrderBy 方法,但这可能会进一步降低并行化带来的性能提升。
综上所述,如果要用PLINQ一定要充分的进行测试与性能评估,一定要确定PLINQ有较大的提升时,才去使用.
.
使用.NET并行任务库(TPL)与并行Linq(PLINQ)充分利用多核性能的更多相关文章
- 并行Linq(一)
.Net 并行计算 ----并行Linq(一) 本文是.Net 并行计算 的第三篇 欢迎大家拍砖,阅读本文需要有LINQ基础,因为并行LINQ (PLinq) 其实是LINQ To Object 的并 ...
- C#编程(六十三)----------并行LINQ
并行LINQ .NET4在System.Linq命名空间中包含一个新类ParallelEnumerable,可以分解查询的工作使其分布在多个线程上.尽管Enumerable类给IEnumerable& ...
- C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是TAP(Task-based Asynchronous Pattern, 基于任务的异步模式)
学习书籍: <C#本质论> 1--C#5.0之后推荐使用TPL(Task Parallel Libray 任务并行库) 和PLINQ(Parallel LINQ, 并行Linq). 其次是 ...
- C#使用任务并行库(TPL)
TPL(Task Parallel Library) 任务并行库 (TPL) 是 System.Threading和 System.Threading.Tasks 命名空间中的一组公共类型和 API. ...
- C# 多线程八之并行Linq(ParallelEnumerable)
1.简介 关于并行Linq,Ms官方叫做并行语言集成(PLINQ)查询,其实本质就是Linq的多线程版本,常规的Linq是单线程的,也就是同步的过程处理完所有的查询.如果你的Linq查询足够简单,而且 ...
- 并行Linq
有时候我们对大批量数据进行处理,此时并行linq就起作用了. 并行查询 对于以下查询可以耗时会非常大,如下: ; var r = new Random(); , arraySize).Select(x ...
- 四、并行编程 - 并行LINQ(PLINQ) 的使用。AsParallel
用于对内存中的数据做并行运算,也就是说其只支持 LINQ to Object 的并行运算 一.AsParallel(并行化) 就是在集合后加个AsParallel(). 例如: , ); == ); ...
- .NET并发编程-TPL Dataflow并行工作流
本系列学习在.NET中的并发并行编程模式,实战技巧 本小节了解TPL Dataflow并行工作流,在工作中如何利用现成的类库处理数据.旨在通过TDF实现数据流的并行处理. TDF Block 数据流由 ...
- C#并行编程-PLINQ:声明式数据并行
目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C#并行编程-线程同步原语 C#并行编程-PLINQ:声明式数据并行 背景 通过LINQ可 ...
- C#并行编程-PLINQ:声明式数据并行-转载
C#并行编程-PLINQ:声明式数据并行 目录 C#并行编程-相关概念 C#并行编程-Parallel C#并行编程-Task C#并行编程-并发集合 C#并行编程-线程同步原语 C#并行编程-P ...
随机推荐
- Day 3 - 单调栈、单调队列、凸包与斜率优化
单调栈 引入 何为单调栈?顾名思义,单调栈即满足单调性的栈结构.与单调队列相比,其只在一端进行进出. 为了描述方便,以下举例及伪代码以维护一个整数的单调递增栈为例. 过程 插入 将一个元素插入单调栈时 ...
- vue项目中实现sql编辑器功能自定义高亮词汇可提示关键词-codemirror
先上图:左侧是数据库表,右侧上部是sql编辑器,下部是执行sql的返回接口 HTML: <el-row> <el-col :span="4" class=&quo ...
- 如何正确使用@Bulider与<T>返回数据
@Data @ToString @Builder @AllArgsConstructor public class PageResult<T> implements Serializabl ...
- hadoop hive hbase flume sqoop基本操作
top 里的id为cpu空闲度 如果wa为99.8就是负担太重.得停掉一些任务 cat /proc/cpuinfo 查看cpu信息 cat /proc/meminfo 查看内存信息 hadoop基础操 ...
- 【微信小程序】02 常用标签组件
轮播标签: 轮播图 <swiper> <!-- 轮播项 --> <swiper-item>1</swiper-item> <swiper-item ...
- 3天搞定Linux,1天搞定Shell笔记
Linux概述 Linux是一个操作系统OS 开源 MacOS基于Darwin,Darwin基于FreeBSD开发. Linux基于Minix(开发重写),Minix基于Unix开发. Linux一切 ...
- [rCore学习笔记 024]多道程序与协作式调度
写在前面 本随笔是非常菜的菜鸡写的.如有问题请及时提出. 可以联系:1160712160@qq.com GitHhub:https://github.com/WindDevil (目前啥也没有 本节重 ...
- 组长:你熟悉过React,开发个Next项目模板吧,我:怎么扯上关系的?
组长:你熟悉过React,开发个Next项目模板吧,我:怎么扯上关系的? 最近工作安排我开发一个Next.js项目模板,心里默笑,React用得少得都快忘光了,现在得搞Next?虽然我曾是React的 ...
- 金融、支付行业的开发者不得不知道的float、double计算误差问题
为什么浮点数 float 或 double 运算的时候会有精度丢失的风险呢? <阿里巴巴 Java 开发手册>中提到:"浮点数之间的等值判断,基本数据类型不能用 == 来比较,包 ...
- 全网最适合入门的面向对象编程教程:37 Python常用复合数据类型-列表和列表推导式
全网最适合入门的面向对象编程教程:37 Python 常用复合数据类型-列表和列表推导式 摘要: 在 Python 中,列表是一个非常灵活且常用的复合数据类型.它允许存储多个项,这些项可以是任意的数据 ...