指定默认的 MaxDegreeOfParallelism 会导致并行循环更快 运行

Specifing default MaxDegreeOfParallelism cause the parallel loop to run faster

我正在使用 System.Threading.Tasks.Parallel.ForEach()。 出于某种原因,将 MaxDegreeOfParallelism 设置为“-1”甚至“50”,会导致循环 运行 更快(大约 15 秒并且是一致的)。 MaxDegreeOfParallelism 参数的默认值为 -1,将其设置为 50 或任何其他数字只会使其变慢。 可能是什么原因?

System.Collections.Concurrent.ConcurrentBag<FileDataInfo> filesData = new System.Collections.Concurrent.ConcurrentBag<FileDataInfo>();
        System.Threading.Tasks.Parallel.ForEach(filesInfo, 
            new System.Threading.Tasks.ParallelOptions() { MaxDegreeOfParallelism = -1 },
            info =>
        {
            if (!string.IsNullOrEmpty(info.FolderPath))
                info.FolderPath = System.IO.Path.Combine(dataPathDirName, info.FolderPath);
            else
                info.FolderPath = dataPathDirName;

            var storageHandler = FileStorageFactory.CreateStorageHander();
            byte[] data = storageHandler.GetFileData(info.FilePath);
            filesData.Add(new FileDataInfo() { Info = info, Data = data });
        });

MaxDegreeOfParallelism 告诉 TPL 有多少东西可以同时 运行ning。这会在很多方面影响执行速度。通过将此值设置为较低的值,它允许任务 运行 自己 CPU/Core。这使事情 运行 更快,因为您获得了良好的并行性。如果您将此值设置得更高(或设置为 -1),那么您可以 运行 执行比 CPUs/Cores 更多的任务。当发生这种情况时,跨任务共享 CPU 所需的时间可能会花费大量时间并使操作看起来更慢。

一般经验法则:不要将并行度设置为高于系统中 cores/CPUs 的数量。

你的问题不是 CPU-bound,而是 I/O 的问题。现代驱动器可以利用 I/O 的大队列来更有效地执行它。通过使用 Parallel.ForEach,您将填满此队列并使驱动器以最高效率运行。

虽然您可能注意到此处速度有所提高,但值得注意的是您正在创建大量线程来完成此操作。过多的线程几乎从来都不是一个好主意,因为它由于调度程序开销和缓存流失而变得非常低效。如果可能,我建议转换代码以使用异步和 TPL 数据流。这将使您可以使用单个线程来管理大量并行 I/O 请求。