为什么我的 Parallel.Foreach 似乎没有使用 10 个线程

本文关键字:线程 Parallel 我的 Foreach 为什么 | 更新日期: 2023-09-27 18:37:15

似乎

没有最小度的并行性。以下代码似乎只使用了 1% 的 CPU,所以我怀疑它没有正确使用内核:

Parallel.ForEach(lls, new ParallelOptions { MaxDegreeOfParallelism = 10 },  GetFileSizeFSO);

有没有办法使用 10 个内核/线程来强制?

附加信息:

private void GetFileSizeFSO(List<string> l)
{
    foreach (var dir in l)
    {
        var ds = GetDirectorySize3(dir);
        Interlocked.Add(ref _size, ds);
    }
}
    public static long GetDirectorySize3(string parentDirectory)
    {
        Scripting.FileSystemObject fso = new Scripting.FileSystemObject();
        Scripting.Folder folder = fso.GetFolder(parentDirectory);
        Int64 dirSize = (Int64)folder.Size;
        Marshal.ReleaseComObject(fso);

        return dirSize;
    }

为什么我的 Parallel.Foreach 似乎没有使用 10 个线程

你的函数GetFileSizeFSO做什么?如果它访问光盘上的文件,那一定是您的主要时间消费者。处理器太快了,光盘无法赶上处理器。因此,处理器有足够的时间空闲并等待HDD完成其工作。

如果您需要优化代码,您最好考虑更有效地访问文件,而不是尝试 100% 加载处理器。

被称为MaxDegreeOfParallelism,而不是MinDegreeOfParallelismParallel 专为 CPU 密集型工作而设计 - 使用比 CPU 更多的线程没有任何意义。听起来您的工作受 I/O 限制,而不是 CPU 限制,因此Parallel根本不是适合这项工作的工具。

理想情况下,找到一个异步 API 来执行您尝试执行的操作 - 这是使用您拥有的资源的最佳方式。如果没有异步 API,则必须自己生成这些线程 - 不过,不要指望看到 CPU 使用率。最重要的是,度量 - 并行化工作负载很可能根本不会提高吞吐量(例如,I/O 可能已经饱和)。

简单的答案是——你不能。

但是你为什么要这样做呢?.NET 非常擅长选择使用的最佳线程量。MaxDegreeOfParallelism的使用是为了限制并行性,而不是强制并行性,例如,如果您不想将所有系统资源提供给循环。

作为旁注,从您的函数名称GetFileSizeFSO ,我猜它从您的持久存储中读取文件大小,这可以解释为什么您的 CPU 没有被充分利用。

ManInMoon,您的CPU使用率可能很慢,因为您正在执行的工作可能受到存储机制的约束。 10 个内核撞击同一硬盘驱动器以获取文件大小可能不会比 2 个内核快,因为与周围的 C# 逻辑相比,对硬盘驱动器进行打击是一种相对(荒谬)昂贵的操作。

因此,您没有并行性问题,而是 I/O 问题。

旁注,也许不要使用 FSO,请使用 .NET的FileInfo代替。