Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Beberapa perulangan paralel tidak mengharuskan semua iterasi dijalankan. Misalnya, algoritma yang mencari nilai dapat dihentikan setelah nilai ditemukan. OpenMP tidak menyediakan mekanisme untuk keluar dari perulangan paralel. Namun, Anda dapat menggunakan nilai Boolean, atau bendera, untuk mengaktifkan iterasi perulangan untuk menunjukkan bahwa solusi telah ditemukan. Runtime Konkurensi menyediakan fungsionalitas yang memungkinkan satu tugas untuk membatalkan tugas lain yang belum dimulai.
Contoh ini menunjukkan cara mengonversi paralelOpenMP untuk perulangan yang tidak mengharuskan semua perulangan dijalankan untuk menggunakan mekanisme pembatalan Runtime Konkurensi.
Contoh
Contoh ini menggunakan OpenMP dan Runtime Konkurensi untuk mengimplementasikan versi paralel algoritma std::any_of . Versi OpenMP dari contoh ini menggunakan bendera untuk berkoordinasi di antara semua iterasi perulangan paralel yang telah terpenuhi kondisinya. Versi yang menggunakan Runtime Konkurensi menggunakan metode konkurensi::structured_task_group::batal untuk menghentikan operasi keseluruhan saat kondisi terpenuhi.
// concrt-omp-parallel-any-of.cpp
// compile with: /EHsc /openmp
#include <ppl.h>
#include <array>
#include <random>
#include <iostream>
using namespace concurrency;
using namespace std;
// Uses OpenMP to determine whether a condition exists in
// the specified range of elements.
template <class InIt, class Predicate>
bool omp_parallel_any_of(InIt first, InIt last, const Predicate& pr)
{
typedef typename std::iterator_traits<InIt>::value_type item_type;
// A flag that indicates that the condition exists.
bool found = false;
#pragma omp parallel for
for (int i = 0; i < static_cast<int>(last-first); ++i)
{
if (!found)
{
item_type& cur = *(first + i);
// If the element satisfies the condition, set the flag to
// cancel the operation.
if (pr(cur)) {
found = true;
}
}
}
return found;
}
// Uses the Concurrency Runtime to determine whether a condition exists in
// the specified range of elements.
template <class InIt, class Predicate>
bool concrt_parallel_any_of(InIt first, InIt last, const Predicate& pr)
{
typedef typename std::iterator_traits<InIt>::value_type item_type;
structured_task_group tasks;
// Create a predicate function that cancels the task group when
// an element satisfies the condition.
auto for_each_predicate = [&pr, &tasks](const item_type& cur) {
if (pr(cur)) {
tasks.cancel();
}
};
// Create a task that calls the predicate function in parallel on each
// element in the range.
auto task = make_task([&]() {
parallel_for_each(first, last, for_each_predicate);
});
// The condition is satisfied if the task group is in the cancelled state.
return tasks.run_and_wait(task) == canceled;
}
int wmain()
{
// The length of the array.
const size_t size = 100000;
// Create an array and initialize it with random values.
array<int, size> a;
generate(begin(a), end(a), mt19937(42));
// Search for a value in the array by using OpenMP and the Concurrency Runtime.
const int what = 9114046;
auto predicate = [what](int n) -> bool {
return (n == what);
};
wcout << L"Using OpenMP..." << endl;
if (omp_parallel_any_of(begin(a), end(a), predicate))
{
wcout << what << L" is in the array." << endl;
}
else
{
wcout << what << L" is not in the array." << endl;
}
wcout << L"Using the Concurrency Runtime..." << endl;
if (concrt_parallel_any_of(begin(a), end(a), predicate))
{
wcout << what << L" is in the array." << endl;
}
else
{
wcout << what << L" is not in the array." << endl;
}
}
Contoh ini menghasilkan output berikut.
Using OpenMP...
9114046 is in the array.
Using the Concurrency Runtime...
9114046 is in the array.
Dalam versi yang menggunakan OpenMP, semua iterasi perulangan dijalankan, bahkan ketika bendera diatur. Selain itu, jika tugas memiliki tugas turunan, bendera juga harus tersedia untuk tugas anak tersebut untuk berkomunikasi pembatalan. Di Runtime Konkurensi, saat grup tugas dibatalkan, runtime membatalkan seluruh pohon pekerjaan, termasuk tugas anak.
Algoritma concurrency::p arallel_for_each menggunakan tugas untuk melakukan pekerjaan. Oleh karena itu, ketika satu iterasi perulangan membatalkan tugas akar, seluruh pohon komputasi juga dibatalkan. Ketika pohon pekerjaan dibatalkan, runtime tidak memulai tugas baru. Namun, runtime memungkinkan tugas yang sudah mulai selesai. Oleh karena itu, dalam kasus parallel_for_each algoritma, iterasi perulangan aktif dapat membersihkan sumber daya mereka.
Dalam kedua versi contoh ini, jika array berisi lebih dari satu salinan nilai yang akan dicari, beberapa iterasi perulangan dapat masing-masing secara bersamaan mengatur hasilnya dan membatalkan operasi keseluruhan. Anda dapat menggunakan primitif sinkronisasi, seperti bagian penting, jika masalah Anda mengharuskan hanya satu tugas yang melakukan pekerjaan saat kondisi terpenuhi.
Anda juga dapat menggunakan penanganan pengecualian untuk membatalkan tugas yang menggunakan PPL. Untuk informasi selengkapnya tentang pembatalan, lihat Pembatalan di PPL.
Untuk informasi selengkapnya tentang parallel_for_each dan algoritma paralel lainnya, lihat Algoritma Paralel.
Mengompilasi Kode
Salin kode contoh dan tempelkan dalam proyek Visual Studio, atau tempelkan dalam file yang diberi nama concrt-omp-parallel-any-of.cpp lalu jalankan perintah berikut di jendela Prompt Perintah Visual Studio.
cl.exe /EHsc /openmp concrt-omp-parallel-any-of.cpp
Lihat juga
Migrasi dari OpenMP ke Runtime Konkurensi
Pembatalan di PPL
Algoritma Paralel