Parallel For Method in C#

Parallel For Method in C# with Examples

In this article, I am going to discuss the static Parallel For method in C# with some examples. Please read our previous article before proceeding to this article where we discussed the basics of Parallel Programming in C#. As part of this article, we will discuss the need and use of Parallel For loop comparing with the C# for loop. So, let’s start the discussion with one of the most frequently asked interview questions.

What is the difference between the Parallel For loop and standard C# for loop?

The main difference between the Parallel For loop and the standard C# for loop are as follows

  1. In case of the standard C# for loop, the loop is going to run using a single thread whereas, in the case of Parallel For loop, the loop is going to execute using multiple threads.
  2. The second difference is that, in the case of the standard C# for loop, the loop is iterated in sequential order whereas, in the case of Parallel For loop, the order of the iteration is not going to be in sequential order.

Note1: When the iterations are independent of each other, means, subsequent iterations do not read the state updates made by previous iterations, then on such cases, we need to use Task Parallel Library (TPL) to run each iteration in parallel on all the available cores.

Note2: Moreover, the iteration should be an expensive iteration otherwise we will get negative performance, that we will also discuss as part of this article.

Syntax:

Parallel For Method in C#

Let us see an example for a better understanding of the above two types of for loop in C#:
using System;
using System.Threading;
using System.Threading.Tasks;

namespace ParallelProgrammingDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("C# For Loop");
            int number = 10;
            for (int count = 0; count < number; count++)
            {
                //Thread.CurrentThread.ManagedThreadId returns an integer that 
                //represents a unique identifier for the current managed thread.
                Console.WriteLine($"value of count = {count}, thread = {Thread.CurrentThread.ManagedThreadId}");
                //Sleep the loop for 10 miliseconds
                Thread.Sleep(10);
            }
            Console.WriteLine();

            Console.WriteLine("Parallel For Loop");
            Parallel.For(0, number, count =>
            {
                Console.WriteLine($"value of count = {count}, thread = {Thread.CurrentThread.ManagedThreadId}");
                //Sleep the loop for 10 miliseconds
                Thread.Sleep(10);
            });
            Console.ReadLine();
        }
    }
}

As you can see in the above example, the static “For” method of the static “Parallel” class is defined as public static ParallelLoopResult For(int fromInclusive, int toExclusive, Action<int> body);. Here the first parameter (i.e. int fromInclusive) is the start index. The second parameter (i.e. int toExclusive) is the end index and the third parameter (i.e. Action<int> body) is the delegate which is invoked once per iteration. You can find many overloaded versions of this method in the Parallel class.

Once you run the above code, you will get the following output.

C# Standard Forl oop vs Parallel For Loop

As you can see in the above output, the standard C# for loop iterates sequentially using a single thread as a result, the results are printed sequentially. On the other hand, you can see with the Parallel for loop the results are not printed in sequential order. This is because it uses multiple threads to iterate over the collection. You can see that there are in our example it uses five threads to execute the code. It may vary in your system.

Let’s consider another example for the better understanding from a performance point of view.

First, we will write the example using C# for loop and will see how much time it will take to complete the execution. Then we will write the same example using Parallel For method and will see how much time it will take to complete the execution.

In the below example, we create a sequential loop. The loop iterates ten times, and the loop control variable increasing from zero to nine. In each iteration, the DoSomeIndependentTask method is called. The DoSomeIndependentTask method performs a calculation that is included to generate a long enough pause to see the performance improvement of the parallel version.

namespace ParallelProgrammingDemo
{
    class Program
    {
        static void Main()
        {
            DateTime StartDateTime = DateTime.Now;

            Console.WriteLine(@"For Loop Execution start at : {0}", StartDateTime);
            for (int i = 0; i < 10; i++)
            {
                long total = DoSomeIndependentTask();
                Console.WriteLine("{0} - {1}", i, total);
            }
            DateTime EndDateTime = DateTime.Now;
            Console.WriteLine(@"For Loop Execution end at : {0}", EndDateTime);

            TimeSpan span = EndDateTime - StartDateTime;
            int ms = (int)span.TotalMilliseconds;
            Console.WriteLine(@"Time Taken to Execute the For Loop in miliseconds {0}", ms);

            Console.WriteLine("Press any key to exist");
            Console.ReadLine();
        }

        static long DoSomeIndependentTask()
        {
            //Do Some Time Consuming Task here
            //Most Probably some calculation or DB related activity
            long total = 0;
            for (int i = 1; i < 100000000; i++)
            {
                total += i;
            }
            return total;
        }
    }
}

OUTPUT:

Parallel For method in C#

