65.9K
CodeProject 正在变化。 阅读更多。
Home

PLINQ 即将推出 (PFX)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (14投票s)

2007 年 10 月 24 日

CPOL

4分钟阅读

viewsIcon

31690

多核硬件的普及速度非常快,然而多核编程并非易事,Parallel FX (PFX) 应运而生。

引言

自从 LINQ 发布之初,我就一直听说 PLINQ(并行 LINQ)。它的理念是利用 .NET 3.5 中提供的新函数式编程风格,以便在多核机器上获得更好的性能。这个想法从一开始就很棒,现在它以 Parallel FX 或 PFX 的新名称实现了。

注意: 在撰写本文时,微软尚未发布任何版本的 PFX。本文仅提供来自微软内外多个来源收集的未来展望。一旦 CTP 发布,文章将进行更新,请将此链接保存在您的书签中。

背景

LINQ(语言集成查询)是 C# 3.0、VB 9 和 .NET 3.5 中的一项新功能,它将查询的概念作为一等公民引入到下一版本的 .NET 编程语言中。其理念是提供一种更好的抽象方式来处理数据,从而使编译器和运行时能够在许多方面提供帮助。其中一种方式就是优化性能。

PLINQ 是一种让您的代码在多核机器(现在和将来都很常见)上运行的方式,而无需显式定义线程、锁等。

提供的编程模型非常简单,并利用了相同的 LINQ 模型。新程序集名为 System.Concurrency.dll,它包含了名为 IParallelEnumerable<T> 的新接口。它还为所有实现旧 IEnumerable 的集合和数组添加了一个扩展方法。该扩展方法称为 AsParrallel<T>,它将任何集合转换为 Parallel 启用类型的集合,即 IParallelEnumerable<T>

Using the Code

看看下面的代码

// or whatever complex data collection
IEnumerable<int> data = new int[] {1, 2, 3, 4, 5, 6}; 
var q = data.Where(x => x > 4).OrderBy(x=>x).Select(x => x);
foreach (var i in q) ....

这段代码是您在 C# 3.0 中已经写过的。现在,如果您想添加 PLINQ 支持,只需在使用任何查询操作之前添加 AsParallel 函数调用,之前的代码将如下所示:

IEnumerable data = new int[] {1, 2, 3, 4, 5, 6}; // or whatever complex data collection
var q = data.AsParallel().Where(x => x > 4).OrderBy(x=>x).Select(x => x);
foreach (var i in q) ....

或者您也可以用 LINQ 查询的风格来写:

IEnumerable data = new int[] {1, 2, 3, 4, 5, 6}; // or whatever complex data collection
var q = from i in data.AsParallel()
        where i > 4
        orderby i
        select i;
foreach(var i in q) .... 

添加 AsParallel 函数调用后,PLINQ 将能够透明地在所有可用处理器上执行 OrderByWhereSelectGroupBy 等操作。您无需显式创建线程、锁和管理并发执行(除非您在做一些非常庞大的事情)。这并不意味着您只能对查询使用 PLINQ 的强大功能。ParallelEnumerable 类还添加了一些额外的扩展方法,例如 ForAll 方法。如果您要对某个集合的所有成员应用某种操作,ForAll 方法会很有用,因为 ForAll 函数将并行地对集合的所有成员执行此操作。

IEnumerable data = new int[] {1, 2, 3, 4, 5, 6}; // or whatever complex data collection
data.ForAll(i=>Console.WriteLine(i));

上面的代码示例将打印出数组的所有成员。如果您想象调用一个更复杂的函数,对每个数组成员执行一些繁重的工作,ForAll 将通过利用并行数据处理技术为您提供额外的强大功能来更快地完成任务。这并不是 System.Concurrency 库中引入的所有新东西。新的 Parallel 类也是一个不错的补充。它提供了一些额外的通用并行执行功能,因此与 LINQ 无关。最重要的一部分是 Parallel.For 函数,正如您从名称中所期望的那样,它执行一个 parallel 循环。请看下面的代码:

void ParMatrixMult(int size, double[,] m1, double[,] m2, double[,] result)
{
  Parallel.For( 0, size, delegate(int i) {
    for (int j = 0; j < size; j++) {
      result[i, j] = 0;
      for (int k = 0; k < size; k++) {
        result[i, j] += m1[i, k] * m2[k, j];
      }
    }
  });
}

这是我从 这里 获得的一个示例。它展示了使用 Parallel.For 进行矩阵乘法。正如您所看到的,Parallel.For 方法接受起始索引和长度,然后是一个要执行的 delegate。还有一个 Parallel.Aggregate 函数,可用于安全地对并行循环中的特定数据项进行聚合。这就是我一篇帖子中能写完的所有内容,但是 System.Concurrency 包含更多很棒的 API。

关注点

PLINQ = PFX。PLINQ 仅仅是 LINQ 为软件开发带来的未来愿景。PFX 是一个更大的概念,PLINQ 只是其一部分;它附带了许多通用 API,可以帮助您解决可能遇到的各种并发问题。

资源

以下是进一步阅读的资源。我最初是在 我的博客 上撰写本文的。

  1. 为多核机器优化托管代码
  2. 在多核处理器上运行查询
  3. Channel9 视频:并发时代的编程(Andres Hejlsberg 和 Joe Duffy)

历史

  • 2007 年 10 月 24 日:初始发布
© . All rights reserved.