前端时间因为要做个大数据量分析,所以用C#写了个脚本跑,不过由于算法复杂度问题,初步估计需要40小时才能跑完。为了加快运算,我一开始想到了 并行计算,利用MPICH或其他类似的分布式计算框架开发,不过都比较麻烦。正巧微软新出来的并行库进入了我的视线,于是做了一次简单的尝试。
并行库全称是Microsoft Parallel Extensions,此库已经计划作为framework 4.0的一部分来发布。不过现在已经有针对framework 3.5平台的CTP版本,让开发人员尝个鲜,大家可以通过以下这个链接进行下载:
此版本是第二版CTP,经过了一定的扩展和补充,总结下来此库主要包含了三大块:
本文我们先着重讲述一下TPL的使用,并会给出一些性能对比数据。
通常我们线性的去执行一个循环,是这样写的:
在保证以上每个i的计算不存在依赖性的前提下,我们可以通过并行库很方便的改写成:
可以发现,并行库可以很方便将我们的单线程程序改写成多线程并行的结构。
那让我们来做个实验:假设我们构造一个执行时间为100ms的Compute函数,并设N=100
我在一台双核的机器上的运行结果如下:
可以看到并行运行的速度差不多是单线程的两倍,而266ms则是线程切换调度时的耗费。
平均每个核心处理调度的耗费是133ms
如果在8核的机器上,运行结果如下:
理论上没有线程调度耗费的情况下是10000/8 =1250ms,则8线程并行时的线程调度耗费是470ms
平均每个核心处理调度的耗费是59ms
所以在并行计算中的损耗(调度耗费)是可控的,无需我们担心。
并行库还是给我们带来很多令人振奋的东西的,不过用下来还是感觉有许多需要改进的地方。例如现在还不能方便对线程数的使用进行调节,即:如果用了Parallel.For,他会占满你所有的cpu来进行运算,如果需要设置线程数,TPL确实也提供了。
其中TaskManger可以在初始化的时候利用Policy来设定最小线程数与理想线程数等等,但用起来很麻烦,如果这块能简化一下就好了,就像PLINQ提供了As函数,可以方便的设定线程数。
另外虽说是并行的,但归根结底还是在一台机器上跑,如果想用多台机器跑程序,这个就要指望Azure了,不过TPL确实可以帮助我们在大多数情况下充分利用强大的多核并行处理能力来处理数据,是个非常不错的东东。
文章转载自:http://it.dianping.com/microsoft_parallel_extensions_tutorial_tpl.htm
测试程序下载:http://it.dianping.com/microsoft_parallel_extensions_tutorial_tpl.htm