Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi threaded task not utilizing CPU?

Tags:

c#

.net

I have a method in C# that I want to run from multiple threads for lets say 20 times in a console app, on a 4 core machine. The problem I am facing is that the results are not what I expect them to be. When I run the method 25 times sequentially, the time taken is X and I can see in perfmon that max CPU is 100% (it tells me that it is using 1 core). Running the same method using multiple threads, I expect the execution time to be X/4 and also I expect the max CPU usage in perfmon to be 400% (since it is a 4 core machine). However, I can only see that the execution time is X/2 and the max CPU usage has never been more than 275%. I have tried various things such as creating my own threads, using threasdpool etc. and nothing seems to work. Can somebody please explain/help me understand it better?

Other interesting thing is that if I replace my method with a dummy task using Thread.SpinWait(x) the execution time is X/4 and I can see max CPU going to 400%. This tells me that something is wrong in my method and I don't understand what it is. I have no locks/sleep anywhere in my method. Following is the code I use to execute:

public static void DoWorkParallel()
{
    var s = new List<string> { "a", "b", "c", "d", "e", etc. };
    s.ParallelForEach2(x =>
                       {
                           MyTask(x);
                       });
}

public static void DoWorkSequential()
{
    var s = new List<string> { "a", "b", "c", "d", "e", etc. };
    foreach (var ss in s)
    {
        MyTask(x);
    }       
}

public static void ParallelForEach<T>(this IEnumerable<T> collection, Action<T> action)
{
    var results = collection.Skip(1).Select(item => new 
    {
        action,
        res = action.BeginInvoke(item, null, null)
    }).ToArray();

    action(collection.First()); /* let the mainthread do a job too*/

    foreach (var r in results)
    {
        r.action.EndInvoke(r.res); /*then wait the rest of time */
    }
}
like image 347
Kumar Avatar asked Jul 04 '11 10:07

Kumar


People also ask

Does multithreading reduce CPU utilization?

Although you can take advantage of multithreading to perform several tasks simultaneously and increase the application's throughput, it should be used judiciously. Incorrect usage of multithreading may result in high CPU usages or increased CPU cycles and can drastically reduce your application's performance.

Does multithreading improve CPU utilization?

The ultimate goal of multithreading is to increase the computing speed of a computer and thus also its performance. To this end, we try to optimize CPU usage. Rather than sticking with a process for a long time, even when it's waiting on data for example, the system quickly changes to the next task.

How do I force a program to use multiple cores?

Core Settings In Windows 10Type 'msconfig' into the Windows Search Box and hit Enter. Select the Boot tab and then Advanced options. Check the box next to Number of processors and select the number of cores you want to use (probably 1, if you are having compatibility issues) from the menu. Select OK and then Apply.

Can a CPU run multiple threads simultaneously?

Each core contains a complete CPU capable of executing a thread. Many modern processors support hyperthreading: each physical core behaves as if it is actually two cores, so it can run two threads simultaneously (e.g. execute one thread while the other is waiting on a cache miss).


1 Answers

Thread.SpinWait is running in a tight loop, performing no I/O and accessing no memory -- it's doing no useful work, so comparing its CPU usage to that of your task is a fallacy.

Without details of what your task is doing (whether it accesses files, waits on mutexes, etc.), it's difficult to determine what's going on.

One thing you can do is to add a Stopwatch instance to your task, and use it to print the time elapsed for each invocation. Compare the results of running tasks with DoWorkSequential and ParallelForEach -- each invocation should take the same amount of time regardless of the method. If the tasks run by ParallelForEach are taking longer, it could indicate you have, say, a mutex that is in contention and needs to be replaced with another locking method.

like image 137
Blair Holloway Avatar answered Sep 28 '22 05:09

Blair Holloway