As you can see from the above output screen the for loop statement took approximately 3635 milliseconds to complete the execution.

Let’s rewrite the same example using the Parallel For method.

namespace ParallelProgrammingDemo
{
    class Program
    {
        static void Main()
        {
            DateTime StartDateTime = DateTime.Now;

            Console.WriteLine(@"Parallel For Loop Execution start at : {0}", StartDateTime);

            Parallel.For(0, 10, i => {
                long total = DoSomeIndependentTask();
                Console.WriteLine("{0} - {1}", i, total);
            });

            DateTime EndDateTime = DateTime.Now;
            Console.WriteLine(@"Parallel For Loop Execution end at : {0}", EndDateTime);

            TimeSpan span = EndDateTime - StartDateTime;
            int ms = (int)span.TotalMilliseconds;
            Console.WriteLine(@"Time Taken to Execute the Loop in miliseconds {0}", ms);

            Console.WriteLine("Press any key to exist");
            Console.ReadLine();
        }

        static long DoSomeIndependentTask()
        {
            //Do Some Time Consuming Task here
            //Most Probably some calculation or DB related activity
            long total = 0;
            for (int i = 1; i < 100000000; i++)
            {
                total += i;
            }
            return total;
        }
    }
}

OUTPUT:

Parallel For method in C#

As shown in the above output image, the Parallel For method took 2357 milliseconds to complete the execution.

ParallelOptions class

The ParallelOptions class is one of the most useful class when working with multithreading. This class provides options to limit the number of concurrently executing loop methods. 

The Degree of parallelism:

Using the Degree of parallelism we can specify the maximum number of threads to be used to execute the program. Following is the syntax to use ParallelOptions class with Degree of parallelism.

ParallelOptions class with Degree of Parallelism in C#

The MaxDegreeOfParallelism property affects the number of concurrent operations run by Parallel method calls that are passed this ParallelOptions instance. A positive property value limits the number of concurrent operations to the set value. If it is -1, there is no limit on the number of concurrently running operations.

Let us see an example for better an understanding of the MaxDegreeOfParallelism.

namespace ParallelProgrammingDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Limiting the maximum degree of parallelism to 2
            var options = new ParallelOptions()
            {
                MaxDegreeOfParallelism = 2
            };

            int n = 10;
            Parallel.For(0, n, options, i =>
            {
                Console.WriteLine(@"value of i = {0}, thread = {1}",
                i, Thread.CurrentThread.ManagedThreadId);

                Thread.Sleep(10);
            });

            Console.WriteLine("Press any key to exist");
            Console.ReadLine();
        }
    }
}

OUTPUT:

Parallel For method in C#

As we set the degree of parallelism to 2. So, a maximum of 2 threads is used to execute the code that we can see from the above output.

Terminating a Parallel Loop:

The below example shows how to break out of a For loop and also how to stop a loop. In this context, “break” means complete all iterations on all threads that are prior to the current iteration on the current thread, and then exit the loop. “Stop” means to stop all iterations as soon as convenient.

namespace ParallelProgrammingDemo
{
    class Program
    {
        static void Main()
        {
            var BreakSource = Enumerable.Range(0, 1000).ToList();
            int BreakData = 0;
            Console.WriteLine("Using loopstate Break Method");
            Parallel.For(0, BreakSource.Count, (i, BreakLoopState) =>
            {
                BreakData += i;
                if (BreakData > 100)
                {
                    BreakLoopState.Break();
                    Console.WriteLine("Break called iteration {0}. data = {1} ", i, BreakData);
                }
            });
            Console.WriteLine("Break called data = {0} ", BreakData);

            var StopSource = Enumerable.Range(0, 1000).ToList();
            int StopData = 0;
            Console.WriteLine("Using loopstate Stop Method");
            Parallel.For(0, StopSource.Count, (i, StopLoopState) =>
            {
                StopData += i;
                if (StopData > 100)
                {
                    StopLoopState.Stop();
                    Console.WriteLine("Stop called iteration {0}. data = {1} ", i, StopData);
                }
            });

            Console.WriteLine("Stop called data = {0} ", StopData);
            Console.ReadKey();
        }
    }
}

In a Parallel.For or Parallel.ForEach loop, you cannot use the same break or Exit statement that is used in a sequential loop because those language constructs are valid for loops, and a parallel “loop” is actually a method, not a loop. Instead, you use either the Stop or Break method.

In the next article, I am going to discuss the Parallel ForEach Method in C# with some examples. Here, In this article, I try to explain the Parallel For method in C# with some examples. I hope you understood the need and use of Parallel For method in C#.

Leave a Reply

Your email address will not be published. Required fields are marked *