230 likes | 934 Views
.NET Parallel Programming in C#. Three approaches. There are three approaches you can run your tasks in parallel Task programming For control parallel Parallel Loops For data parallel Parallel LINQ For concurrency based on concurrent data access. Task programming—start tasks.
E N D
Three approaches • There are three approaches you can run your tasks in parallel • Task programming • For control parallel • Parallel Loops • For data parallel • Parallel LINQ • For concurrency based on concurrent data access
Task programming—start tasks task1.Start(); //Thread.Sleep(1000); task2.Start(); //Thread.Sleep(1000); task3.Start(); //Thread.Sleep(1000); task4.Start(); // wait for input before exiting Console.WriteLine("Main method complete. Press enter to finish."); Console.ReadLine(); } static void printMessage(inti) { //Thread.Sleep(1000); Console.WriteLine("Hello World, this is task" + i.ToString() + " with id = " + Task.CurrentId.ToString() + " at " + System.DateTime.Now.ToString()); } static void printMessage() { printMessage(1); } } } using System; using System.Threading.Tasks; using System.Threading; namespace Listing_02 { class Listing_02 { static void Main(string[] args) { // use an Action delegate and a named method Task task1 = new Task(new Action(printMessage)); // use a anonymous delegate Task task2 = new Task(delegate { printMessage(2); Console.WriteLine("This is task2"); }); // use a lambda expression and a named method Task task3 = new Task(() => printMessage(3)); // use a lambda expression and an anonymous method Task task4 = new Task(() => { printMessage(4); Console.WriteLine("This is task4"); });
Task programming— passing an object task1.Start(); task2.Start(); task3.Start(); task4.Start(); // wait for input before exiting Console.WriteLine("Main method complete. Press enter to finish."); Console.ReadLine(); } static void printMessage(object message) { Console.WriteLine("Message: {0}", message + " from task with id " + Task.CurrentId.ToString()); } } } using System; using System.Threading.Tasks; namespace Listing_03 { class Listing_03 { static void Main(string[] args) { // use an Action delegate and a named method Task task1 = new Task(new Action<object>(printMessage), "First task"); // use a anonymous delegate Task task2 = new Task(delegate(object obj) { printMessage(obj); }, "Second Task"); // use a lambda expression and a named method Task task3 = new Task((obj) => printMessage(obj), "Third task"); // use a lambda expression and an anonymous method Task task4 = new Task((obj) => { printMessage(obj); }, "Fourth task");
Task programming—passing an object (2) string[] messages = { "Task 1", "Task 2", "Task 3", "Task 4", "Task 5", "Task 6", "Task 7", "Task 8", "Task 9", "Task 10" }; foreach(string msg in messages) { Task myTask = new Task(obj => printMessage((string)obj), msg); myTask.Start(); }
Task programming—getting results // create the task using state Task<int> task2 = new Task<int>(obj => { int sum = 0; int max = (int)obj; for (int i = 0; i < max; i++) { sum += i; } return sum; }, 100); // start the task task2.Start(); // write out the result Console.WriteLine("Result 2: {0}", task2.Result); // wait for input before exiting Console.WriteLine("Main method complete. Press enter to finish."); Console.ReadLine(); } } } using System; using System.Threading.Tasks; namespace Listing_05 { class Listing_05 { static void Main(string[] args) { // create the task Task<int> task1 = new Task<int>(() => { int sum = 0; for (int i = 0; i < 100; i++) { sum += i; } return sum; }); // start the task task1.Start(); // write out the result Console.WriteLine("Result 1: {0}", task1.Result);
Task programming—getting results • It is like the return value of a method • Imaging using this approach to get the max of an array segment • How do we know all the tasks are done?
Task programming—waiting • Wait for one • Task.Wait(); // wait for completes, is canclled, or throws an exception • Task.Wait(CancellationToken); //cancelled or completes • Task.Wait(Int32); // wait for Int32 milliseconds or Wait() • Task.Wait(TimeSpan); //TimeSpan represent length of time • Task.Wait(Int32, CancellationToken) • Wait for any • wait for all • See list 6
Task programming—other activities • Cancel a task • Monitoring calculation • Waiting for time to pass • Handling exceptions • Getting task status • Task continuations • A way to coordinate tasks • Conclusions • Task programming can achieving concurrency • It supports control parallelism better • When you only have a few cores, this is a good tool
One more • System.Collections.Concurrent
Parallel Loops • There are two • Parallel.For, and • Parallel.ForEach (see an example 5-4) // create a collection of strings List<string> dataList = new List<string> { "the", "quick", "brown", "fox", "jumps", "etc" }; // process elements of the collection using a parallel foreach loop Parallel.ForEach(dataList, item => { Console.WriteLine("Item {0} has {1} characters", item, item.Length); });
ParallelLoopState Class • Enables iterations of Parallel loops to interact with other iterations. An instance of this class is provided by the Parallel class to each loop; you can not create instances in your user code.
ParallelLoopStateClass (2) • Two Key methods • You can get the result if you break/stop (5-9)
Using Thread Local Storage • Interlocked is a global level lock, the more cores you have the more expensive it becomes • Still, it is better than the lock object • Thread Local Storage is a better solution • Example 5 - 11 Parallel.For( 0, 100, () => 0, (int index, ParallelLoopStateloopState, inttlsValue) => { tlsValue += index; return tlsValue; }, value => Interlocked.Add(ref total, value));
Partitioning • This one answers how to divide works and associated data among tasks • The trick is to reduce synchronization overhead while keeping the workload balanced • Generally speak, there are two approaches • Static • Dynamic • PLINQ uses static • We will look into dynamic here
Partitioning (2) • Must use ForEach • You can create your own partitioning schema