【问题标题】:Number of threads decreases as Parallel.Foreach loop goes on随着 Parallel.Foreach 循环的继续,线程数减少
【发布时间】:2014-04-11 14:27:39
【问题描述】:

我有一个 Parallel Foreach 循环,它遍历一个项目列表,并对它们执行一些操作。其中一些操作比其他操作花费更长的时间,具体取决于项目。

Parallel.ForEach(list, new ParallelOptions { MaxDegreeOfParallelism = 5 }, item =>
{
    var subItems = item.subItems;
    foreach (var subItem in subItems)
    {
        //do some actions for subItem
    }

    Console.WriteLine("Action Complete for {0}", item);
});

一段时间后,当列表中只剩下大约 5-10 项要运行时,似乎只剩下 1 个线程在运行。这并不理想,因为有些项目会卡在另一个项目后面才能完成。

如果我停止脚本,然后重新启动它,列表中只有剩余的 5-10 个项目,它会启动多个线程以再次并行执行每个项目。

如何确保其他线程将继续使用,而无需我重新启动脚本?

【问题讨论】:

    标签: multithreading foreach parallel-processing


    【解决方案1】:

    这里的问题是默认分区器将每个任务的工作阻止到 N items 的块中。它假设项目的数量很大并且每个项目花费相同的时间,那么您会期望几个线程将运行最后〜 N * 5 个项目并且所有项目同时完成。

    但是,在您的情况下,情况并非如此。您可以编写自己的 Partitioner 以在每个块中使用较少数量的项目,请参阅 Partitioner Class。这可能会提高性能,但如果每个项目完成的工作非常小,那么您将增加有用工作与管理任务完成的工作的比率,并可能降低性能。

    您还可以编写一个动态分区程序来减小分区大小,以便最后几个项目位于较小的分区中,从而确保您仍在使用所有可用线程。这篇 MSDN 文章涵盖了编写自定义分区器,Custom Partitioners for PLINQ and TPL

    【讨论】:

    • 谢谢。很久以来我一直在寻找相同的信息。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-15
    • 2015-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-22
    相关资源
    最近更新 更多