Заметка
Доступ к этой странице требует авторизации. Вы можете попробовать войти в систему или изменить каталог.
Доступ к этой странице требует авторизации. Вы можете попробовать сменить директорию.
В PLINQ цель — повысить производительность при сохранении правильности. Запрос должен выполняться как можно быстрее, но по-прежнему получать правильные результаты. В некоторых случаях правильность требует сохранения порядка исходной последовательности; однако порядок может быть дорогостоящим. Поэтому по умолчанию PLINQ не сохраняет порядок исходной последовательности. В этом отношении PLINQ напоминает LINQ to SQL, но в отличие от LINQ to Objects, который сохраняет порядок.
Чтобы переопределить поведение по умолчанию, можно включить сохранение порядка с помощью AsOrdered оператора в исходной последовательности. Затем вы можете отключить сохранение заказа позже в запросе AsUnordered с помощью метода. При использовании обоих методов запрос обрабатывается на основе эвристики, которая определяет, следует ли выполнять запрос как параллельный или последовательный. Дополнительные сведения см. "Понимание ускорения в PLINQ".
В следующем примере показан неупорядоченный параллельный запрос, который фильтрует все элементы, соответствующие условию, без попытки упорядочить результаты каким-либо образом.
var cityQuery =
(from city in cities.AsParallel()
where city.Population > 10000
select city).Take(1000);
Dim cityQuery = From city In cities.AsParallel()
Where city.Population > 10000
Take (1000)
Этот запрос не обязательно создает первые 1000 городов в исходной последовательности, которые соответствуют условию, а скорее некоторые из 1000 городов, которые соответствуют условию. Операторы запросов PLINQ разбивают исходную последовательность на несколько подпоследовательностей, которые обрабатываются как одновременные задачи. Если сохранение порядка не указано, результаты каждого раздела передаются на следующий этап запроса в произвольном порядке. Кроме того, раздел может предоставить подмножество своих результатов, прежде чем продолжить обработку оставшихся элементов. Результирующий порядок может отличаться каждый раз. Приложение не может контролировать это, так как оно зависит от того, как операционная система планирует потоки.
Следующий пример переопределяет поведение по умолчанию с помощью AsOrdered оператора в исходной последовательности. Это гарантирует, что Take метод возвращает первые 1000 городов в исходной последовательности, удовлетворяющей условию.
var orderedCities =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
Dim orderedCities = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Take (1000)
Однако этот запрос, вероятно, не выполняется так быстро, как неупорядоченная версия, так как ему необходимо отслеживать исходное упорядочение через разделы и во время слияния гарантировать согласованность упорядочения. Поэтому рекомендуется использовать AsOrdered только в тех случаях, когда это необходимо, и только для тех частей запроса, которые требуют его. Если сохранение порядка больше не требуется, используйте AsUnordered, чтобы его отключить. В следующем примере это достигается путем создания двух запросов.
var orderedCities2 =
(from city in cities.AsParallel().AsOrdered()
where city.Population > 10000
select city).Take(1000);
var finalResult =
from city in orderedCities2.AsUnordered()
join p in people.AsParallel()
on city.Name equals p.CityName into details
from c in details
select new
{
city.Name,
Pop = city.Population,
c.Mayor
};
foreach (var city in finalResult) { /*...*/ }
Dim orderedCities2 = From city In cities.AsParallel().AsOrdered()
Where city.Population > 10000
Select city
Take (1000)
Dim finalResult = From city In orderedCities2.AsUnordered()
Join p In people.AsParallel() On city.Name Equals p.CityName
Select New With {.Name = city.Name, .Pop = city.Population, .Mayor = city.Mayor}
For Each city In finalResult
Console.WriteLine(city.Name & ":" & city.Pop & ":" & city.Mayor)
Next
Обратите внимание, что PLINQ сохраняет порядок последовательности, созданной операторами, налагающими порядок, в оставшейся части запроса. Другими словами, операторы, такие как OrderBy и ThenBy рассматриваются, как если бы за ними последовал вызов AsOrdered.
Операторы запросов и упорядочивание
Следующие операторы запросов вводят сохранение порядка во все последующие операции в запросе или до вызова AsUnordered:
В некоторых случаях следующие операторы запросов PLINQ могут потребовать упорядоченные исходные последовательности, чтобы получить правильные результаты.
Некоторые операторы запросов PLINQ ведут себя по-разному в зависимости от того, упорядочена ли их исходная последовательность или неупорядочена. В следующей таблице перечислены эти операторы.
| Оператор | Результат при упорядочении исходной последовательности | Результат при отмене порядка исходной последовательности |
|---|---|---|
| Aggregate | Недетерминированные выходные данные для неассоциативных или некоммутативных операций | Недетерминированные выходные данные для неассоциативных или некоммутативных операций |
| All | Неприменимо | Неприменимо |
| Any | Неприменимо | Неприменимо |
| AsEnumerable | Неприменимо | Неприменимо |
| Average | Недетерминированные выходные данные для неассоциативных или некоммутативных операций | Недетерминированные выходные данные для неассоциативных или некоммутативных операций |
| Cast | Упорядоченные результаты | Неупорядоченные результаты |
| Concat | Упорядоченные результаты | Неупорядоченные результаты |
| Count | Неприменимо | Неприменимо |
| DefaultIfEmpty | Неприменимо | Неприменимо |
| Distinct | Упорядоченные результаты | Неупорядоченные результаты |
| ElementAt | Вернуть указанный элемент | Произвольный элемент |
| ElementAtOrDefault | Вернуть указанный элемент | Произвольный элемент |
| Except | Неупорядоченные результаты | Неупорядоченные результаты |
| First | Вернуть указанный элемент | Произвольный элемент |
| FirstOrDefault | Вернуть указанный элемент | Произвольный элемент |
| ForAll | Выполняется параллельно и недетерминированно | Выполняется параллельно и недетерминированно |
| GroupBy | Упорядоченные результаты | Неупорядоченные результаты |
| GroupJoin | Упорядоченные результаты | Неупорядоченные результаты |
| Intersect | Упорядоченные результаты | Неупорядоченные результаты |
| Join | Упорядоченные результаты | Неупорядоченные результаты |
| Last | Вернуть указанный элемент | Произвольный элемент |
| LastOrDefault | Вернуть указанный элемент | Произвольный элемент |
| LongCount | Неприменимо | Неприменимо |
| Min | Неприменимо | Неприменимо |
| OrderBy | Переупорядочение последовательности | Запускает новый упорядоченный раздел |
| OrderByDescending | Переупорядочение последовательности | Запускает новый упорядоченный раздел |
| Range | Неприменимо (то же, что и AsParallel по умолчанию) | Неприменимо |
| Repeat | Неприменимо (то же, что и AsParallelпо умолчанию) | Неприменимо |
| Reverse | Разворачивает | Ничего не делает |
| Select | Упорядоченные результаты | Неупорядоченные результаты |
| Select (индексировано) | Упорядоченные результаты | Неупорядоченные результаты. |
| SelectMany | Упорядоченные результаты. | Неупорядоченные результаты |
| SelectMany (индексировано) | Упорядоченные результаты. | Неупорядоченные результаты. |
| SequenceEqual | Упорядоченное сравнение | Неупорядоченное сравнение |
| Single | Неприменимо | Неприменимо |
| SingleOrDefault | Неприменимо | Неприменимо |
| Skip | Пропускает первые n-элементы | Пропускает любые элементы n |
| SkipWhile | Упорядоченные результаты. | Недетерминированным. Выполняет SkipWhile в текущем произвольном порядке |
| Sum | Недетерминированные выходные данные для неассоциативных или некоммутативных операций | Недетерминированные выходные данные для неассоциативных или некоммутативных операций |
| Take | Берет первые n элементы |
Принимает любые n элементы |
| TakeWhile | Упорядоченные результаты | Недетерминированным. Выполняет операцию TakeWhile в текущем произвольном порядке |
| ThenBy | Добавки OrderBy |
Добавки OrderBy |
| ThenByDescending | Добавки OrderBy |
Добавки OrderBy |
| ToArray | Упорядоченные результаты | Неупорядоченные результаты |
| ToDictionary | Неприменимо | Неприменимо |
| ToList | Упорядоченные результаты | Неупорядоченные результаты |
| ToLookup | Упорядоченные результаты | Неупорядоченные результаты |
| Union | Упорядоченные результаты | Неупорядоченные результаты |
| Where | Упорядоченные результаты | Неупорядоченные результаты |
| Where (индексировано) | Упорядоченные результаты | Неупорядоченные результаты |
| Zip | Упорядоченные результаты | Неупорядоченные результаты |
Неупорядоченные результаты не активно перетасовываются; Они просто не имеют специальной логики упорядочения, примененной к ним. В некоторых случаях неупорядоченный запрос может сохранить порядок исходной последовательности. Для запросов, использующих индексируемый оператор Select, PLINQ гарантирует, что выходные элементы будут выходить в порядке увеличения индексов, но не гарантирует, какие индексы будут назначены элементам.