当前位置:编程学习 > C#/ASP.NET >>

C#4.0入门 第二章 任务并行库—第三页 性能的差异

全文点击此处
C#4.0入门

    这里有一张单色(2值)的PNG的图片(1024*1024)。因为是单色,所以只有黑跟白两个值(实际上使用了只有黑跟白两色的8位PNG格式的图片文件)。到底,哪些像素是黑色的,我们编写一个程序来查点一下。同时用它来进行单任务和2~4任务分别进行查点时性能的比较。

比较单任务与多任务 
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
class Program
{
  public static IEnumerable<Color> Pixels(int from, int to)
  {
    var bm = new Bitmap(@"s:\sample001.png");
    for (int y = from; y < to; y++)
    {
      for (int x = 0; x < bm.Width; x++)
      {
        yield return bm.GetPixel(x, y);
      }
    }
  }
  private static bool isBlack(Color c)
  {
    return c.B == 0 && c.G == 0 && c.R == 0;
  }
  private static void count(int fromInclusive, int toExclusive, ref int count, object lockTarget)
  {
    var q = from n in Pixels(fromInclusive, toExclusive)
            where isBlack(n)
            select n;
    int r = q.Count();
    lock (lockTarget) { count += r; }
  }
  static void Main(string[] args)
  {
    Object thisLock = new Object();
    DateTime start1 = DateTime.Now;
    int count1 = 0;
    count(0, 1024, ref count1, thisLock);
    Console.WriteLine(DateTime.Now - start1);
    Console.WriteLine("{0} Black Pixels by single task", count1);
    DateTime start2 = DateTime.Now;
    int count2 = 0;
    Parallel.Invoke(() => count(0, 512, ref count2, thisLock),
      () =>count(512, 1024, ref count2, thisLock));
    Console.WriteLine(DateTime.Now - start2);
    Console.WriteLine("{0} Black Pixels by 2 task", count2);
    DateTime start3 = DateTime.Now;
    int count3 = 0;
    Parallel.Invoke(() =>count(0, 342, ref count3, thisLock),
      () => count(342, 682, ref count3, thisLock),
      () => count(682, 1024, ref count3, thisLock));
    Console.WriteLine(DateTime.Now - start3);
    Console.WriteLine("{0} Black Pixels by 3 task", count3);
    DateTime start4 = DateTime.Now;
    int count4 = 0;
    Parallel.Invoke(() =>count(0, 256, ref count4, thisLock),
      () => count(256, 512, ref count4, thisLock),
      () => count(512, 768, ref count4, thisLock),
      () => count(768, 1024, ref count4, thisLock));
    Console.WriteLine(DateTime.Now - start4);
    Console.WriteLine("{0} Black Pixels by 4 task", count4);
  }
}

    这段代码乍看上去有点冗长,其实是必要的,正式开发中存在着大量的这种代码。首先,在并行处理的每一个任务中分别把画像文件一一读入。4任务的情况下要读4次相同的文件。虽然乍看上去是多余的,但是因为Bitmap类是非线程安全的,不能对别的线程进行访问。因此,尽管多余,还是要在一个处理线程内读入相同文件。

    请注意使用了lock语句。在这种程序里,要防止互相竞争访问而导致死锁的发生。

    另外,下面的代码中,变量r是可以去掉的。

未去掉变量r的代码 
int r = q.Count();
lock (lockTarget) { count += r; }

    可以象下例那样去掉变量r。

去掉变量r的代码 
lock (lockTarget) { count += q.Count(); }

    但是,查点像素的处理,实际上是在Count方法内进行的。因此,如果这样进行改写的话,这个处理本身就变成被排他性的锁住了,全体处理就被延迟了,从而失去了有效利用多核进行并行处理的意义。

    还有一点要注意的是,如果任务数超过了实际存在的内核数,反而会影响性能。以下为在双核CPU上执行的例子。

运行结果1(在双核CPU上运行的例子。所花的时间,2任务<3任务=4任务<单任务) 
00:00:07.9630000
16470 Black Pixels by single task
00:00:03.0170000
16470 Black Pixels by 2 task
00:00:03.0870000
16470 Black Pixels by 3 task
00:00:03.0850000
16470 Black Pixels by 4 task

    也就是说,如果在同一个内核上分配太多任务的话,反而会对性能产生影响。因此,在原本是双内核,但是由于使用了HT技术,所以看起来好像是4内核的Core i5上,运行结果又不一样了。

运行结果2(在Core i5上运行的例子。所花的时间,4任务<3任务<2任务<单任务) 
00:00:02.8451627
16470 Black Pixels by single task
00:00:01.4070805
16470 Black Pixels by 2 task
00:00:01.1200640
16470 Black Pixels by 3 task
00:00:01.0490600
16470 Black Pixels by 4 task

    这种情况下,把分配的任务增加到4任务的时候,任务越多所花时间越短。但是,由于实际上是双内核,所以从单任务变为2任务的时候,提速效果特别明显,但是超过了2任务,就没有这么明显的效果了。

■ 总结

    把本章内容进行总结。
    ● 多内核时代已经开始。
    ● 软件开发的多内核时代是从Visual Studio 2010/C#4.0/.NET Framework4.0开始的。

    ● 利用Parallel.Invoke类,可以使并行变得很容易实现。

    ● 利用Parallel.ForEach方法实现foreach语句。
    ● 利用Parallel.For方法实现for语句。

    ● 但是,不能利用并行替换所有循环操作。
    ● 利用并行可以大幅度提高性能。



--------------------编程问答-------------------- --------------------编程问答-------------------- 看 看 --------------------编程问答-------------------- 在一个由很多因素影响的问题的求解过程中,使用基于统计学试验的办法可能比从原理推断可能更好。 --------------------编程问答-------------------- --------------------编程问答-------------------- 强!!! --------------------编程问答-------------------- --------------------编程问答-------------------- marking

--------------------编程问答-------------------- --------------------编程问答-------------------- 顶!!!!!! --------------------编程问答-------------------- 顶。。。。。。。。。。。。
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,