并行开发基础

  并行开发适合用于分解计算密集型的任务片段,并将它们分配给多个线程。

 1、数据的并行处理

   有一批数据,需要对每个元素进行相同的操作。该操作是计算密集型,需要耗费一定的时间。Parallel类型的 ForEach 方法就是专门为此设计的。

Parallel的ForEach可以对一系列值进行并行处理。还有类似的解决方案,就是PLINQ(并行LINQ)。

Parallel和PLINQ的区别:PLINQ假设可以使用计算机的所以CPU核,而Parallel会根据CPU的状态进行动态调整。

Parallel的ForEach是并行版本的foreach版本。Parallel类也提供了并行版本的for循环Parallel.For。如果有多个数组的数据,并且采用了相同的索引,Parallel.For方法就比较适合。

 

2、并行聚合

  在并行操作结束时,需要集合结果,包括累加和、平均值等。

  在Parallel中可以使用加锁的方法,来进行聚合。 

  PLINQ中聚合的支持,比Parallel类使用更顺手。

  

    private static int ParallelSum(IEnumerable<int> values)
        {
            return values.AsParallel<int>().Sum();
        }

 

3、并行调用

  需要并行调用一批方法,并且这些方法(大部分)是互相独立的。 Parallel.Invoke方法就是用于这种场合。

  例如并行调用一个方法10次:

    private static void DoAction10Count(Action action)
        {
            Action[] actions = Enumerable.Repeat(action, 10).ToArray();
            Parallel.Invoke(actions);
        }

对于简单的并行调用, Parallel.Invoke是一个不错的方式。但是,对于每一个输入都要调用一个操作,改用Parallel.Foreach,或者每一个操作要产生一个输出,改用PLINQ可能更好。

 

4、动态并行

  并行任务的结构和数量要在运行时才能确定,这是一种更复杂的并行编程。

  任务并行库(TPL)是以Task类为中心构建的。Parallel和PLINQ都是为了使用方便,对Task类的封装。

  实现动态并行最简单的做法就是直接使用 Task 类。

  

  在并行中是用Task和在异步中使用Task完全不同:

    并行:并行任务可以使用阻塞的成员函数。例如:Task.WaitAll,Task.Wait,Taks.Result,Taks.WaitAny。并行任务通常也使用AttachedToParent来建立任务之间的父/子关系。

       并行任务的创建需要使用Task.Run或者Task.Factory.StartNew方法。

    

    异步:异步任务应该避免使用阻塞的成员函数。而应该使用await,Task.WhenAll、Taks.WhenAny。

 

5、并行LINQ

  需要对一批数据进行处理,生成另外一批数据,或者对数据进行统计。

  PLINQ为各种操作提供了并行操作,包括过滤、投影、聚合等。

  PLINQ适合于对数据流进行操作,一个数据队列做为输入,一个数据队列做为输出。

 

posted @ 2018-06-13 13:53 _York 阅读(...) 评论(...) 编辑 收藏