zoukankan      html  css  js  c++  java
  • 微软并行编程类库Parallel Extensions初探 Part1

    概述

    Microsoft Parallel Extensions to the .NET Framework 3.5是一个托管编程模型,用于数据并行化和任务并行化,并可对统一在共同的工作调度程序之下的并行硬件进行协调。 Parallel Extensions to the .NET Framework 3.5使开发者更容易编写出充分发挥并行硬件的优势的程序,不但能随着处理器数量的增长而提高性能,而且避免了许多旧有并发编程模型的复杂性。

    你可以从这里下载Microsoft Parallel Extensions to the .NET Framework 3.5 June 2008 CTP版本,安装后会注册一个System.Threading.dll程序集到GAC中。Parallel Extensions主要由两部分组成:Task Parallel Library(TPL)和Parallel LINQ (PLINQ),它们将会集成在.NET Framework 4.0中。

    简单调用

    在开始之前,我们不妨停下来思考几个问题:如果有多个线程在同一时间访问同一个变量,它们之间可能会互相影响,该如何解决?如果有多个线程同时锁住了一些资源,由于互相等待而造成死锁,该如何解决?如果觉的这些问题很难解决,那就不要思考了,有了Parallel.Invoke,无需再去考虑这些令人头疼的问题,我们先定义三个任务:

    private void Task1()
    {
        Thread.Sleep(1000);
    }
    private void Task2()
    {
        Thread.Sleep(2000);
    }
    private void Task3()
    {
        Thread.Sleep(3000);
    }

    并行调用这三个任务,只需要一句话:

    Parallel.Invoke(Task1, Task2, Task3);

    除此之外,还可以把所有的任务放在一个Action数据组中,再进行调用,如下代码片段,这在某些场景中会非常的有用,我们在设计阶段无需考虑最终运行时将会有多少个任务会执行:

    Action[] actions = { Task1, Task2, Task3 };
    Parallel.Invoke(actions);

    我们不妨对Parallel.Invoke做一个简单的测试,如下代码片段所示:

    private long InvokeSequential()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        Task1();
        Task2();
        Task3();
        watch.Stop();
    
        return watch.ElapsedMilliseconds;
    }
    
    private long InvokeParallel()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        Parallel.Invoke(Task1, Task2, Task3);
        watch.Stop();
    
        return watch.ElapsedMilliseconds;
    }
    
    private long InvokeParallelArray()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        Action[] actions = { Task1, Task2, Task3 };
        Parallel.Invoke(actions);
        watch.Stop();
    
        return watch.ElapsedMilliseconds;
    }

    来看看最后的结果:

    TerryLee_0199  

    循环调用

    循环执行某件事情应该是我们编程中经常遇到的问题,但是之前所有的循环只能顺序的进行执行,如下面这段代码,再平常不过了:

    for (int i = 0; i < 10; i++)
    {
        Compute(i);
    } 

    在Parallel Extensions中,可以使用Parallel.For来并行的执行循环任务:

    Parallel.For(0, 10,
            delegate (int i){
                Compute(i);
            }
        );

    甚至有了Lambda表达式,还可以更简单的编写为:

    Parallel.For(0, 10,
            i => { Compute(i);}
        );

    现在,我们再来做一个简单的测试,代码如下:

    private static long SequentialForLoop()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < 10; i++)
        {
            Compute(i);
        } 
        watch.Stop();
        return watch.ElapsedMilliseconds;
    }
    
    private static long ParallelForLoop()
    {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        Parallel.For(0, 10,
                i => { Compute(i);}
            );
        watch.Stop();
        return watch.ElapsedMilliseconds;
    }
    
    private static void Compute(int i)
    {
        Thread.Sleep(200 * i);
    }

    测试结果如下:

    TerryLee_0200

    类似的在Parallel中还提供了Parallel.ForEach方法,如下图所示:

    TerryLee_0201 

    我们使用类似于如下的代码来使用该方法:

    List<int> data = new List<int> { 1, 2, 3, 4, 5 };
    Parallel.ForEach(
            data,
            i => { Compute(i); }
        );

    总结

    以上简单的介绍了Task Parallel Library中的Parallel, 希望对大家有所帮助

  • 相关阅读:
    centos 7 和 centoa 8的区别
    centos7制作U盘启动盘
    juypyter notebook安装
    Centos6安装MariaDB
    提job
    report a bug and update
    runtest提交job
    bug
    ps常用选项
    每日一句
  • 原文地址:https://www.cnblogs.com/liufei88866/p/3133641.html
Copyright © 2011-2022 走看看