首页 文章

在Parallel.Foreach中分块IEnumerable

提问于
浏览
19

有没有人知道让Parallel.Foreach循环使用块分区的方法,我认为默认情况下是范围分区 . 使用数组时似乎很简单,因为您只需创建自定义分区程序并将负载均衡设置为true即可 .

由于IEnumerable中的元素数量直到运行时才知道,因此我似乎无法找到使块分区工作的好方法 .

任何帮助,将不胜感激 .

谢谢!

我试图在每个对象上执行的任务执行的时间明显不同 . 最后,我通常会等待最后一个线程完成其工作的时间 . 我想要实现的是在整个过程中使用并行循环请求块而不是为每个线程预分配项 .

2 回答

  • 2

    如果您的IEnumerable真的是一个有索引器的东西(即你可以做 obj[1] 来取出一个项目)你可以做以下事情

    var rangePartitioner = Partitioner.Create(0, source.Length);
        Parallel.ForEach(rangePartitioner, (range, loopState) =>
        {
            // Loop over each range element without a delegate invocation. 
            for (int i = range.Item1; i < range.Item2; i++)
            {
                var item = source[i]
                //Do work on item
            }
        });
    

    但是,如果它不能这样做,您必须通过创建一个派生自 System.Collections.Concurrent.Partitioner<TSource> 的新类来编写自定义分区程序 . 该主题过于宽泛,无法涵盖在SO答案中,但您可以查看this guide on the MSDN以帮助您入门 .

    UPDATE: 从.NET 4.5开始,他们添加了一个不缓冲数据的Partitioner.Create重载,它与制作一个范围最大为1的自定义分区具有相同的效果 . 这样你就不会得到一个有一堆的单个线程如果一连串的慢速项目运气不好,就排队等候工作 .

    var partitoner = Partitioner.Create(source, EnumerablePartitionerOptions.NoBuffering);
    Parallel.ForEach(partitoner, item =>
    {
        //Do work
    }
    
  • 20

    MSDN Samples for Parallel Programming with the .NET Framework包含 ChunkPartitioner 的实现 . 它包含在 ParallelExtensionsExtra 项目中 .

相关问题