0

I am new to C# I am generating random numbers saving into an integer array of size 1 million, then I search user input number and its occurrences in an array using single thread then I search it using 5 threads. My processor has 4 cores. THE PROBLEM is multithreading is taking way more time than sequential I just cannot figure out why any help would be much appreciated. Here is the code.

namespace LAB_2
{
    class Program
    {
        static int[] arr = new int[1000000];
        static int counter = 0, c1 = 0, c2 = 0, c3 = 0, c4 = 0,c5=0;
        static int x = 0;

#if DEBUG
        static void Main(string[] args)
        {

            try
            {
                //Take input
                generate();
                Console.WriteLine("Enter number to search for its occurances");
                x = Console.Read();

                //Multithreaded search
                Stopwatch stopwatch2 = Stopwatch.StartNew();
                multithreaded_search();

                stopwatch2.Stop();
                Console.WriteLine("Multithreaded search");
                Console.WriteLine("Total milliseconds with multiple threads = " + stopwatch2.ElapsedMilliseconds);

                //search without multithreading
                Stopwatch stopwatch = Stopwatch.StartNew();
                search();
                stopwatch.Stop();
                Console.WriteLine("Total milliseconds without multiple threads = " + stopwatch.ElapsedMilliseconds);

            }
            finally
            {
                Console.WriteLine("Press enter to close...");
                Console.ReadLine();
            }
#endif

        }
        public static void generate() //Populate the array
        {
            Random rnd = new Random();

            for (int i = 0; i < 1000000; i++)
            {
                arr[i] = rnd.Next(1, 500000);
            }

        }
        public static void search() //single threaded/Normal searching
        {

            int counter = 0;

            for (int i = 0; i < 1000000; i++)
            {
                if (x == arr[i])
                {
                    counter++;
                }
            }
            Console.WriteLine("Number of occurances " + counter);
        }

        public static void multithreaded_search()
        {


            Task thr1 = Task.Factory.StartNew(() => doStuff(0, 200000, "c1"));
            Task thr2 = Task.Factory.StartNew(() => doStuff(200001, 400000, "c2"));
            Task thr3 = Task.Factory.StartNew(() => doStuff(400001, 600000, "c3"));
            Task thr4 = Task.Factory.StartNew(() => doStuff(600001, 800000, "c4"));
            Task thr5 = Task.Factory.StartNew(() => doStuff(800001, 1000000, "c5"));

 //IF I don't use WaitAll then the search is 
 //faster than sequential, but gets compromised
            Task.WaitAll(thr1, thr2, thr3, thr4, thr5);            
            counter = c1 + c2 + c3 + c4 + c5;
            Console.WriteLine("Multithreaded search");
            Console.WriteLine("Number of occurances " + counter);
        }
        static void doStuff(int stime, int etime, String c)
        {
            for (int i = stime; i < etime; i++)
            {
                if (x == arr[i])
                {
                    switch (c)
                    {
                        case "c1":
                            c1++;
                            break;
                        case "c2":
                            c2++;
                            break;
                        case "c3":
                            c3++;
                            break;
                        case "c4":
                            c4++;
                            break;
                        case "c5":
                            c5++;
                            break;
                    };
                }
                Thread.Yield();
            }
        }

    }

}
  • You should return from dostuff method once you found the number. – user1672994 Nov 02 '19 at 07:16
  • 1
    Why are you calling `Thread.Yield` inside the loop? – Theodor Zoulias Nov 02 '19 at 07:24
  • Also why have you rolled out a custom implementation of [`Parallel.For`](https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.parallel.for)? – Theodor Zoulias Nov 02 '19 at 07:29
  • After confirming that a Parallel.For is significantly slower than sequential processing in this use case, I wondered about it and a quick search found a question from 2012 which answers this one... – oerkelens Nov 02 '19 at 07:59
  • 1
    Possible duplicate of [Why was the parallel version slower than the sequential version in this example?](https://stackoverflow.com/questions/10418493/why-was-the-parallel-version-slower-than-the-sequential-version-in-this-example) – oerkelens Nov 02 '19 at 07:59
  • Multithreading is meant to spread load over several cores. It takes a little overhead. When there is no load only the overhead remains. – TaW Nov 02 '19 at 08:19
  • Check this fiddle --- [https://dotnetfiddle.net/rNEKVk](https://dotnetfiddle.net/rNEKVk). If you remove the `Thread.Yield` then multi threaded program runs faster. – user1672994 Nov 02 '19 at 10:03

1 Answers1

0

First, in your doStuff you do more work than in search. While it is not likely to have a tangible effect, you never know.

Second, Thread.Yield is a killer with tasks. This methods is intended to be used in very marginal situations like spinning when you think a lock might be too expensive. Here, it is just a brake to your code, causing the OS scheduler to do more work, perhaps even do a context-switch on the current core, which in turn will invalidate the cache.

Finally, your data and computations are small. Moderns CPUs will enumerate such an array in no time, and it is likely a great part of it, or even all, fits in the cache. Concurrent processing has its overhead.

I recommend Benchmark.NET.

Nick
  • 4,787
  • 2
  • 18
  • 24
  • Thanks, Nick. Thread.yield has significantly lowered the time. It's still more than sequential threading I guess because of so many function calls. Again thanks a ton – syed sabeeh ahmed fatmi Nov 02 '19 at 17:57