Cara: Menggunakan yang dapat dikombinasikan untuk Meningkatkan Performa

Contoh ini menunjukkan cara menggunakan kelas konkurensi::combinable untuk menghitung jumlah angka dalam objek std::array yang prima. Kelas combinable meningkatkan performa dengan menghilangkan status bersama.

Tip

Dalam beberapa kasus, peta paralel (konkurensi::p arallel_transform) dan mengurangi (konkurensi:: parallel_reduce) dapat memberikan peningkatan performa atas combinable. Untuk contoh yang menggunakan peta dan mengurangi operasi untuk menghasilkan hasil yang sama dengan contoh ini, lihat Algoritma Paralel.

Contoh - terakumulasi

Contoh berikut menggunakan fungsi std::accumulate untuk menghitung jumlah elemen dalam array yang prima. Dalam contoh ini, a adalah array objek dan is_prime fungsi menentukan apakah nilai inputnya prima.

prime_sum = accumulate(begin(a), end(a), 0, [&](int acc, int i) {
   return acc + (is_prime(i) ? i : 0);
});

Contoh - parallel_for_each

Contoh berikut menunjukkan cara naif untuk menyejajarkan contoh sebelumnya. Contoh ini menggunakan algoritma concurrency::p arallel_for_each untuk memproses array secara paralel dan objek konkurensi::critical_section untuk menyinkronkan akses ke prime_sum variabel. Contoh ini tidak menskalakan karena setiap utas harus menunggu sumber daya bersama tersedia.

critical_section cs;
prime_sum = 0;
parallel_for_each(begin(a), end(a), [&](int i) {
   cs.lock();
   prime_sum += (is_prime(i) ? i : 0);
   cs.unlock();
});

Contoh - dapat dikombinasikan

Contoh berikut menggunakan combinable objek untuk meningkatkan performa contoh sebelumnya. Contoh ini menghilangkan kebutuhan akan objek sinkronisasi; diskalakan karena combinable objek memungkinkan setiap utas untuk melakukan tugasnya secara independen.

Objek combinable biasanya digunakan dalam dua langkah. Pertama, menghasilkan serangkaian komputasi halus dengan melakukan pekerjaan secara paralel. Selanjutnya, gabungkan (atau kurangi) komputasi menjadi hasil akhir. Contoh ini menggunakan metode konkurensi::combinable::local untuk mendapatkan referensi ke jumlah lokal. Kemudian menggunakan konkurensi::combinable::combine method dan objek std::p lus untuk menggabungkan komputasi lokal ke dalam hasil akhir.

combinable<int> sum;
parallel_for_each(begin(a), end(a), [&](int i) {
   sum.local() += (is_prime(i) ? i : 0);
});
prime_sum = sum.combine(plus<int>());

Contoh - serial dan paralel

Contoh lengkap berikut menghitung jumlah bilangan prima baik secara serial maupun paralel. Contoh mencetak ke konsol waktu yang diperlukan untuk melakukan kedua komputasi.

// parallel-sum-of-primes.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <array>
#include <numeric>
#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;
}

// Determines whether the input value is prime.
bool is_prime(int n)
{
   if (n < 2)
      return false;
   for (int i = 2; i < n; ++i)
   {
      if ((n % i) == 0)
         return false;
   }
   return true;
}

int wmain()
{   
   // Create an array object that contains 200000 integers.
   array<int, 200000> a;

   // Initialize the array such that a[i] == i.
   iota(begin(a), end(a), 0);

   int prime_sum;
   __int64 elapsed;

   // Compute the sum of the numbers in the array that are prime.
   elapsed = time_call([&] {
      prime_sum = accumulate(begin(a), end(a), 0, [&](int acc, int i) {
         return acc + (is_prime(i) ? i : 0);
      });
   });   
   wcout << prime_sum << endl;   
   wcout << L"serial time: " << elapsed << L" ms" << endl << endl;

   // Now perform the same task in parallel.
   elapsed = time_call([&] {
      combinable<int> sum;
      parallel_for_each(begin(a), end(a), [&](int i) {
         sum.local() += (is_prime(i) ? i : 0);
      });
      prime_sum = sum.combine(plus<int>());
   });
   wcout << prime_sum << endl;
   wcout << L"parallel time: " << elapsed << L" ms" << endl << endl;
}

Contoh output berikut adalah untuk komputer yang memiliki empat prosesor.

1709600813
serial time: 6178 ms

1709600813
parallel time: 1638 ms

Mengompilasi Kode

Untuk mengkompilasi kode, salin lalu tempelkan dalam proyek Visual Studio, atau tempelkan dalam file yang diberi nama parallel-sum-of-primes.cpp lalu jalankan perintah berikut di jendela Prompt Perintah Visual Studio.

cl.exe /EHsc parallel-sum-of-primes.cpp

Pemrograman yang Kuat

Untuk contoh yang menggunakan peta dan mengurangi operasi untuk menghasilkan hasil yang sama, lihat Algoritma Paralel.

Baca juga

Kontainer dan Objek Paralel
Kelas yang dapat dikombinasikan
Kelas critical_section