Anteckning
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
PPL (Parallel Patterns Library) innehåller flera containrar och objekt som ger trådsäker åtkomst till elementen.
En samtidig container ger samtidig åtkomst till de viktigaste åtgärderna. Här innebär samtidighetssäkert att pekare eller iteratorer alltid är giltiga. Det är inte en garanti för elementinitiering eller en viss bläddreringsordning. Funktionerna i dessa containrar liknar de som tillhandahålls av C++-standardbiblioteket. Till exempel liknar concurrency::concurrent_vector-klassen std::vector-klassen, förutom att concurrent_vector-klassen tillåter dig att addera element parallellt. Använd samtidiga containrar när du har parallell kod som kräver både läs- och skrivåtkomst till samma container.
Ett samtidigt objekt delas samtidigt mellan komponenter. En process som beräknar tillståndet för ett parallellt objekt ger samma resultat som en annan process som beräknar samma tillstånd seriellt. Klassen concurrency::combinable är ett exempel på en samtidig objekttyp. Med combinable klassen kan du utföra beräkningar parallellt och sedan kombinera dessa beräkningar till ett slutligt resultat. Använd samtidiga objekt när du annars skulle använda en synkroniseringsmekanism, till exempel en mutex, för att synkronisera åtkomst till en delad variabel eller resurs.
Sektioner
I det här avsnittet beskrivs följande parallella containrar och objekt i detalj.
Samtidiga containrar:
Samtidiga objekt:
concurrent_vector-klass
              Klassen concurrency::concurrent_vector är en sekvenscontainerklass som precis som klassen std::vector ger dig slumpmässig åtkomst till dess element. Klassen concurrent_vector möjliggör samtidighetssäkra tilläggs- och elementåtkomståtgärder. Tilläggsåtgärder ogiltigförklarar inte befintliga pekare eller iteratorer. Iteratoråtkomst och traverseringsoperationer är också samtidighetssäkra. Här innebär samtidighetssäkert att pekare eller iteratorer alltid är giltiga. Det är inte en garanti för elementinitiering eller en viss bläddreringsordning.
Skillnader mellan concurrent_vector och vektor
Klassen concurrent_vector liknar klassen vector. Komplexiteten i tilläggs-, elementåtkomst- och iteratoråtkomståtgärder på ett concurrent_vector objekt är samma som för ett vector objekt. Följande punkter illustrerar var concurrent_vector skiljer sig från vector:
- Tillägg, elementåtkomst, iteratoråtkomst och iteratortraverseringar på ett - concurrent_vector-objekt är säkra för samtidighet.
- Du kan bara lägga till element i slutet av ett - concurrent_vectorobjekt. Klassen- concurrent_vectortillhandahåller inte metoden- insert.
- Ett - concurrent_vectorobjekt använder inte rörelse-semantik när du lägger till det.
- Klassen - concurrent_vectortillhandahåller inte metoderna- eraseeller- pop_back. Precis som med- vectoranvänder du clear-metoden för att ta bort alla element från ett- concurrent_vectorobjekt.
- Klassen - concurrent_vectorlagrar inte elementen sammanhängande i minnet. Därför kan du inte använda- concurrent_vectorklassen på alla sätt som du kan använda en matris. För en variabel med namnet- vav typen- concurrent_vectorskapar uttrycket- &v[0]+2till exempel odefinierat beteende.
- Klassen - concurrent_vectordefinierar metoderna grow_by och grow_to_at_least . Dessa metoder liknar storleksändringsmetoden , förutom att de är samtidighetssäkra.
- Ett - concurrent_vectorobjekt flyttar inte dess element när du lägger till det eller ändrar storlek på det. På så sätt kan befintliga pekare och iteratorer förbli giltiga under samtidiga åtgärder.
- Körtiden definierar inte en specialiserad version av - concurrent_vectorför typen- bool.
Concurrency-Safe åtgärder
Alla metoder som lägger till eller ökar storleken på ett concurrent_vector objekt, eller som har åtkomst till ett element i ett concurrent_vector objekt, är samtidighetssäkra. Här innebär samtidighetssäkert att pekare eller iteratorer alltid är giltiga. Det är inte en garanti för elementinitiering eller en viss bläddreringsordning. Undantaget till den här regeln är resize metoden.
I följande tabell visas vanliga concurrent_vector metoder och operatorer som är samtidighetssäkra.
Operationer som tillhandahålls av runtime-miljön för kompatibilitet med C++-standardbiblioteket, till exempel reserve, är inte trådsäkra. I följande tabell visas vanliga metoder och operatorer som inte är samtidighetssäkra.
Åtgärder som ändrar värdet för befintliga element är inte samtidighetssäkra. Använd ett synkroniseringsobjekt, till exempel ett reader_writer_lock-objekt för att synkronisera samtidiga läs- och skrivåtgärder till samma dataelement. Mer information om synkroniseringsobjekt finns i Synkronisera datastrukturer.
När du konverterar befintlig kod som använder vector för att använda concurrent_vectorkan samtidiga åtgärder göra att programmets beteende ändras. Tänk dig till exempel följande program som samtidigt utför två uppgifter på ett concurrent_vector objekt. Den första uppgiften lägger till ytterligare element i ett concurrent_vector objekt. Den andra aktiviteten beräknar summan av alla element i samma objekt.
// 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;
      }
   );
}
              end Även om metoden är samtidighetssäker, gör ett samtidigt anrop till push_back-metoden att värdet som returneras av end ändras. Antalet element som iteratorn passerar är obestämt. Därför kan det här programmet generera olika resultat varje gång du kör det. När elementtypen inte är trivial är det möjligt att ett loppvillkor finns mellan push_back och end-anropen. Metoden end kan returnera ett element som är allokerat, men inte helt initierat.
