Why can't I reach 100% CPU utilization with my parallel tasks code?

淺唱寂寞╮ 提交于 2020-06-01 04:10:03

问题


private static async Task<int> SumParallel()
        {
            var intList = Enumerable.Range(1, 1000_000_000);
            int count = intList.Count();
            int total = 0;
            for(int i = 1; i < 5; i++)
            {
                int skip = ((i - 1) * count) / 4;
                int take = count / 4;
                Interlocked.Add(ref total,
                    await GetSum(intList, skip, take));
            }
            return total;
        }

private static async Task<int> GetSum(IEnumerable<int> list, int skip, int take)
        {
            return await Task.Run(() =>
             {
                 int temp = 0;
                 foreach(int n in list.Skip(skip).Take(take))
                 {
                     if (n % 2 == 0)
                         temp -= n;
                     else
                         temp += n;
                 }
                 return temp;
             });
        }

I am trying to perform compute intensive task, just to practice the task parallel library. So, I wrote this code. If I try to compute the same sum using Parallel Linq, I can see the CPU utilization going to 100% as follows:

int sum = Enumerable.Range(1, 1000_000_000)
                .AsParallel()
                .Select(i => i % 2 == 0 ? -i : i).Sum();

Manual parallel tasks code = 10 seconds time, cpu = 25% only

Parallel Linq code = 18 seconds time, cpu = 100% (And still takes 18 seconds)

Linq code without parallel: 14 seconds, cpu = 25% only

Why is it so? When I am also starting 4 threads in parallel, why my cpu utilization doesn't go to 100%? It is just 25% like there is in unparallel code (with just one thread). Am I really running 4 threads in parallel or not?

My laptop is Core i3 - 2 cores = 4 logical processors


回答1:


The SumParallel is not doing parallel job, because it creates and awaits each task sequentially:

for(int i = 1; i < 5; i++) {
    //...
    await GetSum(intList, skip, take)

To make it parallel you must start all five tasks, and then await all of them to complete with await Task.WhenAll(tasks);.

As for the Parallel Linq being slower than the standard Linq, it is because your workload is too granular. As a result the overhead of parallelism negates any benefits of the parallel execution. In other words it is more work to distribute the items to the threads and collect the results back, than the actual calculation (n % 2). To make the most out of parallelism, your workload must be chunky.



来源:https://stackoverflow.com/questions/62099331/why-cant-i-reach-100-cpu-utilization-with-my-parallel-tasks-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!