多线程程序不使用 100% CPU 用于昂贵的 IEnumerables

Multithreaded program NOT using 100% CPU for expensive IEnumerables

使用 IEnumerables 的多线程,并行计算多次并且计算成本高,不使用 100% CPU.示例是 Aggregate() 函数结合 Concat():

// Initialisation.
// Each IEnumerable<string> is made so that it takes time to evaluate it
// everytime when it is accessed.
IEnumerable<string>[] iEnumerablesArray = ...  

// The line of the question (using less than 100% CPU):
Parallel.For(0, 1000000, _ => iEnumerablesArray.Aggregate(Enumerable.Concat).ToList());

问题:为什么并行计算 IEnumerables 多次的并行代码不使用 100% CPU?代码不使用锁或等待,所以这种行为是意外。 post.

末尾有完整的模拟代码

注释和编辑:

完整代码:

class Program
{
    const int DATA_SIZE = 10000;
    const int IENUMERABLE_COUNT = 10000;

    static void Main(string[] args)
    {
        // initialisation - takes milliseconds
        IEnumerable<string>[] iEnumerablesArray = GenerateArrayOfIEnumerables();

        Console.WriteLine("Initialized");

        List<string> result = null;

        // =================
        // THE PROBLEM LINE:
        // =================
        // CPU usage of next line:
        //    - 40 % on 4 virtual cores processor (2 physical)
        //    - 10 - 15 % on 12 virtual cores processor
        Parallel.For(
            0, 
            int.MaxValue, 
            (i) => result = iEnumerablesArray.Aggregate(Enumerable.Concat).ToList());

        // just to be sure that Release mode would not omit some lines:
        Console.WriteLine(result);
    }

    static IEnumerable<string>[] GenerateArrayOfIEnumerables()
    {
        return Enumerable
              .Range(0, IENUMERABLE_COUNT)
              .Select(_ => Enumerable.Range(0, 1).Select(__ => GenerateLongString()))
              .ToArray();
    }

    static string GenerateLongString()
    {
        return string.Concat(Enumerable.Range(0, DATA_SIZE).Select(_ => "string_part"));
    }
}

您的线程在 clr.dll!WKS::gc_heap::wait_for_gc_done 上被阻塞的事实表明垃圾收集器是您应用程序的瓶颈。您应该尽可能地限制程序中堆分配的数量,以减轻 gc 的压力。

也就是说,还有另一种加快速度的方法。默认情况下,在桌面上,GC 配置为使用计算机上的有限资源(以避免减慢其他应用程序的速度)。如果你想充分利用可用的资源,那么你可以activate server GC。此模式假定您的应用程序是计算机上最重要的 运行。它将提供显着的性能提升,但使用更多 CPU 和内存。