Undantagssäkerhet
Om en tillväxt- eller tilldelningsåtgärd utlöser ett undantag blir objektets concurrent_vector tillstånd ogiltigt. Beteendet för ett concurrent_vector objekt som är i ett ogiltigt tillstånd är odefinierat om inget annat anges. Destruktorn frigör dock alltid det minne som objektet allokerar, även om objektet är i ett ogiltigt tillstånd.
Datatypen för vektorelementen, T, måste uppfylla följande krav. Annars är klassens concurrent_vector beteende odefinierat.
- Destruktorn får inte kasta. 
- Om standardkonstruktorn eller kopieringskonstruktorn genererar får destruktorn inte deklareras med nyckelordet - virtualoch den måste fungera korrekt med nollinitierat minne.
[Topp]
concurrent_queue-klass
Med klassen concurrency::concurrent_queue , precis som klassen std::queue , kan du komma åt dess element på framsidan och baksidan. Klassen concurrent_queue möjliggör samtidighetssäkra queue- och dequeue-åtgärder. Här innebär samtidighetssäkert att pekare eller iteratorer alltid är giltiga. Det är inte en garanti för elementinitiering eller en viss bläddreringsordning. Klassen concurrent_queue tillhandahåller även iteratorstöd som inte är samtidighetssäkert.
Skillnader mellan concurrent_queue och queue
Klassen concurrent_queue liknar klassen queue. Följande punkter illustrerar var concurrent_queue skiljer sig från queue:
- Enqueue- och dequeue-åtgärder på ett - concurrent_queueobjekt är samtidighetssäkra.
- Klassen - concurrent_queuetillhandahåller iteratorstöd som inte är samtidighetssäkert.
- Klassen - concurrent_queuetillhandahåller inte metoderna- fronteller- pop. Klassen- concurrent_queueersätter dessa metoder genom att definiera metoden try_pop .
- Klassen - concurrent_queuetillhandahåller inte metoden- back. Därför kan du inte referera till slutet av kön.
- Klassen - concurrent_queueinnehåller metoden unsafe_size i stället för- sizemetoden. Metoden- unsafe_sizeär inte samtidighetssäker.
Concurrency-Safe åtgärder
Alla metoder som köar till eller avviker från ett concurrent_queue objekt är samtidighetssäkra. Här innebär samtidighetssäkert att pekare eller iteratorer alltid är giltiga. Det är inte en garanti för elementinitiering eller en viss bläddreringsordning.
I följande tabell visas vanliga concurrent_queue metoder och operatorer som är samtidighetssäkra.
Även om metoden empty är samtidighetssäker kan en samtidig åtgärd leda till att kön växer eller krymper innan metoden empty returnerar.
I följande tabell visas vanliga metoder och operatorer som inte är samtidighetssäkra.
Iteratorstöd
Tillhandahåller concurrent_queue iteratorer som inte är samtidighetssäkra. Vi rekommenderar att du endast använder dessa iteratorer för felsökning.
En concurrent_queue iterator passerar endast element i framåtriktad riktning. I följande tabell visas de operatorer som varje iterator stöder.
| Operatör | Beskrivning | 
|---|---|
| operator++ | Avancerar till nästa objekt i kön. Den här operatorn är överbelastad för att ge både pre-increment och post-increment semantik. | 
| operator* | Hämtar en referens till det aktuella objektet. | 
| operator-> | Hämtar en pekare till det aktuella objektet. | 
[Topp]
concurrent_unordered_map-klass
Klassen concurrency::concurrent_unordered_map är en associativ containerklass som precis som klassen std::unordered_map styr en sekvens med varierande längd av element av typen std::pair<const Key, Ty>. Tänk på en oordnad karta som en ordlista som du kan lägga till ett nyckel- och värdepar till eller slå upp ett värde efter nyckel. Den här klassen är användbar när du har flera trådar eller uppgifter som måste ha samtidig åtkomst till en delad container, infoga i den eller uppdatera den.
I följande exempel visas den grundläggande strukturen för att använda concurrent_unordered_map. I det här exemplet infogas teckennycklar i intervallet ['a', 'i']. Eftersom ordningen på åtgärderna är obestämd är det slutliga värdet för varje nyckel också obestämt. Det är dock säkert att utföra infogningar parallellt.
// 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]
*/
Ett exempel som använder concurrent_unordered_map för att utföra en mappnings- och reduce-åtgärd parallellt finns i How to: Perform Map and Reduce Operations in Parallel (Så här utför du map- och reduce-åtgärder parallellt).
Skillnader mellan concurrent_unordered_map och unordered_map
Klassen concurrent_unordered_map liknar klassen unordered_map. Följande punkter illustrerar var concurrent_unordered_map skiljer sig från unordered_map:
- Metoderna - erase,- bucket,- bucket_count, och- bucket_sizeheter- unsafe_erase,- unsafe_bucket,- unsafe_bucket_countoch- unsafe_bucket_sizerespektive . Namngivningskonventionen- unsafe_anger att dessa metoder inte är samtidighetssäkra. Mer information om samtidighetssäkerhet finns iConcurrency-Safe Åtgärder.
- Infogningsåtgärder ogiltigförklarar inte befintliga pekare eller iteratorer och ändrar inte heller ordningen på objekt som redan finns på kartan. Infognings- och blädderingsåtgärder kan utföras samtidigt. 
- concurrent_unordered_mapstöder endast framlängesiteration.
- Infogningen ogiltigförklarar eller uppdaterar inte de iteratorer som returneras av - equal_range. Infogning kan lägga till ojämna objekt i slutet av intervallet. Iteratorn begin pekar på ett lika med objekt.
För att undvika dödlägen finns det ingen metod för concurrent_unordered_map att hålla ett lås när den anropar minnesallokeraren, hashfunktionerna eller annan användardefinierad kod. Du måste också se till att hash-funktionen alltid utvärderar lika med nycklar till samma värde. De bästa hash-funktionerna distribuerar nycklar jämnt över hash-kodutrymmet.
Concurrency-Safe åtgärder
Klassen concurrent_unordered_map möjliggör samtidighetssäkra infognings- och elementåtkomståtgärder. Infogningsåtgärder ogiltigförklarar inte befintliga pekare eller iteratorer. Iteratoråtkomst och traverseringsoperationer är också samtidighetssäkra. Här innebär samtidighetssäkert att pekare eller iteratorer alltid är giltiga. Det är inte en garanti för elementinitiering eller en viss bläddreringsordning. I följande tabell visas de metoder och operatorer som används concurrent_unordered_map ofta och som är samtidighetssäkra.
              count Även om metoden kan anropas på ett säkert sätt från trådar som körs samtidigt kan olika trådar få olika resultat om ett nytt värde infogas samtidigt i containern.
I följande tabell visas de metoder och operatorer som används ofta och som inte är samtidighetssäkra.
Förutom dessa metoder är alla metoder som börjar med unsafe_ inte heller samtidighetssäkra.
[Topp]
concurrent_unordered_multimap-klass
              Concurrency::concurrent_unordered_multimap-klassen liknar concurrent_unordered_map-klassen, men tillåter att flera värden kan mappas till samma nyckel. Det skiljer sig också från concurrent_unordered_map på följande sätt:
- Metoden concurrent_unordered_multimap::insert returnerar en iterator i stället - std::pair<iterator, bool>för .
- Klassen - concurrent_unordered_multimaptillhandahåller varken- operator[]eller- at-metoden.
I följande exempel visas den grundläggande strukturen för att använda concurrent_unordered_multimap. I det här exemplet infogas teckennycklar i intervallet ['a', 'i']. 
              concurrent_unordered_multimap gör det möjligt för en nyckel att ha flera värden.
// 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]
*/
[Topp]
concurrent_unordered_set-klass
              Concurrency::concurrent_unordered_set-klassen liknar concurrent_unordered_map-klassen, förutom att den hanterar värden i stället för nyckel- och värdepar. Klassen concurrent_unordered_set tillhandahåller varken operator[] eller at-metoden.
