Parallel.For
Parallel.For 你可能忽视的一个非常实用的重载方法
说起Parallel.For大家都不会陌生,很简单,不就是一个提供并行功能的for循环吗? 或许大家平时使用到的差不多就是其中最简单的那个重载方法,而真实情况
下Parallel.For里面有14个重载,而其中那些比较复杂的重载方法,或许还有同学还不知道怎么用呢~~~ 刚好我最近我有应用场景了,给大家介绍介绍,废话不多说,
先给大家看一下这个并行方法的重载一览表吧。。。
一:遇到的场景
我遇到的场景是这样的,项目中有这样一个功能,这个功能需要根据多个维度对一组customerIDList进行筛选,最后求得多个维度所筛选出客户的并集,我举个
例子:现有8个维度:
1. 交易行为
2.营销活动
3.地区
4.新老客户
5.营销渠道
6.客户属性
7.客户分组
8.商品
每个维度都能筛选出一批customerid出来,然后对8组customerid求并集,这种场景很明显要提升性能的话,你必须要做并行处理,当然能够实现的方式有很多种,
比如我定义8个task<T>,然后使用WaitAll等待一下,最后再累计每个Result的结果就可以了,代码如下:
1 class Program
2 {
3 static void Main(string[] args)
4 {
5 List<string> rankList = Enum.GetNames(typeof(FilterType)).ToList();
6
7 Task<HashSet<int>>[] tasks = new Task<HashSet<int>>[rankList.Count];
8
9 var hashCustomerIDList = new HashSet<int>(); //求customerid的并集
10
11 for (int i = 0; i < tasks.Length; i++)
12 {
13 tasks[i] = Task.Factory.StartNew<HashSet<int>>((obj) =>
14 {
15 //业务方法,耗损性能中。。。
16 var smallCustomerIDHash = GetXXXMethod(rankList[(int)obj]);
17
18 return smallCustomerIDHash;
19 }, i);
20 }
21
22 Task.WaitAll(tasks);
23
24 foreach (var task in tasks)
25 {
26 foreach (var item in task.Result)
27 {
28 hashCustomerIDList.Add(item);
29 }
30 }
31 }
32
33 static HashSet<int> GetXXXMethod(string rank)
34 {
35 return new HashSet<int>();
36 }
37
38 public enum FilterType
39 {
40 交易行为 = 1,
41 营销活动 = 2,
42 地区 = 4,
43 新老客户 = 8,
44 营销渠道 = 16,
45 客户属性 = 32,
46 客户分组 = 64,
47 商品 = 128
48 }
49 }
上面的代码的逻辑还是很简单的,我使用的是Task<T>的模式,当然你也可以用void形式的Task,然后在里面lock代码的时候对hashCustomerIDList进行
插入,实现起来也是非常简单的,我就不演示了,那下面的问题来了,有没有更爽更直接的方式,看人家看上去更有档次一点的方法,而且还要达到这种效果呢?
二:Parallel.For复杂重载
回到文章开头的话题,首先我们仔细分析一下下面这个复杂的重载方法。
1 //
2 // 摘要:
3 // 执行具有线程本地数据的 for(在 Visual Basic 中为 For)循环,其中可能会并行运行迭代,而且可以监视和操作循环的状态。
4 //
5 // 参数:
6 // fromInclusive:
7 // 开始索引(含)。
8 //
9 // toExclusive:
10 // 结束索引(不含)。
11 //
12 // localInit:
13 // 用于返回每个任务的本地数据的初始状态的函数委托。
14 //
15 // body:
16 // 将为每个迭代调用一次的委托。
17 //
18 // localFinally:
19 // 用于对每个任务的本地状态执行一个最终操作的委托。
20 //
21 // 类型参数:
22 // TLocal:
23 // 线程本地数据的类型。
24 //
25 // 返回结果:
26 // 包含有关已完成的循环部分的信息的结构。
27 //
28 // 异常:
29 // T:System.ArgumentNullException:
30 // body 参数为 null。- 或 -localInit 参数为 null。- 或 -localFinally 参数为 null。
31 //
32 // T:System.AggregateException:
33 // 包含在所有线程上引发的全部单个异常的异常。
34 public static ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, Func<TLocal> localInit, Func<int, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);
从上面的代码区域中看,你可以看到上面提供了5个参数,而最后意思的就是后面三个,如果你对linq的扩展方法比较熟悉的话,你会发现这个其实就是一个并行版本
的累加器(Aggregate)操作,因为他们都是具有三个区域:第一个区域就是初始化区域(localInit),就是累积之前的一个初始化操作,第二个区域其实就是一个迭代
区域,说白了就是foreach/for循环,for循环之中,会把计算结果累计到当初初始化区域设置的变量中,第三个区域就是foreach/for之后的一个最终计算区,三者合起
来就是一个并行累加器,为了方便大家更好的理解,我就扒一下源码给大家看看:
由于图太大,就截两张图了,大家一定要仔细体会一下这里面的tlocal变量,因为这个tlocal的使用贯穿着三个区域,所以大家一定要好好体会下面这几句代码
1 TLocal tLocal = default(TLocal);
2
3 tLocal = localInit();
4
5 while(xxx<xxx){
6 tLocal = bodyWithLocal(num5, parallelLoopState, tLocal);
7 }
8 localFinally(tLocal);
当你理解了tLocal具有累积foreach中的item结果之后,你就应该很明白下面这个body=>(item, loop, total) 和 finally => (total) 中total的含义了,
对吧,当你明白了,然后大家可以看看下面这段代码,是不是用一个方法就搞定了原来需要分阶段实现的一个业务逻辑呢?
class Program
{
static void Main(string[] args)
{
List<string> rankList = Enum.GetNames(typeof(FilterType)).ToList();
var hashCustomerIDList = new HashSet<int>(); //求customerid的并集
//并行计算 7个 维度的 总和
Parallel.For(0, rankList.Count, () => { return new List<int>(); }, (item, loop, total) =>
{
//业务方法,耗损性能中。。。
var smallCustomerIDHash = GetXXXMethod(rankList[item]);
total.AddRange(smallCustomerIDHash);
return total;
}, (total) =>
{
lock (hashCustomerIDList)
{
foreach (var customerID in total)
{
hashCustomerIDList.Add(customerID);
}
}
});
}
static HashSet<int> GetXXXMethod(string rank)
{
return new HashSet<int>();
}
public enum FilterType
{
交易行为 = 1,
营销活动 = 2,
地区 = 4,
新老客户 = 8,
营销渠道 = 16,
客户属性 = 32,
客户分组 = 64,
商品 = 128
}
}
Parallel.For的更多相关文章
- .Net多线程编程—System.Threading.Tasks.Parallel
System.Threading.Tasks.Parallel类提供了Parallel.Invoke,Parallel.For,Parallel.ForEach这三个静态方法. 1 Parallel. ...
- Java 8函数编程轻松入门(五)并行化(parallel)
1.并发与并行的区别 并发: 一个时间段内有几个程序都处于已启动到运行完毕之间,且这几个程序都是在同一个处理机上运行.但在任一个时刻点只有一个程序在处理机上运行 并行: 在同一个时刻,多核处理多个任务 ...
- Parallel并行之乱用
关于Parallel我也不细说了,一则微软封装的很好用,二来介绍这个的遍地都是. 我要说的是,要想成为一个优秀的标题党,一定要把重点放到别的地方,为了节省大家阅读时间,我先把结论说了,然后再慢慢从头说 ...
- 代码的坏味道(12)——平行继承体系(Parallel Inheritance Hierarchies)
坏味道--平行继承体系(Parallel Inheritance Hierarchies) 平行继承体系(Parallel Inheritance Hierarchies) 其实是 霰弹式修改(Sho ...
- 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)
Task - 基于线程池的任务(在 System.Threading.Tasks 命名空间下) 多 Task 的并行执行 Parallel - 并行计算(在 System.Threading.Task ...
- Parallel.Foreach
随着多核时代的到来,并行开发越来越展示出它的强大威力! 使用并行程序,充分的利用系统资源,提高程序的性能.在.net 4.0中,微软给我们提供了一个新的命名空间:System.Threading.Ta ...
- 在Parallel中使用DbSet.Add()发现的一系列多线程问题和解决过程
发现问题 需求很简单,大致就是要批量往数据库写数据,于是打算用Parallel并行的方式写入,希望能利用计算机多核特性加快程序执行速度.想的很美好,于是快速撸了类似下面的一串代码: using (va ...
- Intel.parallel.studio.xe.2015.Update.2.ISO-TBE 下载
磁力链下载点我 还有linux版本 Intel.parallel.studio.xe.2015.Update.1.LINUX.ISO-TBE 收集自网络,要跨请跨原作者,谢谢.
- Parallel并行编程初步
Parallel并行编程可以让我们使用极致的使用CPU.并行编程与多线程编程不同,多线程编程无论怎样开启线程,也是在同一个CPU上切换时间片.而并行编程则是多CPU核心同时工作.耗时的CPU计算操作选 ...
- C#~异步编程再续~大叔所理解的并行编程(Task&Parallel)
返回目录 并行这个概念出自.net4.5,它被封装在System.Threading.Tasks命名空间里,主要提供一些线程,异步的方法,或者说它是对之前Thread进行的二次封装,为的是让开发人员更 ...
随机推荐
- 最新GitHub新手使用教程(Linux/Ubuntu Git从安装到使用)——详细图解
说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 一.叙述 1.说明:需要在Windows 安装Git的同学,可以查看该篇博客 https://blog.csdn.net/qq_4 ...
- 利用朴素贝叶斯(Navie Bayes)进行垃圾邮件分类
贝叶斯公式描写叙述的是一组条件概率之间相互转化的关系. 在机器学习中.贝叶斯公式能够应用在分类问题上. 这篇文章是基于自己的学习所整理.并利用一个垃圾邮件分类的样例来加深对于理论的理解. 这里我们来解 ...
- LA 3135 - Argus
看题:传送门 大意就是让你编写一个称为argus的系统,这个系统支持一个register的命令: Register Q_num Period 该命令注册了一个触发器,它每Period秒就会残生一个编 ...
- 【b091&&z11】潜伏者
Time Limit: 1 second Memory Limit: 128 MB [问题描述] R国和S国正陷入战火之中,双方都互派间谍,潜入对方内部,伺机行动. 历尽艰险后,潜伏于S国的R国间谍小 ...
- Aamazon Web Service EC2 Ubuntu 新建用户而且用ssh连接host
本文參照 http://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/managing-users.html http://docs.aws.am ...
- Codeforces Round #315 (Div. 2) (ABCD题解)
比赛链接:http://codeforces.com/contest/569 A. Music time limit per test:2 seconds memory limit per test: ...
- 28、应用调试之strace命令来跟踪系统调用
strace是个工具,在使用时需要先按照,见韦东山书籍: 1.tar xjf starce-4.5.15.tar.bz2 2.cd strace-4.5.15/ 3.patch -p1 < .. ...
- Java 线程第三版 第九章 Thread调度 读书笔记
一.Thread调度的概述 import java.util.*; import java.text.*; public class Task implements Runnable { long n ...
- 编程算法 - 远征队(expedition) 代码(C)
远征队(expedition) 代码(C) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 远征队有一辆卡车须要行驶L单位的距离, 開始时, 车上有P单位的 ...
- jquery-ajax、struts2、json数据问题
jquery代码: $.ajax({ url:url, type:'post', data:{"key1": "value1", "key2" ...