在以往的计算机发展历史中,硬件技术的发展,特别是CPU频率的不断提高,总是给软件带来更强的性能提升。从386到586,从赛扬到奔腾,每次CPU频率的提升,都带来软件性能的大幅提升,而软件无需做任何变动。如果有客户抱怨你的软件性能不佳,我们无需着急,只需要升级到更高频率的CPU就可以了。当单核CPU的频率发展到3G之后,再往上发展就遇到了技术瓶颈,单核心CPU的发展已经到达一个极限,硬件厂商不得不转而向多核芯CPU发展,在一颗芯片中加入两个甚至多个运算核心,通过核心的增加,来提高芯片总的频率。当硬件通过增加运算核心来提高性能时,由于受到其架构的影响,软件并不能充分地利于多个运算核心所带来的性能提升,甚至有的时候性能还有所下降。在这种情况下,开发者不得不改变应用程序的架构和开发方法,以应对这种多核的趋势,使得自己的软件可以充分利于硬件升级所带来的性能提升。
作为下一代开发平台,Visual Studio 2010加大了对并行运算的支持。微软正在使得尽量大的范围内的开发者都能高效而简便地进行并行计算的开发,不管他使用的是非托管代码还是.NET Framework。从而将开发者从繁琐而复杂的多线程开发中解放出来,将更多的精力放到业务逻辑上。
- Visual Studio IDE对并行计算开发的大量支持。Visual Studio 2010提供了一个“并行性能分析器”,它可以帮助我们分析应用程序的性能瓶颈,找到需要并行处理和可以进行并行处理的地方,并以图形化的形式表现出来。
- 非托管的C++库和编译器对并行计算的支持
- .NET Framework 3.5/4.0 对并行计算的大量支持,包括PLINQ、并行语言语句等等
本文讨论的是.net 3.5/4.0对并行计算的性能差别,采用的例子是Visual Studio 2010 Beta2 Training Kit 的Demo代码. 在讨论之前先回顾一下.NET 的并行组件:
由于并行计算是将一个工作任务进行分解以并发执行,因此,任何一个支持并行计算的软件开发与运行平台都必须解决这些并发执行的子任务之间的相互协作问题,比如:
- 一个子任务需要等待其它子任务的完成,多个子任务完成之后才允许执行下一个子任务(即所谓fork-join),
- 一个子任务结束后自动启动多个下级子任务的执行
- 允许一个任务中途取消
- ……
.NET 3.5/4.0通过对已有的基类库进行扩充和增强,满足了上述需求。.NET 给 “System.Threading” 命名空间增加了一些新的类,同时对部分已有类也进行了调整和优化。另外,针对中途取消线程或作务执行这一实际开发中非常普遍的需求,提供了一个统一取消模型。最大的变化是.NET为基类库提供了多个与并行计算密切相关的类,并将它们统一称之为“并行扩展(Parallel Extensions)”。
.NET 3.5通过DevLabs发布了Reactive扩展中包含的类库为并行处理提供支持。Reactive扩展目标是简化异步及事件驱动程序的构建,可参看InfoQ的文章微软发布Reactive框架,简化异步及事件驱动编程。下述.net 3.5的例子代码的运行要求下载Reactive扩展。
先介绍一下我的机器配置,单CPU双核:
下面的例子来自Visual Studio 2010 Beta2 Training Kit 的ParallelBabyNames:
.net 3.5下的运行结果:
.net 4的运行结果:
从上述例子的运行结果来看,.net 4的性能要比.net 3.5要强,.net 3.5和.net 4.0的并行处理能力支持上基本持平。
Visual studio 2010 and parallel computing for developer resources