Udostępnij za pośrednictwem


Opcje scalania w PLINQ

Gdy zapytanie jest wykonywane jako równoległe, plINQ partycjonuje sekwencję źródłową, aby wiele wątków mogło działać na różnych częściach jednocześnie, zazwyczaj w osobnych wątkach. Jeśli wyniki mają być używane w jednym wątku, na przykład w pętli (For Each w foreach Visual Basic), wyniki z każdego wątku należy scalić z powrotem z jedną sekwencją. Rodzaj scalania wykonywanego przez PLINQ zależy od operatorów, które znajdują się w zapytaniu. Na przykład operatory, które nakładają nową kolejność na wyniki, muszą buforować wszystkie elementy ze wszystkich wątków. Z perspektywy wątku zużywania (który jest również użytkownikiem aplikacji) w pełni buforowane zapytanie może działać przez zauważalny okres czasu, zanim wygeneruje pierwszy wynik. Inne operatory domyślnie są częściowo buforowane; dają wyniki w partiach. Jeden operator ForAll nie jest domyślnie buforowany. Daje wszystkie elementy ze wszystkich wątków natychmiast.

Korzystając z WithMergeOptions metody , jak pokazano w poniższym przykładzie, można podać wskazówkę dla PLINQ, która wskazuje, jakiego rodzaju scalanie wykonać.

var scanLines = from n in nums.AsParallel()
                    .WithMergeOptions(ParallelMergeOptions.NotBuffered)
                where n % 2 == 0
                select ExpensiveFunc(n);
Dim scanlines = From n In nums.AsParallel().WithMergeOptions(ParallelMergeOptions.NotBuffered)
                Where n Mod 2 = 0
                Select ExpensiveFunc(n)

Pełny przykład można znaleźć w temacie How to: Specify Merge Options in PLINQ (Instrukcje: określanie opcji scalania w plINQ).

Jeśli określone zapytanie nie może obsługiwać żądanej opcji, opcja zostanie po prostu zignorowana. W większości przypadków nie trzeba określać opcji scalania dla zapytania PLINQ. Jednak w niektórych przypadkach można znaleźć przez testowanie i pomiar, że zapytanie wykonuje najlepiej w trybie nie domyślnym. Typowym zastosowaniem tej opcji jest wymuszenie przesyłania strumieniowego wyników operatora scalania fragmentów w celu zapewnienia bardziej dynamicznego interfejsu użytkownika.

ParallelMergeOptions

Wyliczenie ParallelMergeOptions zawiera następujące opcje, które określają, dla obsługiwanych kształtów zapytania, jak końcowe dane wyjściowe zapytania są zwracane, gdy wyniki są używane w jednym wątku:

  • Not Buffered

    Opcja NotBuffered powoduje, że każdy przetworzony element jest zwracany z każdego wątku zaraz po jego wygenerowaniu. To zachowanie jest analogiczne do "przesyłania strumieniowego" danych wyjściowych. AsOrdered Jeśli operator znajduje się w zapytaniu, NotBuffered zachowuje kolejność elementów źródłowych. Mimo że NotBuffered zaczyna przynosić wyniki natychmiast po ich udostępnieniu, łączny czas na wygenerowanie wszystkich wyników może być nadal dłuższy niż użycie jednej z pozostałych opcji scalania.

  • Auto Buffered

    Opcja AutoBuffered powoduje, że zapytanie zbiera elementy do buforu, a następnie okresowo zwraca zawartość buforu jednocześnie do wątku zużywanego. Jest to analogiczne do uzyskiwania danych źródłowych w "fragmentach" zamiast używania zachowania "przesyłania strumieniowego" elementu NotBuffered. AutoBuffered może potrwać dłużej niż NotBuffered udostępnienie pierwszego elementu w wątku zużywających. Rozmiar buforu i dokładne zachowanie wydajności nie są konfigurowalne i mogą się różnić w zależności od różnych czynników związanych z zapytaniem.

  • FullyBuffered

    Opcja FullyBuffered powoduje buforowanie danych wyjściowych całego zapytania przed uzyskaniem któregokolwiek z elementów. Jeśli używasz tej opcji, może upłynąć dłużej, zanim pierwszy element będzie dostępny w wątku zużywania, ale pełne wyniki mogą być nadal generowane szybciej niż przy użyciu innych opcji.

Operatory zapytań, które obsługują opcje scalania

W poniższej tabeli wymieniono operatory, które obsługują wszystkie tryby opcji scalania, z zastrzeżeniem określonych ograniczeń.

Operator Ograniczenia
AsEnumerable Brak
Cast Brak
Concat Nieskonsekcyjne zapytania, które mają tylko źródło tablicy lub listy.
DefaultIfEmpty Brak
OfType Brak
Reverse Nieskonsekcyjne zapytania, które mają tylko źródło tablicy lub listy.
Select Brak
SelectMany None
Skip None
Take None
Where Brak

Wszystkie inne operatory zapytań PLINQ mogą ignorować dostępne przez użytkownika opcje scalania. Niektóre operatory zapytań, na przykład Reverse i OrderBy, nie mogą zwracać żadnych elementów do momentu utworzenia i zmiany kolejności wszystkich elementów. W związku z tym, gdy ParallelMergeOptions jest używany w zapytaniu zawierającym również operator, taki jak Reverse, zachowanie scalania nie zostanie zastosowane w zapytaniu, dopóki ten operator nie wygenerował wyników.

Możliwość obsługi opcji scalania niektórych operatorów zależy od typu sekwencji źródłowej i tego, czy AsOrdered operator został użyty wcześniej w zapytaniu. ForAll jest zawsze NotBuffered ; daje swoje elementy natychmiast. OrderBy jest zawsze FullyBuffered; musi posortować całą listę, zanim zostanie ona wyświetlona.

Zobacz też