GetPartitions получил перекос разделов? - PullRequest
0 голосов
/ 06 июня 2018

Запуск следующего кода в интерактивном окне C #

using System.Collections.Concurrent;

var l = Enumerable.Range(0, 20);

Partitioner.Create(l).GetPartitions(4)
  .Select(x => { 
    var s = ""; 
    while (x.MoveNext()) { s += x.Current.ToString() + ","; }; 
    return s; 
  })

возвращает

Enumerable.WhereSelectArrayIterator<IEnumerator<int>, string>
  { "0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,", "", "", "" }

Кажется, один раздел получил все значения?Я пробовал это с большим размером Enumerable.Range(0, 12000), и все элементы все еще идут в первом разделе.


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

public static Task ForEachAsync<T>(this IEnumerable<T> source, int dop, Func<T, Task> body)
{
    return Task.WhenAll(
        from partition in Partitioner.Create(source).GetPartitions(dop)
        select Task.Run(async delegate {
            using (partition)
                while (partition.MoveNext())
                    await body(partition.Current);
        }));
}

1 Ответ

0 голосов
/ 06 июня 2018

Я скажу, что причиной этого является ваш код: вы перечисляете только один раздел, но разделы «заполняются» по запросу.

Вам нужен простой тест?

Partitioner.Create(l).GetPartitions(4)
  .Skip(1)
  .Select(x => { 
    var s = ""; 
    while (x.MoveNext()) { s += x.Current.ToString() + ","; }; 
    return s; 
  })

Теперь это еще один раздел, который получает все значения :-) Но не был ли первый раздел, который получил все значения?Теперь это второй: -)

Более правильный тест будет:

var l = Enumerable.Range(0, 20);

var parts = Partitioner.Create(l).GetPartitions(4);

string[] bufs = new string[parts.Count];

while (true)
{
    int countFinished = 0;
    for (int i = 0; i < parts.Count; i++)
    {
        if (parts[i].MoveNext())
        {
            bufs[i] += parts[i].Current + ",";
        }
        else
        {
            countFinished++;
        }
    }
    if (countFinished == parts.Count)
    {
        break;
    }
}

for (int i = 0; i < parts.Count; i++)
{
    Console.WriteLine(bufs[i]);
}

Я перечисляю четыре раздела одновременно.Это распределит все числа поровну между разделами.

...