C#4.0入门 第二章 任务并行库—第一页 只使用双核(转)

 
迄今为止,使用多内核的多核计算机还并没有得到广泛的应用。尽管在高端领域,高端服务器的世界里,应用着很多多核计算机系统,但在广大的低端世界里,还是使用着单核或双核。但是另一方面,在笔记本电脑的世界里,也出现了多核笔记本。


“尽管多核时代还只是对未来的预测,但不再是空想了。已经一点点地逐步靠近我们这个世界了”。


当然,还有很多单核,单处理器的计算机被利用着,但这并不单纯是C#等开发语言的应用环境。今天,主CPU的内核数量的增加趋势越来越明显,所以我们已经可以预见广大用户使用多核计算机时代的即将到来,同时以此为目标,开始我们现在的程序开发了。


首先,让我们看一下现实情况,因为只使用到双核,所以对内核数量的考虑还没有那么必要。大部分程序都只考虑把负荷很好地分散给操作系统和应用程序,至于内核,双核就够了。虽然有时计算量特别大的情况下程序实行并行处理是有必要的,但也只是极少数的情况。


但是,如果想首先超越这种水准的话,无论如何对于程序运行时内核数量的考虑都是有必要的。对于性能来说,增加CPU内核的做法比提高CPU时钟频率的做法会好很多。实际上,通过简单的实验,对于双核4线程的Core
i5来说,只是运行具有多内核意识而开发出来的程序,就把速度提高了2-3倍。(当然,是针对不包含I/O等处理,而纯粹运行计算处理的情况来说)。


但是,这里有一个问题。就是如果开发程序时还要考虑内核数量的话,将会带来很多麻烦。针对这个问题,软件方面的对应可以说是很迟的。但是,Visual Studio
2010与.Net Framework4与C#4都率先针对这个现实问题的对应迈出了第一步。


1980年代,Occam这个开发语言有一个惊人的特点,就是它是专门针对可以实现并行处理的CPU而进行开发的。如下例所示,使用这个语言中的PAR命令,就可以实现两个计算的并行处理。


用PAR命令来实现并行处理(Occam语言)




 PAR
x := x * 2
y := y * 2


但是,如果在C#中利用线程来实现并行处理的话,会相当麻烦。例如,只创建一个线程,并在主线程中实现并行的程序就要如下例所示。


利用线程实现并行处理(C#语言)




 using System;
using System.Threading;
class Program
{
static void Main(string[] args)
{
var thread = new Thread(()=>Console.WriteLine("on sub thread!"));
thread.Start();
Console.WriteLine("on main thread!");
thread.Join();
}
}


上例的执行结果(上下顺序可以颠倒)




 on main thread!
on sub thread!


必须要使用为了让线程开始的Start方法,等待线程结束的Join方法等等,不是很智能,很简单的。




但是,C#4的水准与Occam语言的水准很接近。不使用线程,而使用了一种全新的“任务(Task)”,如果使用封装了这个功能的Parallel类,事情就变得简单了。


利用任务实现并行处理(C#语言)




 using System;
using System.Threading.Tasks;
class Program
{
static void Main(string[] args)
{
Parallel.Invoke(
()=>Console.WriteLine("1st task!"),
()=>Console.WriteLine("2nd task!"));
}
}


上例的执行结果(上下顺序可以颠倒)




 2nd task!
1st task!


这里请注意用“using System.Threading.Tasks;”代替了“using
System.Threading;”。就像以前用“System.Collections.Generic;”代替“System.Collections;”那样,改变了线程的世界。


另外,因为Parallel.Invoke方法的参数是可变的,不管多少个并行lambda表达式这里都可以写,可以按内核数量来写,在多个内核之间实行并行处理。这里由于“作为举例来说只写两个就够了,三个以上就冗长了”的考虑,只写了两个。
posted @ 2011-06-11 16:00  董雨  阅读(257)  评论(0编辑  收藏  举报