Разделение коллекции на равные партии в параллели с помощью c # - PullRequest
0 голосов
/ 16 января 2019

Я пытаюсь разделить коллекцию на равное количество партий. Ниже приведен код.

   public static List<List<T>> SplitIntoBatches<T>(List<T> collection, int size)
    {
        var chunks = new List<List<T>>();
        var count = 0;
        var temp = new List<T>();

        foreach (var element in collection)
        {
            if (count++ == size)
            {
                chunks.Add(temp);
                temp = new List<T>();
                count = 1;
            }
            temp.Add(element);
        }

        chunks.Add(temp);

        return chunks;
    }

Можем ли мы сделать это, используя Parallel.ForEach() для повышения производительности, так как в списке около 1 миллиона элементов?

Спасибо!

1 Ответ

0 голосов
/ 16 января 2019

Если речь идет о производительности, мои мысли (в порядке возрастания воздействия):

  • Правильный размер списков при их создании спасет лот работы,т.е. выяснить размеры выходного пакета до , когда вы начнете копировать, т.е. temp = new List<T>(thisChunkSize)
  • работа с массивами будет более эффективной, чем работа со списками - new T[thisChunkSize]
  • особенноесли вы используете BlockCopy (или CopyTo, который использует это для внутреннего использования), а не копируете отдельные элементы один за другим
  • , как только вы рассчитали смещения для каждого из блоков, отдельные блок-копии могутвероятно, будет выполняться параллельно, но я бы не предполагал, что это будет быстрее - пропускная способность памяти будет ограничивающим фактором на этом этапе
  • , но исправление ultimate : don '• скопировать данные вообще , но вместо этого просто создать диапазонов поверх существующих данных;например, если использовать массивы, ArraySegment<T> поможет;если вы открыты для использования более новых функций .NET, это идеально подходит для Memory<T> / Span<T> - создание диапазонов памяти / диапазона на основе существующего массива является по сути бесплатным и мгновенным - т.е. принимает T[] и возвращает List<Memory<T>> или аналогичный.

Даже если вы не можете переключиться на ArraySegment<T> / Memory<T> и т. Д., Возвращая что-то , например , которое все еще можно использовать - то есть List<ListSegment<T>>где ListSegment<T> выглядит примерно так:

readonly struct ListSegment<T> { // like ArraySegment<T>, but for List<T>
    public List<T> List {get;}
    public int Offset {get;}
    public int Count {get;}
}

и ваш код работает с ListSegment<T>, обрабатывая Offset и Count соответствующим образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...