Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De PPL (Parallel Patterns Library) biedt een imperatief programmeermodel dat schaalbaarheid en gebruiksgemak bevordert voor het ontwikkelen van gelijktijdige toepassingen. De PPL bouwt voort op de plannings- en beheeronderdelen van de Concurrency Runtime. Het verhoogt het abstractieniveau tussen uw toepassingscode en het onderliggende threadingmechanisme door algemene, typeveilige algoritmen en containers te bieden die parallel op gegevens reageren. Met de PPL kunt u ook toepassingen ontwikkelen die schalen door alternatieven te bieden voor de gedeelde status.
De PPL biedt de volgende functies:
Taakparallellisme: een mechanisme dat boven op de Windows ThreadPool werkt om verschillende werkitems (taken) parallel uit te voeren
Parallelle algoritmen: algemene algoritmen die bovenop de Gelijktijdigheidsruntime werken om te reageren op verzamelingen gegevens parallel
Parallelle containers en objecten: algemene containertypen die veilige gelijktijdige toegang tot hun elementen bieden
Voorbeeld
De PPL biedt een programmeermodel dat lijkt op de C++-standaardbibliotheek. In het volgende voorbeeld ziet u veel functies van de PPL. Het berekent meerdere Fibonacci-getallen serieel en parallel. Beide berekeningen handelen op een std::array-object . In het voorbeeld wordt ook naar de console geprint hoeveel tijd er nodig is om beide berekeningen uit te voeren.
De seriële versie maakt gebruik van het C++ Standard Library std::for_each algoritme om de matrix te doorlopen en de resultaten op te slaan in een std::vector-object . De parallelle versie voert dezelfde taak uit, maar gebruikt het concurrency::parallel_for_each-algoritme en slaat de resultaten op in een concurrency::concurrent_vector-object. Met concurrent_vector de klasse kan elke lusiteratie gelijktijdig elementen toevoegen zonder dat u schrijftoegang tot de container hoeft te synchroniseren.
Omdat parallel_for_each deze gelijktijdig werkt, moet de parallelle versie van dit voorbeeld het concurrent_vector object sorteren om dezelfde resultaten te produceren als de seriële versie.
Houd er rekening mee dat in het voorbeeld een naïeve methode wordt gebruikt om de Fibonacci-getallen te berekenen; Deze methode illustreert echter hoe de Gelijktijdigheidsruntime de prestaties van lange berekeningen kan verbeteren.
// parallel-fibonacci.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <concurrent_vector.h>
#include <array>
#include <vector>
#include <tuple>
#include <algorithm>
#include <iostream>
using namespace concurrency;
using namespace std;
// Calls the provided work function and returns the number of milliseconds 
// that it takes to call that function.
template <class Function>
__int64 time_call(Function&& f)
{
   __int64 begin = GetTickCount();
   f();
   return GetTickCount() - begin;
}
// Computes the nth Fibonacci number.
int fibonacci(int n)
{
   if(n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}
int wmain()
{
   __int64 elapsed;
   // An array of Fibonacci numbers to compute.
   array<int, 4> a = { 24, 26, 41, 42 };
   // The results of the serial computation.
   vector<tuple<int,int>> results1;
   // The results of the parallel computation.
   concurrent_vector<tuple<int,int>> results2;
   // Use the for_each algorithm to compute the results serially.
   elapsed = time_call([&] 
   {
      for_each (begin(a), end(a), [&](int n) {
         results1.push_back(make_tuple(n, fibonacci(n)));
      });
   });   
   wcout << L"serial time: " << elapsed << L" ms" << endl;
   
   // Use the parallel_for_each algorithm to perform the same task.
   elapsed = time_call([&] 
   {
      parallel_for_each (begin(a), end(a), [&](int n) {
         results2.push_back(make_tuple(n, fibonacci(n)));
      });
      // Because parallel_for_each acts concurrently, the results do not 
      // have a pre-determined order. Sort the concurrent_vector object
      // so that the results match the serial version.
      sort(begin(results2), end(results2));
   });   
   wcout << L"parallel time: " << elapsed << L" ms" << endl << endl;
   // Print the results.
   for_each (begin(results2), end(results2), [](tuple<int,int>& pair) {
      wcout << L"fib(" << get<0>(pair) << L"): " << get<1>(pair) << endl;
   });
}
De volgende voorbeelduitvoer is voor een computer met vier processors.
serial time: 9250 ms
parallel time: 5726 ms
fib(24): 46368
fib(26): 121393
fib(41): 165580141
fib(42): 267914296
Elke herhaling van de lus vereist een andere hoeveelheid tijd om te voltooien. De prestaties van parallel_for_each zijn afhankelijk van de bewerking die als laatste is voltooid. Daarom moet u geen lineaire prestatieverbeteringen verwachten tussen de seriële en parallelle versies van dit voorbeeld.
Verwante onderwerpen
| Titel | Beschrijving | 
|---|---|
| Parallelle uitvoering van taken | Beschrijft de rol van taken en taakgroepen in de PPL. | 
| Parallelle algoritmen | Beschrijft hoe parallelle algoritmen zoals parallel_for en parallel_for_each te gebruiken. | 
| parallelle containers en objecten | Beschrijft de verschillende parallelle containers en objecten die worden geleverd door de PPL. | 
| Annulering in de PPL | Hierin wordt uitgelegd hoe u het werk annuleert dat wordt uitgevoerd door een parallel algoritme. | 
| Gelijktijdigheidsruntime | Beschrijft de Gelijktijdigheidsruntime, die parallelle programmering vereenvoudigt en koppelingen naar verwante onderwerpen bevat. |