Parallel Programming in C# 4.0

 

History has seen various programming models.

  • Single Threaded Programming – Involves single execution context
  • Multi threaded Programming – Involves multiple execution contexts
  • Concurrent/Parallel Programming – Involves multiple simultaneous computations happening across multiple processors
  • Synchronous Programming – A thread executes one task at a time until it completes
  • Asynchronous Programming – A thread initiates a task, saves the state, continues with another task, and returns back to the original task once the task is complete. Hence tasks are interleaved to each other

C# 4.0 introduced Task Parallel Library to support Parallel Programming.

Many computers have multiple cores of CPU. Code can be parallelized to run across multiple processors.

.NET Parallel Programming Architecture

Task Parallel Library

  • Set of APIs in System.Threading and System.Threading.Tasks.
  • Simplifies the process of adding parallelism to applications.
  • Scales the degree of concurrency dynamically to efficiently use all available processors
  • Handles partitioning of work, scheduling of threads in threadpool, cancellation, state management
  • Starting .Net 4, TPL is the way to write multithreaded and parallel code.

Data Parallelism

  • Same operation executed in parallel on elements of a collection.
  • By partitioning the collection, multiple threads can operate on different segments of the collection
  • Available in System.Threading.Tasks.Parallel class provides parallel implementation of for and foreach loops
  • TPL handles the low level work by creating multiple threads behind the scenes when executing Parallel.for and Parallel.foreach

// Sequential version
foreach (var item in sourceCollection)
{
Process(item);
}

//Parallel version

Parallel.ForEach(sourceCollection, item => Process(item));

Parallel LINQ

  • Parallel Implementation of LINQ to objects
  • Uses up to 64 processors
  • PLINQ query can be written using AsParallel extension method
var source = Enumerable.Range(1, 10000);

var evenNums = from num in source.AsParallel()
               where num % 2 == 0
               select num;
  • Maximum number of processors can be specified using “WithDegreeOfParallelism”
  • The below LINQ query specifies the maximum processors as 2
var query = from item in source.AsParallel().WithDegreeOfParallelism(2)
            where Compute(item) > 42
            select item;
  • Unlike sequential LINQ queries, PLINQ can be cancelled using WithCancellation operator on query and use CancellationToken instance as argument
CancellationTokenSource cts = new CancellationTokenSource();
int[] source = Enumerable.Range(1, 10000000).ToArray();
results = (from num in source.AsParallel().WithCancellation(cts.Token)
                           where num % 3 == 0
                           orderby num descending
                           select num).ToArray();

Reference