/* From: Parallel Programming with Microsoft® .NET Design Patterns for Decomposition and Coordination on Multicore Architectures By Colin Campbell, Ralph Johnson, Ade Miller, Stephen Toub Publisher: Microsoft Press Released: August 2010 On-line: http://msdn.microsoft.com/en-us/library/ff963547.aspx Chapter on Parallel aggregation This example extends the basic ForEach loop with a way to combine all results to an overall result. */ using System; using System.Threading.Tasks; // using Parallel; using System.Collections.Generic; class ParallelLoops { private static int Fib(int n) { if (n==0) { return 1; } else if (n==1) { return 1; } else { int n1 = Fib(n-1); int n2 = Fib(n-2); return n1+n2; } } private static void mkSequence(List seq, int m, int n) { if (m>n) { return; } else { seq.Add(m); mkSequence(seq, m+1, n); return; } } private int SomeComputation(int i) { return Fib(i); } private delegate void WorkerDelegate(); private static void TimeIt(WorkerDelegate worker) { DateTime startTime = DateTime.Now; DateTime stopTime = DateTime.Now; worker(); TimeSpan duration = stopTime - startTime; Console.WriteLine("Elapsed time: {0}", duration.ToString()); } public static void Main(string []args) { if (args.Length != 3) { // expect 1 arg: value to double System.Console.WriteLine("Usage: "); System.Console.WriteLine("k ... number of cores to use"); System.Console.WriteLine("m, n ... the range of values to apply Fib to; a good range isP: 39 43"); } else { int k = Convert.ToInt32(args[0]); int m = Convert.ToInt32(args[1]); int n = Convert.ToInt32(args[2]); int sum = 0; object lockObject = new { }; // any non-null object will do as lock // int[] fibs = new int[n]; // generates a range from input values; slightly artificial List seq = new List(); mkSequence(seq, m, n); /* Parallel version, using only 2 tasks */ System.Console.WriteLine("Running Parallel Foreach, with aggregation, over {0} .. {1} on {2} cores", m, n, k); var options = new ParallelOptions() { MaxDegreeOfParallelism = k}; TimeIt(() => { Parallel.ForEach(// The values to be aggregated seq, // specify degree of parallelism options, // The local initial partial result () => 0, // The loop body (x, loopState, partialResult) => { return Fib(x) + partialResult; }, // The final step of each local context (localPartialSum) => { // Enforce serial access to single, shared result lock (lockObject) { sum += localPartialSum; } }); }); Console.WriteLine("Sum of Fib({0}) .. Fib({1}) = {2}", m, n, sum); } } }