Parallelism in .NET – Part 4, Imperative Data Parallelism: Aggregation
In the article on simple data parallelism, I described how to perform an operation on an entire collection of elements in parallel. Often, this is not adequate, as the parallel operation is going to be performing some form of aggregation.
Simple examples of this might include taking the sum of the results of processing a function on each element in the collection, or finding the minimum of the collection given some criteria. This can be done using the techniques described in simple data parallelism, however, special care needs to be taken into account to synchronize the shared data appropriately. The Task Parallel Library has tools to assist in this synchronization.
Parallelism in .NET – Part 3, Imperative Data Parallelism: Early Termination
Although simple data parallelism allows us to easily parallelize many of our iteration statements, there are cases that it does not handle well. In my previous discussion, I focused on data parallelism with no shared state, and where every element is being processed exactly the same.
Unfortunately, there are many common cases where this does not happen. If we are dealing with a loop that requires early termination, extra care is required when parallelizing.
Parallelism in .NET – Part 2, Simple Imperative Data Parallelism
In my discussion of Decomposition of the problem space, I mentioned that Data Decomposition is often the simplest abstraction to use when trying to parallelize a routine. If a problem can be decomposed based off the data, we will often want to use what MSDN refers to as Data Parallelism as our strategy for implementing our routine. The Task Parallel Library in .NET 4 makes implementing Data Parallelism, for most cases, very simple.
Parallelism in .NET – Part 1, Decomposition
The first step in designing any parallelized system is Decomposition. Decomposition is nothing more than taking a problem space and breaking it into discrete parts. When we want to work in parallel, we need to have at least two separate things that we are trying to run. We do this by taking our problem and decomposing it into parts.
There are two common abstractions that are useful when discussing parallel decomposition: Data Decomposition and Task Decomposition. These two abstractions allow us to think about our problem in a way that helps leads us to correct decision making in terms of the algorithms we’ll use to parallelize our routine.
Parallelism in .NET – Introduction
Parallel programming is something that every professional developer should understand, but is rarely discussed or taught in detail in a formal manner. Software users are no longer content with applications that lock up the user interface regularly, or take large amounts of time to process data unnecessarily. Modern development requires the use of parallelism. There is no longer any excuses for us as developers.
Learning to write parallel software is challenging. It requires more than reading that one chapter on parallelism in our programming language book of choice…
Synchronizing .NET 4 Tasks with the UI Thread
While attending the Patterns of Parallel Programming Workshop at PDC, I picked up a very interesting tidbit from Stephen Toub’s talk: the new Task pattern in .NET 4 has built-in support for synchronization with the UI thread. This makes writing parallel applications that interact with the user interface easier than ever before.
Thread specific data becomes easier in .NET 4.0 via ThreadLocal<T>
Occasionally, when dealing with multithreaded code, there are uses for data that is kept in a manner that is unique to the currently running thread. This is accomplished via using Thread-local storage. Typically, in .NET 3.5, this was handled via the [ThreadStatic] attribute, however, this puts certain restrictions on usage. The main problem with ThreadStatic is that it is exactly that – static data stored per thread. This can be problematic, especially if you’re using ThreadPool threads, as the data is never released cleanly.
Currently, if you want to use data kept at a local scope with a copy per thread, the solution is to use a LocalDataStoreSlot to manage your threaded data. This works, but is not very developer-friendly. It is not type-safe; all data is stored as a System.Object. It is clunky at best to use, especially if you want to free, as you have to use and track strings with named data slots in order to release the memory. Version 4 of the .NET Framework fixes all of these issues by introducing ThreadLocal<T>.
Unusual uses of ExpandoObject in C# 4
One of the new features in C# 4 is the use of the dynamic keyword, allowing types to be defined with no regard to static type checking. Although many of the use cases for this revolve around interoperability, especially with dynamic languages and COM, there are types in the framework designed to make this available for use internally in C# programs as well. The simplest dynamic implementation in .NET 4 is System.Dynamic.ExpandoObject.
How Optional Arguments in C# 4 Actually Work
In my last post, I discussed one of my favorite new features in C# – Optional and Named Arguments. Although they are very easy to use, and quite intuitive, I have seen few discussions which explain how they actually work. Understanding how they are implemented helps in understanding the repercussions of using these features in development.
Optional and Named Arguments in C# 4
After focusing on some of the .NET framework enhancements, I thought I’d turn my attention to two of my most anticipated new features coming with C# 4 – Optional and Named Arguments. These two features provide benefits I haven’t seen mentioned in most of the announcements…