Aracılığıyla paylaş


Nasıl yapılır: Etkinliği Arttırmak için Paralel Kapsayıcılar Kullanma

Bu konu, paralel kapsayıcıları kullanarak verileri paralel olarak verimli bir şekilde depolamayı ve bunlara erişmeyi gösterir.

Örnek kod, asal ve Carmichael sayı kümesini paralel olarak hesaplar. Ardından, her Carmichael numarası için kod bu sayının asal faktörlerini hesaplar.

Örnek: Giriş değerinin asal sayı olup olmadığını belirleme

Aşağıdaki örnekte, giriş değerinin is_prime asal sayı olup olmadığını belirleyen işlev ve giriş değerinin is_carmichael Carmichael sayı olup olmadığını belirleyen işlev gösterilmektedir.

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

Örnek: Asal ve Carmichael sayılarını hesaplama

Aşağıdaki örnek, asal ve Carmichael sayı kümelerini hesaplamak için ve is_carmichael işlevlerini kullanıris_prime. Örnek, her kümeyi paralel olarak hesaplamak için algoritmalar için concurrency::p arallel_invoke ve concurrency::p arallel_kullanır. Paralel algoritmalar hakkında daha fazla bilgi için bkz . Paralel Algoritmalar.

Bu örnekte, carmichael numaraları kümesini tutmak için eşzamanlılık::concurrent_queue nesnesi kullanılır çünkü bu nesne daha sonra iş kuyruğu olarak kullanılır. Asal sayı kümesini tutmak için eşzamanlılık::concurrent_vector nesnesini kullanır çünkü daha sonra asal faktörleri bulmak için bu kümede yinelenir.

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

Örnek: Belirli bir değerin tüm asal faktörlerini bulma

Aşağıdaki örnek, verilen değerin prime_factors_of tüm temel faktörlerini bulmak için deneme bölümünü kullanan işlevini gösterir.

Bu işlev, asal sayıların koleksiyonunda yineleme yapmak için concurrency::p arallel_for_each algoritmasını kullanır. nesnesi, concurrent_vector paralel döngünün eş zamanlı olarak sonuca asal faktörler eklemesini sağlar.

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

Örnek: Carmichael numaraları kuyruğundaki her öğeyi işler

Bu örnek, carmichael numaraları kuyruğundaki her öğeyi prime_factors_of , birincil faktörlerini hesaplamak için işlevini çağırarak işler. Bu işi paralel olarak gerçekleştirmek için bir görev grubu kullanır. Görev grupları hakkında daha fazla bilgi için bkz . Görev Paralelliği.

Bu örnekte, dörtten fazla asal faktör varsa her Carmichael sayısı için asal faktörler yazdırılır.

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

Örnek: Tamamlanan paralel kapsayıcı kodu örneği

Aşağıdaki kod, Carmichael sayılarının temel faktörlerini hesaplamak için paralel kapsayıcılar kullanan tam örneği gösterir.

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

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

Prime factors of 9890881 are: 7 11 13 41 241.
Prime factors of 825265 are: 5 7 17 19 73.
Prime factors of 1050985 are: 5 13 19 23 37.

Kod Derleniyor

Örnek kodu kopyalayıp bir Visual Studio projesine yapıştırın veya adlı carmichael-primes.cpp bir dosyaya yapıştırın ve ardından bir Visual Studio Komut İstemi penceresinde aşağıdaki komutu çalıştırın.

cl.exe /EHsc carmichael-primes.cpp

Ayrıca bkz.

Paralel Kapsayıcılar ve Nesneler
Görev Paralelliği
concurrent_vector Sınıfı
concurrent_queue Sınıfı
parallel_invoke İşlevi
parallel_for İşlevi
task_group Sınıfı