BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース .NET4.0ベータ1でPLINQはどう変わる?

.NET4.0ベータ1でPLINQはどう変わる?

原文(投稿日:2009/4/30)へのリンク

Microsoft並列コンピュータチームのプログラムマネージャであるEd Essey氏は、まもなくリリースされる.NET 4.0ベータ1で登場する予定の最新版のPLINQの変更点について言及している。それによると、PLINQには"With"演算子パターン、実行モード、キャンセル、リファクタリング、性能向上などが盛り込まれる。

PLINQのベータ1の変更点の完全な一覧は次の通り。

  • With演算子パターン
  • 実行モード
  • キャンセル
  • カスタムパーティショニング
  • リファクタリング
  • マージオプション
  • AsMergedをAsSequentialに変更
  • 二項演算子の両辺にAsParallelが新たに必要に
  • 性能改善
  • めったに使われない演算子を廃止

“With” 演算子パターン: 新たに次の4メソッドが導入された。

  • e.AsParallel().WithDegreeOfParallelism
  • e.AsParallel().WithExecutionMode
  • e.AsParallel().WithCancellation
  • e.AsParallel().WithMergeOptions

実行モード:PLINQはLINQ-to-Objectsクエリと同様のリソースを消費するように調整されている。特にメモリ消費については。PLINQの呼び出しが多くのリソースを消費すると見なすと、その呼び出しは並列ではなくシーケンシャルに実行される。シーケンシャルな実行へと切り替える判断はクエリーの形に基づいてなされる。次のクエリーではシーケンシャルに実行される。

  • インデックス付きのSelect、インデックス付きのWhere、インデックス付きのSelectManyを含むクエリや、元の順番ではもはやないインデックスでのElementAt。インデックスによる順番は、順序の変更をする演算子(OrderByなど)や要素を除去する演算子(Whereなど)に敏感である。
  • Take、TakeWhile、Skip、SkipWhile演算子を含むクエリのうち、インデックスが元の順番ではないもの(上の項目を参照)。
  • Zip、SequenceEqualsを含むクエリのうち、1つのデータソースのインデックスが元の順番ではなく、しかもその他のデータソースがインデックス可能でないもの(要するに配列やIList<T>のこと)。
  • Concatを含むクエリのうち、それがインデックス可能なデータソースに適用されていないもの。
  • Reverseを含むクエリのうち、それがインデックス可能なデータソースに適用されていないもの。

強制的に並列実行させたいときは次のようにすればよい。

e.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism)

キャンセル:並列操作は次のようにキャンセルすることができる。

var cts = new CancellationTokenSource();

var q = a.AsParallel().WithCancellation(cts.Token).Where(x=>Filter(x)).Select(x=>DoWork(x);

-- 別のスレッド --

foreach (var e in q) { … }  // 状態(1)

-- 別のスレッド --

var l = q.ToList(); // 状態(2)

-- 別のスレッド --

cts.Cancel(); // 状態(1)(2)を含むすべてのしかかり中のクエリもキャンセルしようとする

カスタムパーティショニング:Partitioner<TSource>、OrderablePartitioner<TSource>クラスとそのファクトリクラスPartitionerはデータの分割の仕方をコントロールできるようにする。

リファクタリング:  インターフェースIParallelEnumerable、IParallelEnumerable<T>およびIParallelOrderedEnumerable<T> は、インターフェースから継承できない抽象クラスになった。これらはそもそも継承されることを意図しないものだからだ。

マージオプション:「ParallelMergeOptionsの処理はAsMergedに移動した。マージバッファリングの指定はWithMergeOptionsメソッドで行うようになった」

AsMerged:AsMergedは見慣れたAsParallelと同じようにAsSequentialと改名された。

二項演算子:2つのデータソースを持つLINQ演算子は双方にAsParallelが必要になった。

a.AsParallel().AsOrdered().Zip(b, (x, y) => x*y);

を並列化するには

a.AsParallel().AsOrdered().Zip(b.AsParallel(), (x, y) => x*y);

とするか、

a.AsParallel().AsOrdered().Zip(b.AsParallel().AsOrdered(), (x, y) => x*y);

のようにする。影響する演算子は、Zip、Join、GroupJoin、Concat、SequenceEqual、Union、Intersect、Except。

性能改善:

1. 順序を保持するパイプライン方式のマージ。以前はAsOrderedをクエリに当てて、それぞれの要素がyieldされる前に強制的にクエリ全体が実行されていた。これはもう最適化され、マージオプションがDefault(AutoBuffered)かNotBufferedで作られたときには、クエリからの要素はyieldされることができる。

2. IList<T>を実装していないデータソースの公平な分割の改善

3. IList<T>や配列へのいくつかのクエリの性能向上

4. パーティショニングのチャンクサイズのチューニング。パーティショニングのチャンクはIList<T>や配列(つまり、インデックス化できないデータソース)以外のデータソースへのクエリをパーティショニングするもっとも一般的な仕組みである。これからは、チャンクのサイズはアクセスされればされるほど大きくなる。これは、2つのケース、すなわち小さいデータセットへのクエリだがクエリの中で高価なデリゲートと大きなデータセットへのクエリだがクエリの中の高価ではないデリゲートの間のバランスをとるためである。

5. falseになりそうな共有ケースを除去した。これによっていくつかのケースで6倍の改善になった。

めったに使われない演算子を廃止:性能上の理由で作られた演算子のうち、LINQ上で性能に寄与しなかったいくつかの演算子が廃止になった。どの演算子が廃止になったかは明記されなかった。

この記事に星をつける

おすすめ度
スタイル

BT