前段时间看到园子里面有同学在用Parallel进行批量插入数据库。后面也有很多同学针对这一事件给出了自己的看法和见解。我在这里不评论内容的好坏,至少能将自己东西总结分享这个是要靠勇气和毅力。

闲话少说,我在最近看崔鹏飞的github的时候,发现他对这块也做了一定的总结,那么我就他这块进行板书与展示。案例是怎么回事呢?话说我有一个公司,里面需要统计一下总收入,另外有一个公司被我收购了,我一起计算总收入。当一天我收购了N个公司,计算总收入的时候,我们采用并行计算。

    internal class Company
{
public decimal TotalIncome; public Company Merge(Company that)
{
Calc();
TotalIncome += that.TotalIncome;
return this;
} /// <summary>
/// 复杂运算
/// </summary>
private void Calc()
{
//TODO:省略500字
}
}

首先我们想到的是采用直接累加就行了吧,这是所谓的线性预算。

        /// <summary>
/// 线性运行
/// </summary>
/// <param name="bigCompany"></param>
/// <param name="smallCompanies"></param>
/// <returns></returns>
private static Company LinearMerge(Company bigCompany, IEnumerable<Company> smallCompanies)
{
foreach (Company smallCompany in smallCompanies)
{
bigCompany.Merge(smallCompany);
}
return bigCompany;
}

采用线性运算,毫无疑问结果是正确的。但是,如果的N大一点,例如30000000个,可能就要花一点时间了。

那么是否我们可以采用并行处理呢?OK,直接上代码。

         /// <summary>
/// 并行处理
/// </summary>
/// <param name="bigCompany"></param>
/// <param name="smallCompanies"></param>
/// <returns></returns>
private static Company ParallelMerge(Company bigCompany, IEnumerable<Company> smallCompanies)
{
Parallel.ForEach(smallCompanies, smallCompany => bigCompany.Merge(smallCompany));
return bigCompany;
}

时间很快,但是结果呢?结果和上面线性的一致么?

那么我如果在并行的基础上面加一把锁呢,保证每次独占资源。

         /// <summary>
/// 并行加锁
/// </summary>
/// <param name="bigCompany"></param>
/// <param name="smallCompanies"></param>
/// <returns></returns>
private static Company ParallelMergeLock(Company bigCompany, IEnumerable<Company> smallCompanies)
{
var obj = new object();
Parallel.ForEach(smallCompanies, smallCompany =>
{
lock (obj)
{
bigCompany.Merge(smallCompany);
}
});
return bigCompany;
}

毫无疑问,结果也是正确的,那么耗时可能我们就要关心了。那么耗时究竟怎么样呢?

我们可以采用函数式处理嘛。

         /// <summary>
/// 函数式合并
/// </summary>
/// <param name="bigCompany"></param>
/// <param name="smallCompanies"></param>
/// <returns></returns>
private static Company FunctionalMerger(Company bigCompany, IEnumerable<Company> smallCompanies)
{
return smallCompanies.Aggregate(bigCompany, (buyer, seller) => buyer.Merge(seller));
}

那么我们在在函数式的基础上面进行并行化处理呢?

         /// <summary>
/// 函数式的并行化
/// </summary>
/// <param name="bigCompany"></param>
/// <param name="smallCompanies"></param>
/// <returns></returns>
private static Company FunctionParallelMerge(Company bigCompany, IEnumerable<Company> smallCompanies)
{
return smallCompanies.AsParallel().Aggregate(() => new Company(), (shell, smallCompany) => shell.Merge(smallCompany), (shell1, shell2) => shell1.Merge(shell2), bigCompany.Merge);
}

上面提出了一些问题,这里我们用实际的测试数据查看。

测试代码

         private static IEnumerable<Company> GenerateSmallCompanies()
{
return Enumerable.Range(, ).Select(number => new Company { TotalIncome = number }).ToArray();
} private static void PrintMergeResult(Func<Company, IEnumerable<Company>, Company> mergeMethod, string funcApproach)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
var mergeResult = mergeMethod(new Company { TotalIncome = }, m_SmallCompanies);
stopWatch.Stop();
Console.WriteLine("{0}:{1} Time:{2}", funcApproach, mergeResult.TotalIncome, stopWatch.ElapsedMilliseconds);
} private static void TryAll()
{
Console.WriteLine("============================");
PrintMergeResult(LinearMerge, "简单直接 ");
PrintMergeResult(ParallelMerge, "错误并行 ");
PrintMergeResult(ParallelMergeLock, "加锁并行 ");
Console.WriteLine("***********");
PrintMergeResult(FunctionalMerge,"函数式合并 ");
PrintMergeResult(FunctionParallelMerge, "函数式并行合并 ");
} private static readonly IEnumerable<Company> m_SmallCompanies = GenerateSmallCompanies();
static void Main()
{
Console.WriteLine("测试数据30000000个");
for (int i = ; i < ; i++)
{
TryAll();
}
Console.ReadKey();
}

测试结果如下:

