Cara: Menggunakan Penanganan Pengecualian untuk Memutuskan dari Perulangan Paralel
Topik ini menunjukkan cara menulis algoritma pencarian untuk struktur pohon dasar.
Topik Pembatalan menjelaskan peran pembatalan di Pustaka Pola Paralel. Penggunaan penanganan pengecualian adalah cara yang kurang efisien untuk membatalkan pekerjaan paralel daripada penggunaan metode konkurensi::task_group::cancel dan konkurensi::structured_task_group::batal . Namun, satu skenario di mana penggunaan penanganan pengecualian untuk membatalkan pekerjaan sesuai adalah ketika Anda memanggil ke pustaka pihak ketiga yang menggunakan tugas atau algoritma paralel tetapi tidak menyediakan task_group
objek atau structured_task_group
untuk dibatalkan.
Contoh: Jenis pohon dasar
Contoh berikut menunjukkan jenis dasar tree
yang berisi elemen data dan daftar simpul anak. Bagian berikut menunjukkan isi for_all
metode , yang secara rekursif melakukan fungsi kerja pada setiap simpul anak.
// A simple tree structure that has multiple child nodes.
template <typename T>
class tree
{
public:
explicit tree(T data)
: _data(data)
{
}
// Retrieves the data element for the node.
T get_data() const
{
return _data;
}
// Adds a child node to the tree.
void add_child(tree& child)
{
_children.push_back(child);
}
// Performs the given work function on the data element of the tree and
// on each child.
template<class Function>
void for_all(Function& action);
private:
// The data for this node.
T _data;
// The child nodes.
list<tree> _children;
};
Contoh: Melakukan pekerjaan secara paralel
Contoh berikut menunjukkan for_all
metode . Ini menggunakan algoritma konkurensi::p arallel_for_each untuk melakukan fungsi kerja pada setiap simpul pohon secara paralel.
// Performs the given work function on the data element of the tree and
// on each child.
template<class Function>
void for_all(Function& action)
{
// Perform the action on each child.
parallel_for_each(begin(_children), end(_children), [&](tree& child) {
child.for_all(action);
});
// Perform the action on this node.
action(*this);
}
Contoh: Mencari pohon untuk nilai
Contoh berikut menunjukkan search_for_value
fungsi, yang mencari nilai dalam objek yang disediakan tree
. Fungsi ini diteruskan ke for_all
metode fungsi kerja yang melempar ketika menemukan simpul pohon yang berisi nilai yang disediakan.
Asumsikan bahwa tree
kelas disediakan oleh pustaka pihak ketiga, dan Anda tidak dapat memodifikasinya. Dalam hal ini, penggunaan penanganan pengecualian sesuai karena for_all
metode tidak menyediakan task_group
atau structured_task_group
objek kepada pemanggil. Oleh karena itu, fungsi kerja tidak dapat langsung membatalkan grup tugas induknya.
Saat fungsi kerja yang Anda berikan ke grup tugas memberikan pengecualian, runtime menghentikan semua tugas yang ada di grup tugas (termasuk grup tugas turunan apa pun) dan membuang tugas apa pun yang belum dimulai. Fungsi ini search_for_value
menggunakan try
-catch
blok untuk menangkap pengecualian dan mencetak hasilnya ke konsol.
// Searches for a value in the provided tree object.
template <typename T>
void search_for_value(tree<T>& t, int value)
{
try
{
// Call the for_all method to search for a value. The work function
// throws an exception when it finds the value.
t.for_all([value](const tree<T>& node) {
if (node.get_data() == value)
{
throw &node;
}
});
}
catch (const tree<T>* node)
{
// A matching node was found. Print a message to the console.
wstringstream ss;
ss << L"Found a node with value " << value << L'.' << endl;
wcout << ss.str();
return;
}
// A matching node was not found. Print a message to the console.
wstringstream ss;
ss << L"Did not find node with value " << value << L'.' << endl;
wcout << ss.str();
}
Contoh: Membuat dan mencari pohon secara paralel
Contoh berikut membuat tree
objek dan mencarinya untuk beberapa nilai secara paralel. Fungsi build_tree
ini ditampilkan nanti dalam topik ini.
int wmain()
{
// Build a tree that is four levels deep with the initial level
// having three children. The value of each node is a random number.
mt19937 gen(38);
tree<int> t = build_tree<int>(4, 3, [&gen]{ return gen()%100000; });
// Search for a few values in the tree in parallel.
parallel_invoke(
[&t] { search_for_value(t, 86131); },
[&t] { search_for_value(t, 17522); },
[&t] { search_for_value(t, 32614); }
);
}
Contoh ini menggunakan algoritma concurrency::p arallel_invoke untuk mencari nilai secara paralel. Untuk informasi selengkapnya tentang algoritma ini, lihat Algoritma Paralel.
Contoh: Sampel kode penanganan pengecualian selesai
Contoh lengkap berikut menggunakan penanganan pengecualian untuk mencari nilai dalam struktur pohon dasar.
// task-tree-search.cpp
// compile with: /EHsc
#include <ppl.h>
#include <list>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <random>
using namespace concurrency;
using namespace std;
// A simple tree structure that has multiple child nodes.
template <typename T>
class tree
{
public:
explicit tree(T data)
: _data(data)
{
}
// Retrieves the data element for the node.
T get_data() const
{
return _data;
}
// Adds a child node to the tree.
void add_child(tree& child)
{
_children.push_back(child);
}
// Performs the given work function on the data element of the tree and
// on each child.
template<class Function>
void for_all(Function& action)
{
// Perform the action on each child.
parallel_for_each(begin(_children), end(_children), [&](tree& child) {
child.for_all(action);
});
// Perform the action on this node.
action(*this);
}
private:
// The data for this node.
T _data;
// The child nodes.
list<tree> _children;
};
// Builds a tree with the given depth.
// Each node of the tree is initialized with the provided generator function.
// Each level of the tree has one more child than the previous level.
template <typename T, class Generator>
tree<T> build_tree(int depth, int child_count, Generator& g)
{
// Create the tree node.
tree<T> t(g());
// Add children.
if (depth > 0)
{
for(int i = 0; i < child_count; ++i)
{
t.add_child(build_tree<T>(depth - 1, child_count + 1, g));
}
}
return t;
}
// Searches for a value in the provided tree object.
template <typename T>
void search_for_value(tree<T>& t, int value)
{
try
{
// Call the for_all method to search for a value. The work function
// throws an exception when it finds the value.
t.for_all([value](const tree<T>& node) {
if (node.get_data() == value)
{
throw &node;
}
});
}
catch (const tree<T>* node)
{
// A matching node was found. Print a message to the console.
wstringstream ss;
ss << L"Found a node with value " << value << L'.' << endl;
wcout << ss.str();
return;
}
// A matching node was not found. Print a message to the console.
wstringstream ss;
ss << L"Did not find node with value " << value << L'.' << endl;
wcout << ss.str();
}
int wmain()
{
// Build a tree that is four levels deep with the initial level
// having three children. The value of each node is a random number.
mt19937 gen(38);
tree<int> t = build_tree<int>(4, 3, [&gen]{ return gen()%100000; });
// Search for a few values in the tree in parallel.
parallel_invoke(
[&t] { search_for_value(t, 86131); },
[&t] { search_for_value(t, 17522); },
[&t] { search_for_value(t, 32614); }
);
}
Contoh ini menghasilkan output sampel berikut.
Found a node with value 32614.
Found a node with value 86131.
Did not find node with value 17522.
Mengompilasi Kode
Salin kode contoh dan tempelkan dalam proyek Visual Studio, atau tempelkan dalam file yang diberi nama task-tree-search.cpp
lalu jalankan perintah berikut di jendela Prompt Perintah Visual Studio.
cl.exe /EHsc task-tree-search.cpp
Baca juga
Pembatalan di PPL
Penanganan Pengecualian
Paralelisme Tugas
Algoritma Paralel
Kelas task_group
Kelas structured_task_group
Fungsi parallel_for_each
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk