Sdílet prostřednictvím


Postupy: Použití paralelních kontejnerů ke zvýšení účinnosti

Toto téma ukazuje, jak použít paralelní kontejnery efektivně ukládat a přistupovat k datům v paralelní.

Příklad vypočítá sada prime a čísla Carmichael paralelně.Potom kód pro každé číslo Carmichael, vypočítá hlavní faktory tohoto čísla.

Příklad

Následující příklad ukazuje is_prime funkce, která určuje, zda vstupní hodnota je Prvočíslo, a is_carmichael funkce, která určuje, zda je počáteční hodnota číslo Carmichael.

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

// Determines whether the input value is a Carmichael number. 
bool is_carmichael(const int n) 
{
   if (n < 2) 
      return false;

   int k = n;
   for (int i = 2; i <= k / i; ++i) 
   {
      if (k % i == 0) 
      {
         if ((k / i) % i == 0) 
            return false;
         if ((n - 1) % (i - 1) != 0)
            return false;
         k /= i;
         i = 1;
      }
   }
   return k != n && (n - 1) % (k - 1) == 0;
}

V následujícím příkladu is_prime a is_carmichael funkce pro výpočet množiny prime a Carmichael čísel.V příkladu concurrency::parallel_invoke a concurrency::parallel_for algoritmy pro výpočet jednotlivých nastavení současně.Další informace o paralelních algoritmech naleznete v tématu Paralelní algoritmy.

V tomto příkladu concurrency::concurrent_queue objektu, který má obsahovat sadu Carmichael čísla, protože tento objekt bude později používat jako fronty pracovních položek.Používá concurrency::concurrent_vector objekt pro uložení sady prvočísel vzhledem k tomu, že bude později iterovat přes tento soubor vyhledejte primární faktory.

// The maximum number to test. 
const int max = 10000000;

// Holds the Carmichael numbers that are in the range [0, max).
concurrent_queue<int> carmichaels;

// Holds the prime numbers that are in the range  [0, sqrt(max)).
concurrent_vector<int> primes;

// Generate the set of Carmichael numbers and the set of prime numbers 
// in parallel.
parallel_invoke(
   [&] {
      parallel_for(0, max, [&](int i) {
         if (is_carmichael(i)) {
            carmichaels.push(i);
         }
      });
   },
   [&] {
      parallel_for(0, int(sqrt(static_cast<double>(max))), [&](int i) {
         if (is_prime(i)) {
            primes.push_back(i);
         }
      });
   });

Následující příklad ukazuje prime_factors_of funkce, která používá zkušební divize najít všechny prvotní faktory dané hodnoty.

Tato funkce využívá concurrency::parallel_for_each algoritmu pro iteraci kolekci prvočísla.concurrent_vector Objekt umožňuje paralelní smyčku souběžně přidat primární faktory k výsledku.

// Finds all prime factors of the given value.
concurrent_vector<int> prime_factors_of(int n, 
   const concurrent_vector<int>& primes)
{
   // Holds the prime factors of n.
   concurrent_vector<int> prime_factors;

   // Use trial division to find the prime factors of n. 
   // Every prime number that divides evenly into n is a prime factor of n. 
   const int max = sqrt(static_cast<double>(n));
   parallel_for_each(begin(primes), end(primes), [&](int prime)
   {
      if (prime <= max)
      {         
         if ((n % prime) == 0)
            prime_factors.push_back(prime);
      }
   });

   return prime_factors;
}

Tento příklad zpracuje každý prvek ve frontě Carmichael čísla voláním prime_factors_of funkce pro výpočet jeho prvotní faktory.Skupina úloh používá k provedení této práce současně.Další informace o skupinách úloh, naleznete v Funkční paralelismus (Concurrency Runtime).

Tento příklad vytiskne hlavní faktory pro každé číslo Carmichael, pokud má dané číslo více než čtyři hlavní faktory.

// Use a task group to compute the prime factors of each  
// Carmichael number in parallel.
task_group tasks;

