Parallel Patterns Library (PPL)

Pustaka Pola Paralel (PPL) menyediakan model pemrograman imperatif yang mempromosikan skalabilitas dan kemudahan penggunaan untuk mengembangkan aplikasi bersamaan. PPL dibangun berdasarkan komponen penjadwalan dan manajemen sumber daya dari Concurrency Runtime. Ini meningkatkan tingkat abstraksi antara kode aplikasi Anda dan mekanisme utas yang mendasar dengan menyediakan algoritma dan kontainer generik dan jenis aman yang bertindak berdasarkan data secara paralel. PPL juga memungkinkan Anda mengembangkan aplikasi yang menskalakan dengan memberikan alternatif untuk status bersama.

PPL menyediakan fitur-fitur berikut:

  • Paralelisme Tugas: mekanisme yang bekerja di atas Windows ThreadPool untuk menjalankan beberapa item kerja (tugas) secara paralel

  • Algoritma paralel: algoritma generik yang bekerja di atas Runtime Konkurensi untuk bertindak pada pengumpulan data secara paralel

  • Kontainer dan objek paralel: jenis kontainer generik yang menyediakan akses bersamaan yang aman ke elemennya

Contoh

PPL menyediakan model pemrograman yang menyerupan Pustaka Standar C++. Contoh berikut menunjukkan banyak fitur PPL. Ini menghitung beberapa angka Fibonacci secara serial dan paralel. Kedua komputasi bertindak pada objek std::array . Contohnya juga mencetak ke konsol waktu yang diperlukan untuk melakukan kedua komputasi.

Versi serial menggunakan algoritma C++ Standard Library std::for_each untuk melintasi array dan menyimpan hasilnya dalam objek std::vector . Versi paralel melakukan tugas yang sama, tetapi menggunakan algoritma konkurensi PPL ::p arallel_for_each dan menyimpan hasilnya dalam objek konkurensi::concurrent_vector . Kelas ini concurrent_vector memungkinkan setiap iterasi perulangan untuk menambahkan elemen secara bersamaan tanpa persyaratan untuk menyinkronkan akses tulis ke kontainer.

Karena parallel_for_each bertindak bersamaan, versi paralel dari contoh ini harus mengurutkan concurrent_vector objek untuk menghasilkan hasil yang sama dengan versi seri.

Perhatikan bahwa contoh menggunakan metode naif untuk menghitung angka Fibonacci; namun, metode ini menggambarkan bagaimana Runtime Konkurensi dapat meningkatkan performa komputasi panjang.

// 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;
   });
}

Contoh output berikut adalah untuk komputer yang memiliki empat prosesor.

serial time: 9250 ms
parallel time: 5726 ms

fib(24): 46368
fib(26): 121393
fib(41): 165580141
fib(42): 267914296

Setiap perulangan perulangan membutuhkan jumlah waktu yang berbeda untuk diselesaikan. Performa parallel_for_each dibatasi oleh operasi yang selesai terakhir. Oleh karena itu, Anda tidak boleh mengharapkan peningkatan performa linier antara versi serial dan paralel dari contoh ini.

Judul Deskripsi
Paralelisme Tugas Menjelaskan peran tugas dan grup tugas di PPL.
Algoritma Paralel Menjelaskan cara menggunakan algoritma paralel seperti parallel_for dan parallel_for_each.
Kontainer dan Objek Paralel Menjelaskan berbagai kontainer dan objek paralel yang disediakan oleh PPL.
Pembatalan di PPL Menjelaskan cara membatalkan pekerjaan yang sedang dilakukan oleh algoritma paralel.
Runtime Konkurensi Menjelaskan Runtime Konkurensi, yang menyederhanakan pemrograman paralel, dan berisi tautan ke topik terkait.