Failure to execute all of the steps in the Parallel class

Reza Jaferi 331 Reputation points
2022-09-04T16:49:54.207+00:00

Hi guys,
Since I'm concerned about speed and efficiency, I began reading Gastón C. Hillar's Professional Parallel Programming with C# book and want to rewrite my project from the ground up using the parallel programming approach.
In the following exercise, I noticed that not all steps of the parallel loop are executed while comparing the execution speed of the sequential and parallel loops.
I noticed this by analyzing the text length.
In the sequential loop, the length is always 200,000, but in the parallel loop it is variable.

Sequential loop

            System.Diagnostics.Stopwatch StopWatch = new System.Diagnostics.Stopwatch();  
            StringBuilder SB = new StringBuilder();  
            Console.ReadKey();  
            StopWatch.Start();  
            for (int i = 0; i < 200000; i++)  
            {  
                SB.Append("B");  
            }  
            StopWatch.Stop();  
            Console.WriteLine("Total seconds: " + StopWatch.Elapsed.TotalSeconds + ", Length: " + SB.Length);  
            Console.ReadKey();  

Result:
237634-sequential-loop.png

Parallel.For

            System.Diagnostics.Stopwatch StopWatch = new System.Diagnostics.Stopwatch();  
            StringBuilder SB = new StringBuilder();  
            Console.ReadKey();  
            StopWatch.Start();  
            Parallel.For(0, 200000, range =>  
            {  
                SB.Append("B");  
            });  
            StopWatch.Stop();  
            Console.WriteLine("Total seconds: " + StopWatch.Elapsed.TotalSeconds + ", Length: " + SB.Length);  
            Console.ReadKey();  

One of the results:
237603-parallelfor.png

Parallel.ForEach

            System.Diagnostics.Stopwatch StopWatch = new System.Diagnostics.Stopwatch();  
            StringBuilder SB = new StringBuilder();  
            Console.ReadKey();  
            StopWatch.Start();  
            Parallel.ForEach(Partitioner.Create(0, 200000, ((200000 / Environment.ProcessorCount) + 1)), range =>  
            {  
                for (int i = range.Item1; i < range.Item2; i++)  
                {  
                    SB.Append("B");  
                }  
            });  
            StopWatch.Stop();  
            Console.WriteLine("Total seconds: " + StopWatch.Elapsed.TotalSeconds + ", Length: " + SB.Length);  
            Console.ReadKey();  

One of the results:
237673-parallelforeach.png

  1. What is the reason for this, and how can I know if the entire parallel loop has been implemented in the projects? Please explain with an example.
  2. Also, what exactly is the concept of overhead?

I use the following tools:

  • .NET Framework 4.5
  • Console app

Thank you for your time.
Best regards

Windows Forms
Windows Forms
A set of .NET Framework managed libraries for developing graphical user interfaces.
1,838 questions
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,681 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,309 questions
{count} votes

Accepted answer
  1. Bruce (SqlWork.com) 56,931 Reputation points
    2022-09-04T17:33:18.033+00:00

    First a StringBuilder is not thread safe, you need to take a lock before accessing. Second the Append method is not too cpu intensive, so the overheard of creating and managing threads is greater. And once you add proper locking, only 1 thread at a time will do the append, so you are just adding needless overheard.

    Now if there was a lot of cpu involved in generating what to append, this example might make sense.

    Update:

    List is not thread safe and requires a lock. there are thread safe collections.

    the following code would work:

                 System.Diagnostics.Stopwatch StopWatch = new System.Diagnostics.Stopwatch();  
                 var List = new ConcurrentBag<object>();  
                 Console.ReadKey();  
                 StopWatch.Start();  
                 Parallel.For(0, 200000, range =>  
                 {  
                     List.Add("A");  
                 });  
                 StopWatch.Stop();  
                 Console.WriteLine("Total seconds: " + StopWatch.Elapsed.TotalSeconds + ", Length: " + List.Count);  
                 Console.ReadKey();  
    

    but this code will be slower due to the locking and thread magement than a non parallel version. again this is because the parallel cpu work is trivial.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful