Równoległe kontenerów i obiektów
Biblioteka desenie równoległe (PPL) obejmuje kilka kontenerów i obiektów, wielowątkowość dostępu do ich elementów.
A równoczesne kontenera zapewnia współbieżność bezpieczny dostęp do najważniejszych operacji.Funkcje tych pojemników podobne do tych, które są dostarczane przez standardowe biblioteki szablonu (STL).Na przykład concurrency::concurrent_vector podobny do klasy std::vector klasy, z wyjątkiem concurrent_vector klasy umożliwia dołączanie elementów jednocześnie.Przy jednoczesnych kontenerów równoległych kod, który wymaga zarówno odczytu i zapisu do tego samego pojemnika.
A równoczesnych obiektu współużytkowany równocześnie składników.Proces, który oblicza stan równoczesnych obiektu równolegle daje taki sam wynik jak inny proces, który oblicza seryjnie tym samym stanie.Concurrency::combinable klasy jest przykładem tego typu obiektu równoczesnych.combinable Klasy umożliwia wykonywanie obliczeń równolegle, a następnie połączenie tych obliczeń w wyniku końcowego.Przy jednoczesnych obiektów do synchronizowania dostępu do udostępnionych zmiennej lub zasobu w przeciwnym razie korzystałyby mechanizm synchronizacji, na przykład mutex.
Sekcje
W tym temacie opisano następujące pojemniki równoległych i obiekty szczegółowo.
Równoczesne kontenery:
Klasa concurrent_vector
Różnice między concurrent_vector i wektorowe
Operacje bezpiecznego współbieżności
Wyjątek bezpieczeństwa
Klasa concurrent_queue
Różnice między concurrent_queue i kolejki
Operacje bezpiecznego współbieżności
Obsługa iteratora
Klasa concurrent_unordered_map
Różnice między concurrent_unordered_map i unordered_map
Operacje bezpiecznego współbieżności
Klasa concurrent_unordered_multimap
Klasa concurrent_unordered_set
Klasa concurrent_unordered_multiset
Równoczesne obiektów:
Klasa łączonymi
Metody i funkcje
Przykłady
Klasa concurrent_vector
Concurrency::concurrent_vector klasa jest klasą sekwencji kontenera, który, podobnie jak std::vector klasy, umożliwia dostęp losowo jego elementów.concurrent_vector Klasy pozwala dołączyć współbieżności bezpieczny i element dostęp.Dołącz operacji nie unieważnia istniejące wskaźniki lub Iteratory.Operacje dostępu i przechodzenie iteratora są również bezpieczne współbieżności.
Różnice między concurrent_vector i wektorowe
concurrent_vector Przypominającym klasę vector klasy.Złożoność dołączającej, dostęp do elementu i iteratora operacje dostępu na concurrent_vector obiektu są takie same, jak w przypadku vector obiektu.Punkty ilustrują where concurrent_vector różni się od vector:
Dołącz dostępu do elementu, iteratora dostępu i iteratora przechodzenia operacji na concurrent_vector obiektu są bezpieczne współbieżności.
Elementy można dodać tylko do końca concurrent_vector obiektu.concurrent_vector Klasy nie dostarcza insert metody.
A concurrent_vector obiektu nie korzysta z przenieść semantykę podczas dołączania do niego.
concurrent_vector Klasy nie dostarcza erase lub pop_back metody.Tak jak w vector, użyj Wyczyść metodę, aby usunąć wszystkie elementy z concurrent_vector obiektu.
concurrent_vector Klasy nie przechowuje jego elementy ciągły obszar w pamięci.Dlatego nie można używać concurrent_vector klasy wszystkie sposoby używania tablicy.Na przykład dla zmiennej o nazwie v typu concurrent_vector, wyrażenie &v[0]+2 powoduje zachowanie niezdefiniowany.
concurrent_vector w klasie grow_by i grow_to_at_least metody.Metody te przypominają zmienić rozmiar metodę, z wyjątkiem, że są one bezpieczne współbieżności.
A concurrent_vector podczas dołączania do niego lub zmienić jego rozmiar, obiekt nie przenieść jego elementów.Umożliwia to istniejące wskaźniki i Iteratory pozostaje ważne podczas operacji jednoczesnych.
Środowiska wykonawczego nie definiuje wersji wyspecjalizowanych concurrent_vector dla typu bool.
Operacje bezpiecznego współbieżności
Wszystkie metody, które są dołączone do lub zwiększyć rozmiar concurrent_vector obiektu lub dostępu do elementu w concurrent_vector obiektów, są bezpieczne współbieżności.Wyjątkiem od tej reguły jest resize metody.
W poniższej tabeli przedstawiono wspólnej concurrent_vector metody i podmioty gospodarcze, które są bezpieczne współbieżności.
Operacje, które środowisko wykonawcze zapewnia zgodność z STL, na przykład, reserve, nie są bezpieczne współbieżności.W poniższej tabeli przedstawiono wspólnych metod i podmioty gospodarcze, które nie są bezpieczne współbieżności.
Operacje, które należy zmodyfikować wartość istniejące elementy nie są bezpieczne współbieżności.Użyj obiektu synchronizacji, takich jak reader_writer_lock obiekt, aby zsynchronizować odczytu jednoczesnych operacji zapisu i do tego samego elementu danych.Aby uzyskać więcej informacji na temat obiektów synchronizacji zobacz Synchronizacja struktury danych.
Podczas konwertowania istniejącego kodu vector , aby użyć concurrent_vector, równoczesne operacje powodują zachowanie aplikacji, aby zmienić.Na przykład, rozważmy następujący program, który jednocześnie wykonuje dwa zadania na concurrent_vector obiektu.Pierwsze zadanie dołącza dodatkowych elementów do concurrent_vector obiektu.Drugie zadanie oblicza sumę wszystkich elementów w tym samym obiekcie.
// parallel-vector-sum.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_vector.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
// Create a concurrent_vector object that contains a few
// initial elements.
concurrent_vector<int> v;
v.push_back(2);
v.push_back(3);
v.push_back(4);
// Perform two tasks in parallel.
// The first task appends additional elements to the concurrent_vector object.
// The second task computes the sum of all elements in the same object.
parallel_invoke(
[&v] {
for(int i = 0; i < 10000; ++i)
{
v.push_back(i);
}
},
[&v] {
combinable<int> sums;
for(auto i = begin(v); i != end(v); ++i)
{
sums.local() += *i;
}
wcout << L"sum = " << sums.combine(plus<int>()) << endl;
}
);
}
Chociaż end metoda jest bezpieczny współbieżności równoczesne wywołanie push_back metoda powoduje, że wartość zwracaną przez end do zmiany.Liczba elementów, które przechodzi iteratora jest nieokreślony.W związku z tym ten program może spowodować różne wyniki przy każdym uruchomieniu go.
Wyjątek bezpieczeństwa
Jeśli operacja wzrostu lub przypisania zgłasza wyjątek stanu concurrent_vector obiekt staje się nieprawidłowy.Zachowanie concurrent_vector obiekt, który jest w nieprawidłowym stanie jest niezdefiniowana, chyba że stwierdzono inaczej.Jednakże destruktor zawsze zwalnia pamięci przydzielanej przez obiekt, nawet jeśli obiekt jest w nieprawidłowym stanie.
Typ danych elementów wektorów _Ty, muszą spełniać następujące wymagania.W przeciwnym razie zachowanie concurrent_vector klasy jest niezdefiniowane.
Nie musisz throw destruktor.
Jeśli generuje konstruktora domyślnego lub Kopiuj, destruktor nie muszą być zadeklarowane za pomocą virtual słowa kluczowego i jego musi działać poprawnie z pamięcią zainicjowany przez zero.
Top
Klasa concurrent_queue
Concurrency::concurrent_queue klasy, podobnie jak std::queue klasy, umożliwia dostęp do jego przednich i z powrotem elementy.concurrent_queue Klasy kolejkowania wywołań zwrotnych umożliwia bezpieczne współbieżności i usuwania z kolejki operacji.concurrent_queue Klasy udostępnia również obsługę iteratora, który nie jest bezpieczny współbieżności.
Różnice między concurrent_queue i kolejki
concurrent_queue Przypominającym klasę queue klasy.Punkty ilustrują where concurrent_queue różni się od queue:
Kolejkowania wywołań zwrotnych i usuwania z kolejki operacji na concurrent_queue obiektu są bezpieczne współbieżności.
concurrent_queue Klasy zapewnia obsługę iteratora, który nie jest bezpieczny współbieżności.
concurrent_queue Klasy nie dostarcza front lub pop metody.concurrent_queue Klasy zastępuje te metody, definiując try_pop metody.
concurrent_queue Klasy nie dostarcza back metody.Dlatego nie można odwoływać się koniec kolejki.
concurrent_queue Klasy unsafe_size metoda zamiast size metody.unsafe_size Metoda nie jest bezpieczny współbieżności.
Operacje bezpiecznego współbieżności
Wszystkie metody tego kolejkowania wywołań zwrotnych do lub usuwania z kolejki z concurrent_queue obiektu są bezpieczne współbieżności.
W poniższej tabeli przedstawiono wspólnej concurrent_queue metody i podmioty gospodarcze, które są bezpieczne współbieżności.
Chociaż empty metody bezpiecznego współbieżności, równoczesnych operacji może spowodować kolejki jest powiększany lub zmniejszany przed empty metoda zwraca.
W poniższej tabeli przedstawiono wspólnych metod i podmioty gospodarcze, które nie są bezpieczne współbieżności.
Obsługa iteratora
concurrent_queue Zapewnia Iteratory, które nie są bezpieczne współbieżności.Zaleca się, aby użyć tych Iteratory tylko debugowanie.
A concurrent_queue iteratora przechodzi elementów w kierunku do przodu tylko.W poniższej tabeli przedstawiono operatory, że obsługuje każdego iteratora.
Operator |
Opis |
---|---|
Zaliczki na następny element w kolejce.Ten operator jest przeciążony zapewnienie semantykę zarówno pre-increment, jak i postinkrementacja. |
|
Pobiera odwołanie do bieżącego elementu. |
|
Pobiera wskaźnik do bieżącego elementu. |
Top
Klasa concurrent_unordered_map
Concurrency::concurrent_unordered_map klasa jest klasą asocjacyjną kontenera, który, podobnie jak std::unordered_map klasy, kontroluje sekwencji długość różnych elementów typu std::pair < klucz const, Ty >.Nieuporządkowana mapy można traktować jako słownik, który można dodać parę kluczy i wartości do lub wyszukiwanie wartości przez klucz.Ta klasa jest przydatne, gdy kilka wątków lub zadania, które mają jednocześnie dostęp do udostępnionych kontenera, go wstawić lub zaktualizować go.
Poniższy przykład pokazuje podstawową strukturę za pomocą concurrent_unordered_map.W tym przykładzie wstawia klawiszy znaków z zakresu ["," "i"].Kolejność operacji jest nieokreślony, dlatego końcowej dla każdego klucza również jest nieokreślony.Jednakże jest bezpiecznie wykonywać wstawienia równolegle.
// unordered-map-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_map.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
//
// Insert a number of items into the map in parallel.
concurrent_unordered_map<char, int> map;
parallel_for(0, 1000, [&map](int i) {
char key = 'a' + (i%9); // Geneate a key in the range [a,i].
int value = i; // Set the value to i.
map.insert(make_pair(key, value));
});
// Print the elements in the map.
for_each(begin(map), end(map), [](const pair<char, int>& pr) {
wcout << L"[" << pr.first << L", " << pr.second << L"] ";
});
}
/* Sample output:
[e, 751] [i, 755] [a, 756] [c, 758] [g, 753] [f, 752] [b, 757] [d, 750] [h, 754]
*/
Na przykład, że korzysta z concurrent_unordered_map do wykonywania mapy i zmniejszyć operacji równolegle, zobacz Jak: wykonywanie mapę i zmniejszyć operacji równolegle.
Różnice między concurrent_unordered_map i unordered_map
concurrent_unordered_map Przypominającym klasę unordered_map klasy.Punkty ilustrują where concurrent_unordered_map różni się od unordered_map:
The erase, bucket, bucket_count, and bucket_size methods are named unsafe_erase, unsafe_bucket, unsafe_bucket_count, and unsafe_bucket_size, respectively.unsafe_ Konwencji nazewnictwa wskazuje, że metody te nie są bezpieczne współbieżności.Aby uzyskać więcej informacji na temat bezpieczeństwa współbieżności zobacz Safe współbieżności operacji.
Operacje nie unieważnia istniejące wskaźniki lub Iteratory nie należy zmieniać kolejność elementów, które już istnieją w mapie.Wstawianie i przechodzenia operacji może być wykonywane równocześnie.
concurrent_unordered_mapobsługuje przesyła tylko iteracji.
Wstawiania nie unieważnia lub zaktualizować Iteratory, które są zwracane przez equal_range.Wstawiania można dołączyć nierówne elementy, na końcu zakresu.Punkty iteratora do elementu równego.
W celu uniknięcia zakleszczenia, nie metody concurrent_unordered_map posiada blokadę, gdy wywołuje program przydzielania pamięci, funkcje mieszania lub inny kod zdefiniowany przez użytkownika.Również należy się upewnić, że funkcja mieszania zawsze oblicza klucze równej do tej samej wartości.Najważniejsze funkcje mieszania rozpowszechniania kluczy jednolicie całej przestrzeni mieszania kodu.
Operacje bezpiecznego współbieżności
concurrent_unordered_map Klasy umożliwia bezpieczne współbieżności Wstaw i element dostępu operacji.Operacje nie unieważnia istniejące wskaźniki lub Iteratory.Operacje dostępu i przechodzenie iteratora są również bezpieczne współbieżności.W poniższej tabeli przedstawiono powszechnie używanych concurrent_unordered_map metody i podmioty gospodarcze, które są bezpieczne współbieżności.
count |
find |
||
begin |
empty |
get_allocator |
max_size |
cbegin |
end |
hash_function |
|
cend |
equal_range |
size |
Chociaż count metoda może być bezpiecznie wywoływana jednocześnie uruchamianie wątków, różne wątki mogą odbierać różne wyniki, jeśli jednocześnie dodaje się nową wartość do pojemnika.
W poniższej tabeli przedstawiono najczęściej używanych metod i podmioty gospodarcze, które nie są bezpieczne współbieżności.
clear |
max_load_factor |
rehash |
load_factor |
Oprócz tych metod, każda metoda który zaczyna się od unsafe_ również nie jest bezpieczny współbieżności.
Top
Klasa concurrent_unordered_multimap
Concurrency::concurrent_unordered_multimap przypominającym klasę concurrent_unordered_map klasy, z wyjątkiem, że pozwala ona na wiele wartości mapować do tego samego klucza.Również różni się od concurrent_unordered_map w następujący sposób:
Concurrent_unordered_multimap::insert metoda zwraca iterację zamiast std::pair<iterator, bool>.
concurrent_unordered_multimap Klasy nie dostarcza operator[] ani at metody.
Poniższy przykład pokazuje podstawową strukturę za pomocą concurrent_unordered_multimap.W tym przykładzie wstawia klawiszy znaków z zakresu ["," "i"].concurrent_unordered_multimapWłącza klucz wieloma wartościami.
// unordered-multimap-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_map.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
//
// Insert a number of items into the map in parallel.
concurrent_unordered_multimap<char, int> map;
parallel_for(0, 10, [&map](int i) {
char key = 'a' + (i%9); // Geneate a key in the range [a,i].
int value = i; // Set the value to i.
map.insert(make_pair(key, value));
});
// Print the elements in the map.
for_each(begin(map), end(map), [](const pair<char, int>& pr) {
wcout << L"[" << pr.first << L", " << pr.second << L"] ";
});
}
/* Sample output:
[e, 4] [i, 8] [a, 9] [a, 0] [c, 2] [g, 6] [f, 5] [b, 1] [d, 3] [h, 7]
*/
Top
Klasa concurrent_unordered_set
Concurrency::concurrent_unordered_set przypominającym klasę concurrent_unordered_map klasy, chyba że zarządza wartości zamiast par kluczy i wartości.concurrent_unordered_set Klasy nie dostarcza operator[] ani at metody.
Poniższy przykład pokazuje podstawową strukturę za pomocą concurrent_unordered_set.W tym przykładzie wstawia znak wartości z zakresu ["," "i"].Bezpiecznie wykonywać wstawienia równolegle.
// unordered-set-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_set.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
//
// Insert a number of items into the set in parallel.
concurrent_unordered_set<char> set;
parallel_for(0, 10000, [&set](int i) {
set.insert('a' + (i%9)); // Geneate a value in the range [a,i].
});
// Print the elements in the set.
for_each(begin(set), end(set), [](char c) {
wcout << L"[" << c << L"] ";
});
}
/* Sample output:
[e] [i] [a] [c] [g] [f] [b] [d] [h]
*/
Top
Klasa concurrent_unordered_multiset
Concurrency::concurrent_unordered_multiset przypominającym klasę concurrent_unordered_set klasy, z wyjątkiem, że pozwala ona na zduplikowane wartości.Również różni się od concurrent_unordered_set w następujący sposób:
Concurrent_unordered_multiset::insert metoda zwraca iterację zamiast std::pair<iterator, bool>.
concurrent_unordered_multiset Klasy nie dostarcza operator[] ani at metody.
Poniższy przykład pokazuje podstawową strukturę za pomocą concurrent_unordered_multiset.W tym przykładzie wstawia znak wartości z zakresu ["," "i"].concurrent_unordered_multisetUmożliwia wartość występuje wiele razy.
// unordered-set-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_set.h>
#include <iostream>
using namespace concurrency;
using namespace std;
int wmain()
{
//
// Insert a number of items into the set in parallel.
concurrent_unordered_multiset<char> set;
parallel_for(0, 40, [&set](int i) {
set.insert('a' + (i%9)); // Geneate a value in the range [a,i].
});
// Print the elements in the set.
for_each(begin(set), end(set), [](char c) {
wcout << L"[" << c << L"] ";
});
}
/* Sample output:
[e] [e] [e] [e] [i] [i] [i] [i] [a] [a] [a] [a] [a] [c] [c] [c] [c] [c] [g] [g]
[g] [g] [f] [f] [f] [f] [b] [b] [b] [b] [b] [d] [d] [d] [d] [d] [h] [h] [h] [h]
*/
Top
Klasa łączonymi
Concurrency::combinable klasy zapewnia przechowywanie wielokrotnego użytku, lokalnej wątku, który pozwala wykonywać obliczenia szczegółowymi, a następnie scalić tych obliczeniach wyniku końcowego.Można traktować combinable obiektu jako zmienna redukcji.
combinable Klasy jest przydatne, gdy dany zasób współużytkowany kilka wątków lub zadań.combinable Klasy pomaga wyeliminować stan udostępnionego przez zapewnienie dostępu do zasobów udostępnionych w sposób wolny blokady.W związku z tym Klasa ta stanowi alternatywę dla za pomocą mechanizmu synchronizacji, na przykład mutex do synchronizowania dostępu do udostępnionych danych z wielu wątków.
Metody i funkcje
W poniższej tabeli przedstawiono niektóre z ważnych metod combinable klasy.Aby uzyskać więcej informacji o wszystkich combinable metody klasy, zobacz Klasa łączonymi.
Metoda |
Opis |
---|---|
Pobiera odwołanie do zmiennej lokalnej, skojarzony z bieżącym kontekstem wątku. |
|
Usuwa wszystkie zmienne lokalne dla wątku z combinable obiektu. |
|
Funkcja Łączenie dostarczonego do generowania wartości końcowej z zestawu obejmującego wszystkie obliczenia lokalnej wątku. |
combinable Klasa jest klasą szablonu, która jest parametryzowana na ostateczny wynik scalone.Jeśli wywołanie konstruktora domyślnego _Ty typ parametru szablonu musi mieć konstruktora domyślnego i konstruktora kopii.Jeśli _Ty typ parametru szablonu nie ma domyślnego konstruktora, wywołaj przeciążony wersję konstruktora, który ma funkcję inicjalizacji jako parametr.
Można przechowywać dodatkowe dane w combinable obiektu po wywołaniu połączyć lub combine_each metody.Można również wywołać combine i combine_each metody wiele razy.Jeśli nie lokalne wartość w combinable obiektu zmian, combine i combine_each metody produkcji tego samego rezultatu każdym razem, gdy są one nazywane.
Przykłady
Do przykładów na temat używania combinable klasy, zobacz następujące tematy:
Top
Tematy pokrewne
Jak: zwiększenie wydajności za pomocą równoległych kontenerów
Przedstawiono sposób użycia pojemników równolegle efektywne przechowywanie i uzyskać dostęp do danych równolegle.Jak: Użyj łączonymi do poprawy wydajności
Pokazuje, jak użyć combinable klasa do wyeliminowania stan udostępnionego, a tym samym zwiększyć wydajność.Jak: Użyj łączonymi połączyć zestawy
Pokazuje, jak użyć combine funkcji, aby scalić lokalnej wątku zestawów danych.Biblioteka desenie równoległe (PPL)
W tym artykule opisano PPL, który zapewnia nadrzędnych model programowania, który promuje skalowalność i łatwość użycia opracowywanie aplikacji równoczesnych.
Odwołanie
Klasa concurrent_unordered_map
Klasa concurrent_unordered_multimap
Klasa concurrent_unordered_set