これら2つの違いは何ですか?
比較する最良の方法は何ですか?
それは常により良い plinq ですか?
plinq を使用する場合
Linq は、同様の問題を解決するために連携して機能するテクノロジのコレクションです。それらのすべてで、データのソース (xml ファイルまたはファイル、データベースの内容、メモリ内のオブジェクトのコレクション) があり、一部またはすべてを取得する必要があります。このデータを分析し、何らかの方法でそれに基づいて行動します。Linq は、次のような一連の問題の共通性に取り組んでいます。
var brithdays = from user in users where
user.dob.Date == DateTime.Today && user.ReceiveMails
select new{user.Firstname, user.Lastname, user.Email};
foreach(bdUser in birthdays)
SendBirthdayMail(bdUser.Firstname, bdUser.Lastname, bdUser.Email);
同等のもの (Linq 関連のクラスとメソッドを従来の C# 構文で明示的に使用):
var birthdays = users
.Where(user => user.dob.Date == DateTime.Today)
.Select(user => new{user.Firstname, user.Lastname, user.Email});
foreach(bdUser in birthdays)
SendBirthdayMail(bdUser.Firstname, bdUser.Lastname, bdUser.Email);
どちらも、データベース呼び出し、xml ドキュメントの解析、またはオブジェクトの配列の検索に変換されるかどうかに関係なく機能するコードの例です。
唯一の違いは、オブジェクトの種類users
です。それがリスト、配列、またはその他の列挙可能なコレクションである場合、それは linq-to-objects であり、それSystem.Data.Linq.Table
が linq to sql である場合です。前者はインメモリ操作になり、後者は SQL クエリで実行され、可能な限り遅くインメモリ オブジェクトに逆シリアル化されます。
ParallelQuery
メモリ内の列挙可能なコレクションを呼び出すことによって生成された場合.AsParallel
、クエリはメモリ内で実行され、(ほとんどの場合) 並列化され、複数のスレッドによって実行されます。理想的には、各コアをビジー状態にして作業を進めます。 .
明らかに、ここでのアイデアはより速くすることです。それがうまくいくとき、それはうまくいきます。
ただし、いくつかの欠点があります。
まず、並列化が不可能な場合でも、並列化を進めるには常にいくらかのオーバーヘッドがあります。データに対して十分な作業が行われていない場合、このオーバーヘッドは潜在的な利益を上回ります。
第 2 に、並列処理の利点は、利用可能なコアによって異なります。4 コア マシンでリソースをブロックしないクエリを使用すると、理論的には 4 倍の速度が得られます (4 ハイパースレッディングでは、それ以上またはそれ以下になる可能性がありますが、ハイパースレッドによって CPU の一部が 2 倍になったとしても、明確な 2 倍の増加にはなりません)。シングルコアで同じクエリを使用するか、1 つのコアしか使用できないことを意味するプロセッサ アフィニティ (たとえば、「Web ガーデン」モードの Web サーバー) を使用すると、速度が向上しません。リソースがブロックされている場合でも利益が得られる可能性がありますが、その場合の利益はマシンによって異なります。
第 3 に、共有リソース (コレクションの結果が出力されている可能性があります) が非スレッドセーフな方法で使用されている場合、誤った結果やクラッシュなどでかなりひどい事態が発生する可能性があります。
第 4 に、スレッド セーフな方法で使用されている共有リソースがあり、そのスレッド セーフがロックに由来する場合、並列化によるすべての利点を台無しにするボトルネックになる十分な競合が発生する可能性があります。
第 5 に、4 つの異なるスレッドで多かれ少なかれ同じアルゴリズムで動作している 4 コア マシンがある場合 (おそらく、クライアントが 4 つあるためクライアント サーバーの状況で、またはデスクトップの状況で、より高い位置にある同様のタスクのセットから)。プロセス)、彼らはすでにそれらのコアを最大限に活用しています。4 つのコアすべてで処理されるようにアルゴリズムの作業を分割するということは、それぞれ 1 つのコアを使用する 4 つのスレッドから、4 つのコアをめぐって戦う 16 のスレッドに移行したことを意味します。せいぜい同じで、おそらくオーバーヘッドがわずかに悪化するでしょう。
多くの場合、それはまだ大きな勝利になる可能性がありますが、上記のことから、常にそうなるとは限らないことは明らかです。
PLinq は Linq の並列バージョンです。一部のクエリは複数のスレッドで実行でき、PLinq によってパフォーマンスが向上します。
ただし、他のクエリを並行して実行することはできません。並行して実行すると、間違った結果が返されます。したがって、いつ PLinq を使用するかは、クエリごとに決定し、パフォーマンスが実際に向上することを確認する必要があります。
MSDNには、それに関する多くのドキュメントがあります。
Joe Albahari による Threading in C# によると、 PLINQを使用している間は匿名型を避けることを検討してください。
匿名型 (クラスであり、したがって参照型である) は、ヒープベースの割り当てとその後のガベージ コレクションのコストが発生します。
(...)
スタックベースの割り当ては高度に並列化できますが (各スレッドが独自のスタックを持っているため)、すべてのスレッドが同じヒープに対して競合する必要があり、単一のメモリ マネージャーとガベージ コレクターによって管理されます。