按照理论情况,错误并行应该比直接更快,但是不知道我机器(CPU AMD)上面出现这样的情况,其他情况还算正常。在另一台计算机(CPU Intel)上面运行测试,数据如下:

【狼窝乀野狼】Parallel浅尝辄止的更多相关文章

  1. 【狼窝乀野狼】Serializer妙手回春

    在我们很多程序中,需要将数据保存到本地,以便于下次打开还能看到原始数据.例如我们Xmind思维导图,例如我们的Power Designer等等,都是有保存一个隶属于自己的工程文件,那么今天我要说的就是 ...

  2. 【狼窝乀野狼】Excel那些事儿

    在工作中我们常常遇到Excel表格,不管是数据的导入导出,还是财务统计什么都,都离不开Excel,Excel是我见过的最牛逼的一个软件(可能我的见识少)没有之一:如果你只停留在Excel处理数据,统计 ...

  3. 【狼窝乀野狼】Windows Server 2008 R 配置 Microsoft Server 2008 远程登录连接

    如果你已经了解了,或者你已经经历了,那么此篇文章对你是毫无用处.因为文笔深处未必有自己亲身体验来的真实有效. 闲话少说,直接上菜. 最近脑子“抽筋”,想安装一个服务器来玩玩,那么怎么选择呢?我的PC是 ...

  4. .Net多线程编程—System.Threading.Tasks.Parallel

    System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Parallel.For,Parallel.ForEach这三个静态方法. 1 Parallel. ...

  5. Java 8函数编程轻松入门(五)并行化(parallel)

    1.并发与并行的区别 并发: 一个时间段内有几个程序都处于已启动到运行完毕之间,且这几个程序都是在同一个处理机上运行.但在任一个时刻点只有一个程序在处理机上运行 并行: 在同一个时刻,多核处理多个任务 ...

  6. Parallel并行之乱用

    关于Parallel我也不细说了,一则微软封装的很好用,二来介绍这个的遍地都是. 我要说的是,要想成为一个优秀的标题党,一定要把重点放到别的地方,为了节省大家阅读时间,我先把结论说了,然后再慢慢从头说 ...

  7. 代码的坏味道(12)——平行继承体系(Parallel Inheritance Hierarchies)

    坏味道--平行继承体系(Parallel Inheritance Hierarchies) 平行继承体系(Parallel Inheritance Hierarchies) 其实是 霰弹式修改(Sho ...

  8. 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    Task - 基于线程池的任务(在 System.Threading.Tasks 命名空间下) 多 Task 的并行执行 Parallel - 并行计算(在 System.Threading.Task ...

  9. Parallel.Foreach

    随着多核时代的到来,并行开发越来越展示出它的强大威力! 使用并行程序,充分的利用系统资源,提高程序的性能.在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threading.Ta ...

随机推荐

  1. swift 旋转加载动画

    https://github.com/naoyashiga/RPLoadingAnimation

  2. HTML标签的权重

    原文 简书原文:https://www.jianshu.com/p/c86d540aec40 大纲 1.HTML权重标签 2.常见的权重标签 3.常见的权重标签的使用 1.HTML权重标签 SEOer ...

  3. window下利用navicat访问Linux下的mariadb数据库

    1.再Linux上成功安装mariadb数据库后,不管是在dos(敲命令mysql -h192.168.136.8 -uroot -p)下或者是navicat(创建连接)下连接mariadb数据库,会 ...

  4. PatentTips - Multi-host SATA Controller

    BACKGROUND The present subject matter relates, in general, to a computing system having multi-host p ...

  5. [AngularFire2] Building an Authentication Observable Data Service

    After successfully login, we want something help to check whether user has already login or not. And ...

  6. Java fork join ForkJoinPool 用法例子

    本例是把一个大的数组求和的计算的大任务分解到在小范围内求和的小任务,然后把这些小任务之和加起来就是所求之结果. 技术:JDK8.0, Javafork-join模式下的RecursiveTask技术, ...

  7. CentOS下安装和配置MySQL-JDK-Tomcat-Nginx(个人官网环境搭建手册)

    今天,重新弄我的个人云主机的环境,准备运营自己用Java写的个人官网等网站. 服务器环境:阿里云CentOS 6.4位 包括以下脚本在内的绝大部分命令和脚本,都是我亲自执行过,靠谱的. 完整的&quo ...

  8. html5-7 html5语义标签和视频

    html5-7  html5语义标签和视频 一.总结 一句话总结:设计网站的时候要兼顾早期浏览器的话,最新技术要缓着用,自己可以先尝试. 1.html5所有标签共有属性有哪四种? 1.id2.clas ...

  9. Linux开发环境搭建与使用系列教程

    00.Linux开发环境搭建与使用1——Linux简史 01.Linux开发环境搭建与使用2——Linux系统(ubuntu)安装方案 02.Linux开发环境搭建与使用3——通过虚拟机安装系统(ub ...

  10. [React] Pass Data To Event Handlers with Partial Function Application

    In this lesson we’ll see how to pass an item’s id value in an event handler and get the state to ref ...