Today we're going to talk about one of the key components of parallel extensions, PLINQ (Parallel LINQ). Microsoft's position with PLINQ in Parallel FX is that PLINQ is a high-level application of the TPL (Task Parallel Library). Because of the short time that Microsoft has developed for TPL, the quality of this Community preview version of TPL is still relatively low, and Microsoft's release of this version is designed to better get feedback from the development community, so that PLINQ has a higher quality, So the current PLINQ is based on ThreadPool implementations rather than on the TPL API. However, this is only a different internal implementation, the subsequent formal release of PLINQ's external interface changes should not be too large.
How do I use PLINQ?
1 adding System.Threading.dll to references
2 encapsulates the data into iparallelenumerable by invoking the System.Linq.ParallelQuery.AsParallel extension method.
Data parallelism based on declarative method
Invoking the AsParallel extension method enables the compiler to use the System.Linq.ParallelEnumerable version of the query operator instead of the System.Linq.Enumerable. As anyone familiar with LINQ knows, a query expression is converted to a call to an extension method at compile-time. For Linq, all extension methods are encapsulated in the System.Linq.Enumerable static class, which defines an extension method for the IEnumerable data source. And for PLINQ, All extension methods are encapsulated in the System.Linq.ParallelEnumerable static class, and the class is aimed at iparallelenumerable data source extension methods, and is a mirror of the System.Linq.Enumerable static class extension method, but only Queries are evaluated in a parallel manner. The IParallelEnumerable interface inherits from the IEnumerable interface, so PLINQ also has the feature of deferred execution of LINQ and the execution of foreach.
To get a clear idea of how the system will use the System.Linq.Enumerable version of the query operator into the System.Linq.ParallelEnumerable version, let's take a look at System.Linq.ParallelQuery.AsPara Llel Method:
public static IParallelEnumerable AsParallel(IEnumerable source)
It is obvious that this approach is to convert IEnumerable data sources into iparallelenumerable so that parallel versions of the operation are used. This is the way in which parallel schemas use data in parallel using asparallel declarations, as well as PLINQ's programming model.
So this declarative data parallelism makes it easy to transform from LINQ to PLINQ, for example, we have this LINQ code fragment:
string[] words = new[] { "Welcome", "to", "Beijing" };
(from word in words select Process(word)).ToArray();
It's easy to turn it into a PLINQ version:
string[] words = new[] { "Welcome", "to", "Beijing" };
(from word in words.AsParallel() select Process(word)).ToArray();
Of course, if you are using a query (that is, calling a static extension function directly) instead of a query expression (sometimes the query expression does not provide the corresponding expression statement, for example, the query expression statement for Skip and take is not provided in c#3.0), We can migrate LINQ to PLINQ only by calling the query action function directly, and in addition to calling the AsParallel method, we need to change the method that calls the enumerable directly to the parallelenumerable call, for example:
IEnumerable data = ...;
var q = Enumerable.Select(Enumerable.OrderBy(
Enumerable.Where(data, (x) => p(x)),(x) => k(x)),(x) => f(x));
foreach (var e in q) a(e);
To use PLINQ, you must rewrite the query as follows:
IEnumerable data = ...;
var q = ParallelEnumerable.Select(ParallelEnumerable.OrderBy(
ParallelEnumerable.Where(data.AsParallel(), (x) => p(x)),
(x) => k(x)),(x) => f(x));
foreach (var e in q) a(e);
Note: Some query operators are two yuan, using two IEnumerable as input parameters (such as join), the type of the leftmost data source determines whether to use LINQ or PLINQ, so you only need to call AsParallel on the first data source to make the query parallel, for example:
IEnumerable leftData = ..., rightData = ...;
var q = from x in leftData.AsParallel()
join y in rightData on x.a == y.b
select f(x, y);