int carmichael;
while (carmichaels.try_pop(carmichael))
{
   tasks.run([carmichael,&primes] 
   {
      // Compute the prime factors.
      auto prime_factors = prime_factors_of(carmichael, primes);

      // For brevity, print the prime factors for the current number only 
      // if there are more than 4. 
      if (prime_factors.size() > 4)
      {
         // Sort and then print the prime factors.
         sort(begin(prime_factors), end(prime_factors));

         wstringstream ss;
         ss << L"Prime factors of " << carmichael << L" are:";

         for_each (begin(prime_factors), end(prime_factors), 
            [&](int prime_factor) { ss << L' ' << prime_factor; });
         ss << L'.' << endl;

         wcout << ss.str();
      }
   });
}

// Wait for the task group to finish.
tasks.wait();

Následující kód ukazuje kompletní příklad, který používá paralelní kontejnery pro výpočet přednostní faktory Carmichael čísel.

// carmichael-primes.cpp 
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_queue.h>
#include <concurrent_vector.h>
#include <iostream>
#include <sstream>

using namespace concurrency;
using namespace std;

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

// Determines whether the input value is a Carmichael number. 
bool is_carmichael(const int n) 
{
   if (n < 2) 
      return false;

   int k = n;
   for (int i = 2; i <= k / i; ++i) 
   {
      if (k % i == 0) 
      {
         if ((k / i) % i == 0) 
            return false;
         if ((n - 1) % (i - 1) != 0)
            return false;
         k /= i;
         i = 1;
      }
   }
   return k != n && (n - 1) % (k - 1) == 0;
}

// Finds all prime factors of the given value.
concurrent_vector<int> prime_factors_of(int n, 
   const concurrent_vector<int>& primes)
{
   // Holds the prime factors of n.
   concurrent_vector<int> prime_factors;

   // Use trial division to find the prime factors of n. 
   // Every prime number that divides evenly into n is a prime factor of n. 
   const int max = sqrt(static_cast<double>(n));
   parallel_for_each(begin(primes), end(primes), [&](int prime)
   {
      if (prime <= max)
      {         
         if ((n % prime) == 0)
            prime_factors.push_back(prime);
      }
   });

   return prime_factors;
}

int wmain()
{
   // The maximum number to test. 
   const int max = 10000000;

   // Holds the Carmichael numbers that are in the range [0, max).
   concurrent_queue<int> carmichaels;

   // Holds the prime numbers that are in the range  [0, sqrt(max)).
   concurrent_vector<int> primes;

   // Generate the set of Carmichael numbers and the set of prime numbers 
   // in parallel.
   parallel_invoke(
      [&] {
         parallel_for(0, max, [&](int i) {
            if (is_carmichael(i)) {
               carmichaels.push(i);
            }
         });
      },
      [&] {
         parallel_for(0, int(sqrt(static_cast<double>(max))), [&](int i) {
            if (is_prime(i)) {
               primes.push_back(i);
            }
         });
      });

   // Use a task group to compute the prime factors of each  
   // Carmichael number in parallel.
   task_group tasks;

   int carmichael;
   while (carmichaels.try_pop(carmichael))
   {
      tasks.run([carmichael,&primes] 
      {
         // Compute the prime factors.
         auto prime_factors = prime_factors_of(carmichael, primes);

         // For brevity, print the prime factors for the current number only 
         // if there are more than 4. 
         if (prime_factors.size() > 4)
         {
            // Sort and then print the prime factors.
            sort(begin(prime_factors), end(prime_factors));

            wstringstream ss;
            ss << L"Prime factors of " << carmichael << L" are:";

            for_each (begin(prime_factors), end(prime_factors), 
               [&](int prime_factor) { ss << L' ' << prime_factor; });
            ss << L'.' << endl;

            wcout << ss.str();
         }
      });
   }

   // Wait for the task group to finish.
   tasks.wait();
}

Tento příklad vytvoří následující vzorový výstup.

  

Probíhá kompilace kódu

Zkopírovat ukázkový kód a vložit jej do projektu sady Visual Studio nebo vložit do souboru s názvem carmichael-primes.cpp a potom spusťte následující příkaz v okně Příkazový řádek Visual Studio.

cl.exe /EHsc carmichael-primes.cpp

Viz také

Referenční dokumentace

concurrent_vector – třída

concurrent_queue – třída

parallel_invoke – funkce

parallel_for – funkce

task_group – třída

Koncepty

Paralelní kontejnery a objekty

Funkční paralelismus (Concurrency Runtime)