I följande exempel visas den grundläggande strukturen för att använda concurrent_unordered_set. I det här exemplet infogas teckenvärden i intervallet ['a', 'i']. Det är säkert att utföra infogningar parallellt.
// 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]
*/
[Topp]
concurrent_unordered_multiset-klass
              Concurrency::concurrent_unordered_multiset-klassen liknar concurrent_unordered_set-klassen, förutom att den tillåter duplicerade värden. Det skiljer sig också från concurrent_unordered_set på följande sätt:
- Metoden concurrent_unordered_multiset::insert returnerar en iterator i stället för - std::pair<iterator, bool>.
- Klassen - concurrent_unordered_multisettillhandahåller varken- operator[]eller- at-metoden.
I följande exempel visas den grundläggande strukturen för att använda concurrent_unordered_multiset. I det här exemplet infogas teckenvärden i intervallet ['a', 'i']. 
              concurrent_unordered_multiset aktiverar ett värde för att inträffa flera gånger.
// 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]
*/
[Topp]
kombinerbar klass
Klassen concurrency::combinable ger återanvändbar, trådlokal lagring som gör att du kan utföra detaljerade beräkningar och sedan sammanfoga dessa beräkningar till ett slutligt resultat. Du kan se ett combinable objekt som en minskningsvariabel.
Klassen combinable är användbar när du har en resurs som delas mellan flera trådar eller aktiviteter. Klassen combinable hjälper dig att eliminera delat tillstånd genom att ge åtkomst till delade resurser på ett låsfritt sätt. Därför är den här klassen ett alternativ till att använda en synkroniseringsmekanism, till exempel en mutex, för att synkronisera åtkomst till delade data från flera trådar.
Metoder och funktioner
I följande tabell visas några av de viktiga metoderna i combinable klassen. Mer information om alla klassmetoder finns i combinablekombinerbar klass.
| Metod | Beskrivning | 
|---|---|
| lokala | Hämtar en referens till den lokala variabeln som är associerad med den aktuella trådkontexten. | 
| klar | Tar bort alla trådlokala variabler från objektet combinable. | 
| kombinera combine_each | Använder den angivna kombinationsfunktionen för att generera ett slutligt värde från uppsättningen med alla trådlokala beräkningar. | 
Klassen combinable är en mallklass som parametriseras på det slutliga sammanfogade resultatet. Om du anropar standardkonstruktorn T måste mallparametertypen ha en standardkonstruktor och en kopieringskonstruktor. 
              T Om mallparametertypen inte har någon standardkonstruktor anropar du den överlagrade versionen av konstruktorn som tar en initieringsfunktion som parameter.
Du kan lagra ytterligare data i ett combinable objekt när du anropar metoderna kombinera eller combine_each . Du kan också anropa combine metoderna och combine_each flera gånger. Om inget lokalt värde i ett combinable objekt ändras combine ger metoderna och combine_each samma resultat varje gång de anropas.
Exempel
Exempel på hur du använder combinable klassen finns i följande avsnitt:
[Topp]
Relaterade ämnen
              Gör så här: Använda parallella containrar för att öka effektiviteten
Visar hur du använder parallella containrar för att effektivt lagra och komma åt data parallellt.
              Gör så här: Använd kombinerbart för att förbättra prestanda
Visar hur du använder combinable klassen för att eliminera delat tillstånd och därmed förbättra prestandan.
              Gör så här: Använd kombinerbart för att kombinera uppsättningar
Visar hur du använder en combine funktion för att sammanfoga trådlokala datauppsättningar.
              PPL (Parallel Patterns Library)
Beskriver PPL, som tillhandahåller en imperativ programmeringsmodell som främjar skalbarhet och användarvänlighet för utveckling av samtidiga program.
Hänvisning
Concurrent_unordered_map-Klass
concurrent_unordered_multimap-klass
Klassen concurrent_unordered_set