Как ParallelEnumerable.Zip () предназначен для работы и почему поведение изменяется при вызове AsEnumerable ()? - PullRequest
0 голосов
/ 28 ноября 2018

Я пытаюсь понять поведение ParallelEnumerable.Zip() в сочетании с IEnumerable<T> и AsEnumerable().

С учетом приведенного ниже кода parallelResult и result не будут одинаковыми.Предполагая, что ParallelEnumerable.Zip() означает, что я просто хочу объединить элементы в случайном порядке, что имеет смысл.Но если я раскомментирую AsEnumerable(), parallelResult.ShouldBe(result) больше не выбрасывает, даже для очень больших n и повторных прогонов.Если оба входа List s, утверждение также проходит.

Какое поведение ожидается?Мы полагаемся на детали реализации при вызове AsEnumerable()?

int n = 200;
IReadOnlyList<double> list = Enumerable.Range(0, n).Select(x=>(double)x).ToList();
IEnumerable<double> enumerable = Enumerable.Range(10, n).Select(x => (double)x);

var result = list
    .Zip(enumerable, Tuple.Create)
    .OrderBy(x=>x.Item1)
    .ThenBy(x=>x.Item2)
    .ToList();

var parallelResult = list
    .AsParallel()
    .Zip(enumerable.AsParallel(), Tuple.Create)
    // .AsEnumerable()
    .OrderBy(x => x.Item1)
    .ThenBy(x => x.Item2)
    .ToList();

parallelResult.ShouldBe(result);

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

1 Ответ

0 голосов
/ 13 декабря 2018

Поскольку NetMage указывает, что в документации PLINQ о порядке указано, что Zip() входит в число операторов в группе " Следующие операторы запросов PLINQ могут в некоторых случаях требовать упорядоченных последовательностей исходного кода для получения правильныхрезультаты: ».

Следовательно, AsOrdered() необходимо использовать для гарантии того, что одни и те же элементы присутствуют в каждой паре, если код запускается несколько раз.Чтобы получить упорядоченный результат, приведенный выше пример должен выглядеть следующим образом:

int n = 200;
IReadOnlyList<double> list = Enumerable.Range(0, n).Select(x=>(double)x).ToList();
IEnumerable<double> enumerable = Enumerable.Range(10, n).Select(x => (double)x);

var result = list
    .Zip(enumerable, Tuple.Create)
    .OrderBy(x=>x.Item1)
    .ThenBy(x=>x.Item2)
    .ToList();

var parallelResult = list
    .AsParallel()
    .AsOrdered()
    .Zip(enumerable.AsParallel().AsOrdered(), Tuple.Create)
    .OrderBy(x => x.Item1)
    .ThenBy(x => x.Item2)
    .ToList();

parallelResult.ShouldBe(result);

Все остальные, казалось бы, повторяемые результаты - просто совпадение или из-за деталей реализации, которые могут измениться.

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