Huseyin YILDIZ Software Design Engineer Microsoft Corporation SESSION CODE: DEV314
Op1 Op2 Op3 Op4 Op5 CPU1 CPU2 CPU3 CPU4
IEnumerable records = GetRecords(); List results = new List (); foreach(Record record in records) { Result res = ProcessRecord(record); // non-trivial computation per record if (Filter(res)) results.Add(res); // check if result matches our criteria, if so add it into results } // can also be expressed as a simple LINQ statement List results = records.Select(rec => ProcessRecord(rec)).Where(res => Filter(res)).ToList();
IEnumerable records = GetRecords(); List results = new List (); int numWorkers = Environment.ProcessorCount; int activeWorkers = numWorkers; IEnumerator enumerator = records.GetEnumerator(); ManualResetEvent completionEvent = new ManualResetEvent(false); for(int i = 0; i < numWorkers; i++) { ThreadPool.QueueUserWorkItem(delegate { // launch P workers while(true) { Record currentRecord; lock (enumerator) { // grab a record under the lock before processing it if (!enumerator.MoveNext()) break; currentRecord = enumerator.Current; } Result res = ProcessRecord(currentRecord); // non-trivial computation per record if (Filter(res)) // check if result matches our criteria { lock(results) results.Add(res); // if so add it into results list under a lock } if (Interlocked.Decrement(ref activeWorkers) == 0) completionEvent.Set(); }); } completionEvent.WaitOne(); // wait until all workers are done
SAME CODE PARALLELIZED USING PLINQ
Visual Studio IDE.NET Framework 4 Parallel Debugger Concurrency Visualizer Thread Pool Task Scheduler Task Parallel Library Parallel LINQ Sync Primitives Concurrent Collections CLR
PARALLEL LOOPS src Thread 1 rec 1 rec 1 Thread P rec P+1 rec P+1 rec 2P+1 rec 2P+1 rec 2P rec 2P rec 3P rec 3P rec P Parallel.For(0, 100, i => DoWork(i)); Parallel.ForEach(src, rec => DoWork(rec)); Thread 1 i=0 Thread P Thread 2 i=C+1 i=C+2 i=C+3 i=1 i=2 i=P*C+1 i=P*C+2
// Breaking from a parallel loop Parallel.For(0, 1000, (i, state) => { if (SearchFunc(i)) state.Stop(); } // Controlling Degree Of Parallelism ParallelOptions po = new ParallelOptions() { MaxDegreeOfParallelism = 4 }; Parallel.ForEach(source, po, element => ProcessRecord(element) } // Using thread local state Dictionary counts = GetGlobalCounts(); Parallel.ForEach(enumSource, () => { //once per worker thread local init return new List (); }, (record, loopState, threadLocal) => { // actual loop body var result = ProcessRecord(record); if (result.InterestingFlag) threadLocal.Add(result); //cache results }, (threadLocal) => { //end of loop, once per worker combine delegate lock (counts) foreach (Result res in threadLocal) counts[res.GUID] += res.Count; });
PARALLEL LINQ
HOW PLINQ WORKS src Thread 1 where f(x) select y(x) Sum() Thread P where f(x) select y(x) Sum()
PARALLEL LINQ (cont’d)
Enqueue Global Queue (FIFO) Thread 1 Dispatch Loop Thread 2 Dispatch Loop Thread N Dispatch Loop Dequeue T2T2 T3T3 T1T1
Enqueue Global Queue (FIFO) Thread 1 Dispatch Loop Thread 1 Local Queue (LIFO) Thread 2 Dispatch Loop Thread 2 Local Queue (LIFO) Thread N Dispatch Loop Thread N Local Queue (LIFO) Dequeue Enqueue Steal T2T2 T3T3 T4 T4 T5T5 T6T6 T7T7 T8T8 T1T1
// Producer consumer pattern BlockingCollection bc = new BlockingCollection (); // Start the producer Task Task t1 = Task.Factory.StartNew(() => { while(!streamReader.EndOfStream) bc.Add(streamReader.ReadLine()); bc.CompleteAdding(); }); // Start the consumer Task Task t2 = Task.Factory.StartNew(() => { try { // Consume from the blocking collection while (true) Console.WriteLine(bc.Take()); } catch (InvalidOperationException) { // IOE thrown from Take() indicated completed collection Console.WriteLine("That's All!"); } });
Required Slide Track PMs will supply the content for this slide, which will be inserted during the final scrub.
Required Slide Track PMs will supply the content for this slide, which will be inserted during the final scrub.
Sign up for Tech·Ed 2011 and save $500 starting June 8 – June 31 st You can also register at the North America 2011 kiosk located at registration Join us in Atlanta next year