Заказанное параллельное исполнение

У меня есть заказанный список, как [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], Я передаю это Parallel.ForEach заявление. Можно ли как-то добиться следующего порядка выполнения блоков, например: обработать первые 3 элемента [1, 2, 3] где заказ в ведре не является обязательным и может быть [2, 1, 3] например. Затем обработайте следующие 3 пункта [4, 5, 6], так далее?

2 ответа

Решение

Я не уверен, что вы можете сделать это напрямую. но я бы посоветовал вам разделить входной список на более мелкие списки, а затем вы можете обработать каждый подсписок с помощью Parallel.Foreach,

List<int> fruits = new List<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
List<List<int>> ls = new List<List<int>>();
for (int i = 0; i < fruits.Count; i += 3)
{
    ls.Add(fruits.GetRange(i, Math.Min(3, fruits.Count - i)));
}
foreach (List<int> group in ls)
{
    Parallel.ForEach(group, fruit =>
    {
    });
}

3 - длина небольшого списка.

Даже если принятый ответ полностью соответствует требованиям, в нем есть некоторые накладные расходы. Прежде всего, поскольку мы говорим о TPL, объем массивов данных, вероятно, велик, поэтому простое создание такого количества массивов занимает очень много памяти.
Кроме того, решение, предложенное @viveknuna, не гарантирует порядок для кусков. Если все в порядке, вы, вероятно, должны использовать ответ @DmitryBychenko с небольшим обновлением:

const int chunkSize = 3;
var array = Enumerable.Range(1, 9).ToArray();
// get the chunks for indexes for array sized in group of 3
var partitioner = Partitioner.Create(0, array.Length, chunkSize);

// use all the system resources
var parallelOptions = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };

// use the partitioner for a chunks, so outer parallel foreach
// will start a task for all the chunks, [1, 2, 3], [4, 5, 6], [7, 8, 9]
Parallel.ForEach(partitioner, parallelOptions, part =>
    {
        // inner foreach will handle part of the chunk in parallel
        Parallel.ForEach(array.Skip(part.Item1).Take(chunkSize), parallelOptions, value =>
            {
                // handle the array value in parallel
            });
    });

В данном коде, если вы установите для ParallelOptions.MaxDegreeOfParallelism к 1, вы получите желаемое упорядоченное параллельное выполнение, порция за куском.

Другие вопросы по тегам