Let’s check today how to write a simple For loop using parallel programming. Basically the parallel programming takes advantage of the multi-processor computing and the .NET Framework 4.0 provides a set of tools to help you out developing multi-thread applications.
Method Overloads
The most basic Parallel For loop overload accepts a start index (inclusive), an end index (exclusive) and a delegate that is executed once per iteration.
- ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int, ParallelLoopState> body);
- ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body);
- ParallelLoopResult For(long fromInclusive, long toExclusive, Action<long, ParallelLoopState> body);
- ParallelLoopResult For(long fromInclusive, long toExclusive, Action<long> body);
- ParallelLoopResult For(int fromInclusive, int toExclusive, ParallelOptions parallelOptions, Action<int, ParallelLoopState> body);
- ParallelLoopResult For(int fromInclusive, int toExclusive, ParallelOptions parallelOptions, Action<int> body);
- ParallelLoopResult For(long fromInclusive, long toExclusive, ParallelOptions parallelOptions, Action<long, ParallelLoopState> body);
- ParallelLoopResult For(long fromInclusive, long toExclusive, ParallelOptions parallelOptions, Action<long> body);
Generic overloads
The generic overloads give you all the flexibility to perform Parallel For loops against several different types and control each the state for each thread execution:
- ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, Func<TLocal> localInit, Func<int, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);
- ParallelLoopResult For<TLocal>(long fromInclusive, long toExclusive, Func<TLocal> localInit, Func<long, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);
- ParallelLoopResult For<TLocal>(int fromInclusive, int toExclusive, ParallelOptions parallelOptions, Func<TLocal> localInit, Func<int, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);
- ParallelLoopResult For<TLocal>(long fromInclusive, long toExclusive, ParallelOptions parallelOptions, Func<TLocal> localInit, Func<long, ParallelLoopState, TLocal, TLocal> body, Action<TLocal> localFinally);
How to
Let’s create a simple Parallel For loop that performs a sum of all numbers existing from zero until the number passed as parameter:
public void ParallelCalculation(int maximum)
{
int subTotal = 0;
Parallel.For(0, sequenceSize, i =>
{
subTotal += i;
});
}
On the previous method we are passing three parameters to the Parallel For loop: the start and end indexes and a delegate that is executed once per iteration.
The following method is the same code implementation but with sequential programming.
public void SequentialCalculation(int maximum)
{
int subTotal = 0;
for (int i = 0; i < maximum; i++)
{
subTotal += i;
}
}
Performance
Let’s use both methods shown previously to make a really simple performance test by executing several times with different parameters. The time to perform the calculation changes from computer to computer when you have different numbers of processors. Running the application on a laptop with 2 processors the results were (in milliseconds):
Parameter Sequential Parallel
1,000 17ms 16ms
1,000,000 69ms 59ms
5,000,000 410ms 365ms
50,000,000 3142ms 2796ms
Let’s add a Console.WriteLine that writes the partial results of the calculation to the Console window to check how the execution time changes:
Parameter Sequential Parallel
1,000 643ms 519ms
10,000 2,821ms 1,727ms
100,000 21,164ms 13,799ms
1,000,000 239,585ms 129,016ms
Let’s check tomorrow how to work with Parallel For Each loops.
Stay tuned!