Www Xddl Info Introducing Dot Net_2

Chia sẻ: Up Upload | Ngày: | Loại File: PDF | Số trang:45

0
17
lượt xem
3

Www Xddl Info Introducing Dot Net_2

Mô tả tài liệu

Tham khảo tài liệu 'www xddl info introducing dot net_2', công nghệ thông tin, kỹ thuật lập trình phục vụ nhu cầu học tập, nghiên cứu và làm việc hiệu quả

Chủ đề:

Bình luận(0)

Lưu

Nội dung Text: Www Xddl Info Introducing Dot Net_2

2. CHAPTER 5 PARALLELIZATION AND THREADING ENHANCEMENTS Stocks.Add(new StockQuote { ID = 7, Company = "Amazon", Price = 20.8m }); Stocks.Add(new StockQuote { ID = 8, Company = "HSBC", Price = 54.6m }); Stocks.Add(new StockQuote { ID = 9, Company = "Barclays", Price = 23.2m }); Stocks.Add(new StockQuote { ID = 10, Company = "Gilette", Price = 1.84m }); } private static void RunInSerial() { for (int i = 0; i < Stocks.Count; i++) { Console.WriteLine("Serial processing stock: {0}",Stocks[i].Company); StockService.CallService(Stocks[i]); Console.WriteLine(); } } private static void RunInParallel() { Parallel.For(0, Stocks.Count, i => { Console.WriteLine("Parallel processing stock: {0}", Stocks[i].Company); StockService.CallService(Stocks[i]); Console.WriteLine(); }); } } Create a new class called StockQuote and add the following code: 3. Listing 5-1. Parallel For Loop public class StockQuote { public int ID {get; set;} public string Company { get; set; } public decimal Price{get; set;} } Create a new class called StockService and enter the following code: 4. public class StockService { public static decimal CallService(StockQuote Quote) { Console.WriteLine("Executing long task for {0}", Quote.Company); var rand = new Random(DateTime.Now.Millisecond); System.Threading.Thread.Sleep(1000); return Convert.ToDecimal(rand.NextDouble()); } } Press F5 to run the code. When I run the code on my machine I receive the output shown in Figure 5-2. 103
3. CHAPTER 5 PARALLELIZATION AND THREADING ENHANCEMENTS Figure 5-2. O utput of parallel for loop against serial processing Are the stock quotes processed incrementally or in a random order? You might have noted that your application did not necessarily process the stock quotes in the order in which they were added to the list when run in parallel. This is because work was divided between the cores on your machine, so it’s important to remember that work might not (and probably won’t) be processed sequentially. You will look at how the work is shared out in more detail when we look at the new task functionality. Try running the code again. Do you get similar results? The quotes might be processed in a slightly different order, and speed increases might vary slightly depending on what other applications are doing on your machine. When measuring performance, be sure to perform a number of tests. Let’s now take a look at the syntax used in the Parallel.For() loop example: System.Threading.Parallel.For(0, Stocks.Count, i => { .. } The Parallel.For() method actually has 12 different overloads, but this particular version accepts 3 parameters: 0 is the counter for the start of the loop. • Stocks.Count lets the loop know when to stop. • i=>: Our friendly lambda statement (or inline function) with the variable i • representing the current iteration, which allows you to query the list of stocks. 104
4. CHAPTER 5 PARALLELIZATION AND THREADING ENHANCEMENTS ParallelOptions Some of the various parallel overloads allow you to specify options such as the number of cores to use when running the loop in parallel by using the ParallelOptions class. The following code limits the number of cores to use for processing to two. You might want to do this to ensure cores are available for other applications. ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 2 }; Parallel.For(0, 100, options, x=> { //Do something }); Parallel.ForEach() Similar to the Parallel.For() loop, the Parallel.ForEach() method allows you to iterate through an object supporting the IEnumerable interface: Parallel.ForEach(Stocks, stock => { StockService.CallService(stock); }); Warning: Parallelization Can Hurt Performance Parallelizing code contains overhead and can actually slow down your code, including when there are loops that run a very small amounts of code in each iteration. Please refer to the following articles about why this occurs: http://msdn.microsoft.com/en-us/library/dd560853(VS.100).aspx • http://en.wikipedia.org/wiki/Context_switch • Parallel.Invoke() The Parallel.Invoke() method can be used to execute code in parallel. It has the following syntax: Parallel.Invoke(()=>StockService.CallService(Stocks[0]), () => StockService.CallService(Stocks[1]), () => StockService.CallService(Stocks[2]) ); When you use Parallel.Invoke() or any of the parallel loops, the parallel extensions are behind the scenes using tasks. Let’s take a look at tasks now. 105
14. CHAPTER 5 PARALLELIZATION AND THREADING ENHANCEMENTS N OTE Daniel Moth has recorded some great screen casts and written some excellent articles on parallel debugging at http://www.danielmoth.com/Blog/2009/11/parallel-debugging.html. PLINQ (Parallel LINQ) PLINQ is the parallelized version of LINQ to objects and supports all existing LINQ operators and functionality with a few new options for fine-grained control of parallelization functionality. The new functionality has been introduced through the interface IParallelEnumerable> t hat inherits from IEnumerable>. At the time of writing, LINQ to SQL and LINQ to Entities will not benefit from parallelization because in these cases the query is executed on the database or the provider, so .NET cannot parallelize it. Why Not Parallelize All LINQ Queries Automatically? Parallelizing LINQ queries automatically is potentially the ultimate goal for LINQ, but it can introduce some issues (particularly around ordering), so at present you have to opt in to the parallel model. A WORD OF WARNING When using PLINQ, it is important to ensure that your query does not modify the result set because this might have unforeseen effects if values are utilized later in the query. PLINQ will do its best to work out best how to process the query (including not running it in parallel at all), but do you really want to take the chance of weird, scary, and hard- to-reproduce bugs? Hello PLINQ This example iterates through all the objects in the stock list, calls an external service, and processes the result. Writing such a query in traditional LINQ might look something like this: var query = from s in Stocks let result = StockService.CallService(s) select result; To run the same query in parallel, simply use the .AsParallel() extension method to the Stocks object: var query = from s in Stocks.AsParallel() let result = StockService.CallService(s) select result; It really is as easy as that (well almost...). 115
15. CHAPTER 5 PARALLELIZATION AND THREADING ENHANCEMENTS Ordering Results To order the results of your queries, use the AsOrdered() method to tell .NET to buffer the results before sorting them. This will slow the query down slightly because PLINQ now has to do additional work to preserve the ordering: var query = from s in Stocks.AsParallel().AsOrdered() orderby s.Company let company = s.Company let result = StockService.CallService(s) Note that the AsUnordered() operator can be used to tell PLINQ that you no longer care about ordering items. ForAll Operator() Iterating through the results of a LINQ query requires that all the output be merged together. If results ordering is not important, you should use the ForAll() operator, which avoids merging the results set, thus executing more quickly: query.ForAll(result => Console.WriteLine(result)); T IP Query performance can also be further increased by using the orderby clause in your LINQ query when combined with a filtering operation such as where because the ordering will then be applied only to the filtered results. AsSequential() The AsSequential() method forces PLINQ to process all operations sequentially, which can sometimes be required when you are working with user-defined query methods: var query = from s in Stocks.AsParallel().AsSequential() let result = StockService.CallService(s) select result; WithMergeOptions The WithMergeOptions operator allows you to tell PLINQ how you want results to be merged when processing is complete. PLINQ is not guaranteed to do this, though. WithMergeOptions operates in three modes: NotBuffered: Results are returned sooner, but slower overall. • FullyBuffered: Quickest option but results are returned slowest. • AutoBuffered: Chunks items returned and offers a middle ground between the • other two options. 116
16. CHAPTER 5 PARALLELIZATION AND THREADING ENHANCEMENTS PLINQ performance Sometimes the overhead of parallelizing a query can actually make it perform more slowly than if it was run sequentially, so be sure to measure your queries’ performance. LINQ queries are not actually executed until you enumerate through them (deferred execution), so measuring performance can be slightly harder. Thus if you want to measure the performance, be sure to iterate through the data in the result set or call a method such as ToList. T IP Visual Studio Premium edition onward also contains a parallel performance analyzer, which allows you to compare the performance of queries. Cancelling a PLINQ Query You can cancel a PLINQ query by passing in a CancellationTokenSource, which is discussed very shortly, into the WithCancellation() method. Exceptions and Parallel LINQ When a query is run in parallel, exceptions can occur in multiple threads. PLINQ aggregates these exceptions into an AggregateException class and returns them back to the caller. You can then iterate through each individual exception. If you run the following example, you need to modify a setting in the IDE to see it working. To do this, go to Tools Options Debugging General and uncheck the Enable Just my code option or run in Release mode. //select stock that doesnt exist var query = from s in Stocks.AsParallel() let result = StockService.CallService(Stocks[11]) select result; try { query.ForAll(result=>Console.WriteLine(result.ToString())); } catch (AggregateException e) { foreach (var ex in e.InnerExceptions) { Console.WriteLine(ex.Message); } } 117