• 并行Linq


      .Net 4在 System.Linq 名称空间中包含一个新类 ParallelEnumerable,可以分解查询的工作使其分布在多个线程上。尽管 Enumerable 类给 IEnumerable<T> 接口定义了扩展方法,但 ParallelEnumerable 类的大多数扩展方法是 Parallel<TSource> 类的扩展。一个重要的例外是 AsParallel()方法,它扩展了 IEnumerable<TSource> 接口,返回 ParallelQuery<TSource> 类,所以正常的集合类可以以平行方式查询。

    并行查询

      为了说明并行LINQ,需要一个大型集合。对于可以放在CPU的缓存中的小集合,并行LINQ看不出效果。在下面的代码中,用随机值填充一个大型的 int 数组:

               const int arraySize = 100000000;
                var data = new int[arraySize];
                var r = new Random ( );
                for ( int i = 0; i < arraySize; i++ ) {
                    data[i] = r.Next ( 40 );
                }

      现在可以使用LINQ查询筛选数据,获取所筛选数据的总和。该查询用 where 子句定义了一个筛选器,仅汇总对应值小于20的项,接着调用聚合函数 Sum()方法。与平时的LINQ查询的唯一区别是,这次调用了 AsParallel() 方法。

                var sum = ( from x in data.AsParallel ( )
                            where x < 20
                            select x ).Sum ( );

      与平时LINQ查询一样,编译器会修改语法,以调用 AsParallel()、Where()、Select()和Sum()方法。AsParallel()方法用 ParallelEnumerable 类定义,以扩展 IEnumerable<T> 接口,所以可以对简单的数组调用它。AsParallel()方法返回 ParallelQuery<TSource>。因为返回的类型,所以编译器选择的Where()方法是 ParallelEnumerable.Where(),而不是 Enumerable.Where() 。在下面的代码中, Select()和 Sum()方法也来自 ParallelEnumerable 类。与Enumerable类的实现代码相反,对于ParallelEnumerable类,查询是分区的,以便 多个线程可以同时处理该查询。数组可以分为多个部分,其中每个部分由不同的线程处理,以筛选其余项。完成分区的工作后,就需要合并,获得所有部分的总和。

                var sum = data.AsParallel ( ).Where ( x => x < 20 ).Select ( x => x ).Sum ( );

      运行这行代码会启动任务管理器,这样就可以看出系统的所有CPU都在忙碌。如果删除AsParallel()方法,就不可能使用多个CPU。当然,如果系统上没有多个CPU,就不会看到并行版本带来的改进。

    分区器

      AsParallel()方法不仅扩展了 IEnumerable<T>接口,还扩展了Partitioner类。通过它,可以影响要创建的分区。

      Partitioner类用System.Collection.Concurrent名称空间定义,并且有不同的变体。Create()方法接受实现了 IList<T>类的数组或对象。根据这一点,以及类型的参数 loadBalance 和该方法的一些重载版本,会返回一个不同的Partitioner类型。对于数组, .NET 4 包含派生自抽象基类OrderablePartitioner<TSource>的DynamicPartitionerForArray<TSource>类和StaticPartitionerForArray<TSource>类和StaticParitionerForArray<TSource>类。

      修改上面一小节的代码,手工创建一个分区器,而不是使用默认的分区器:

                var sum = ( from x in Partitioner.Create ( data, true ).AsParallel ( )
                            where x < 20
                            select x ).Sum ( );

      也可以调用WithExecutionMode()和WithDegreeOfParallelism()方法,来影响并行机制。对于WithExecutionMode()方法可以传递ParallelExecutionMode()的一个Default值或者ForceParallelism值。默认情况下,并行LINQ避免使用系统开销很高的并行机制。对于WithDegreeOfParallelism()方法,可以传递一个整数值,以指定应并行运行的最大任务数。

  • 相关阅读:
    Python xlrd.biffh.XLRDError: Excel xlsx file; not supported
    Python 报/usr/bin/python^M: bad interpreter: No such file or directory
    Linux curl命令
    课程学习总结报告
    信息安全实验二
    结合中断上下文切换和进程上下文切换分析linux内核的一般执行过程
    深入理解Linux系统调用
    基于mykernel2.0编写一个操作系统内核
    如何评测软件工程知识技能水平
    创新产品的需求分析:未来图书会是什么样子?
  • 原文地址:https://www.cnblogs.com/xiaoyu5062/p/2581709.html
Copyright © 2020-2023  润新知