Aracılığıyla paylaş


Nasıl yapılır: özel durum için sonu paralel bir döngü işleme kullanın

Bu konu nasıl arama algoritması için bir temel ağaç yapısı yazılacağını gösterir.

Konu ppl iptali paralel desen Kitaplığı'nda iptal rolünü açıklar. Daha az verimli şekilde kullanımını daha paralel iş iptal etmek için özel durum işleme kullanılmasıdır concurrency::task_group::cancel ve concurrency::structured_task_group::cancel yöntemleri. Görevler veya paralel algoritmalar kullanır, ancak sağlamaz bir üçüncü taraf kütüphaneye çağırdığınızda ancak, burada iş iptal etmek için özel durum işleme kullanımını olduğu uygun bir senaryo, bir task_group veya structured_task_group iptal etmek için nesne.

Örnek

Aşağıdaki örnek, bir basic gösterir tree türü bir veri öğesi ve alt düğümlerin listesini içerir. Gövde metni aşağıdaki bölümde gösterilmektedir for_all yöntemi, art arda her alt düğümünde iş işlevi gerçekleştirir.

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

Aşağıdaki örnekte gösterildiği for_all yöntem. Kullandığı concurrency::parallel_for_each paralel ağacının her düğümde çalışma işlevi gerçekleştirmek için algoritma.

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

Aşağıdaki örnekte gösterildiği search_for_value sağlanan bir değeri arar işlevi, tree nesne. Bu işlev geçirir ve for_all sağlanan değeri içeren bir ağaç düğümü bulduğu oluşturduğunda, iş işlevi bir yöntem.

Var sayın tree sınıfı bir üçüncü taraf kitaplığı tarafından sağlanan ve üzerinde değişiklik yapamazsınız. Bu durumda, özel durum işleme kullanımı uygundur çünkü for_all yöntemini sağlamaz bir task_group veya structured_task_group arayan için nesne. Bu nedenle, iş işlevi doğrudan kendi üst görev grubu iptal veremiyor.

Sağladığınız bir görev grubu iş işlevi özel durum oluşturduğunda, çalışma zamanı (herhangi bir alt görev grupları da dahil olmak üzere) görev grubundaki tüm görevler durdurur ve henüz başlatılmamış herhangi bir görevi atar. search_for_value İşlevini kullanan bir try-catch özel durum yakalamak ve konsola sonucu yazdırmak için blok.

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

Aşağıdaki örnek oluşturur bir tree nesne ve paralel birkaç değerleri arar. build_tree İşlevi, bu konuda daha sonra gösterilir.

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

Bu örnek kullanır concurrency::parallel_invoke paralel değerleri aramak için kullanılan algoritma. Bu algoritma hakkında daha fazla bilgi için bkz: Paralel algoritmalar.

Aşağıdaki tam bir örnek değerleri temel ağaç yapısı içinde aramak için özel durum işleme kullanır.

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

Bu örnek, aşağıdaki örnek çıktı oluşturur.

       

Kod Derleniyor

Örnek kodu kopyalayın ve Visual Studio projesinde yapıştırın veya adlı bir dosyaya yapıştırın görev ağacı search.cpp ve ardından Visual Studio komut istemi penceresinde aşağıdaki komutu çalıştırın.

cl.exe /EHsc task-tree-search.cpp

Ayrıca bkz.

Başvuru

task_group sınıfı

structured_task_group sınıfı

parallel_for_each işlevi

Kavramlar

ppl iptali

Özel durum işleme eşzamanlılık çalışma zamanında

Görev paralellik (eşzamanlılık çalışma zamanı)

Paralel algoritmalar