为什么我的 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;
}
你的函数GetFileSizeFSO
做什么?如果它访问光盘上的文件,那一定是您的主要时间消费者。处理器太快了,光盘无法赶上处理器。因此,处理器有足够的时间空闲并等待HDD完成其工作。
如果您需要优化代码,您最好考虑更有效地访问文件,而不是尝试 100% 加载处理器。
被称为MaxDegreeOfParallelism
,而不是MinDegreeOfParallelism
。 Parallel
专为 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代替。