정보
요청한 주제가 아래에 표시됩니다. 그러나 이 주제는 이 라이브러리에 포함되지 않습니다.

방법: combinable을 사용하여 성능 개선

이 예제에서는 concurrency::combinable 클래스를 사용하여 std::array 개체에서 소수의 합계를 계산하는 방법을 보여 줍니다. combinable 클래스는 공유 상태를 제거하여 성능을 향상시킵니다.

팁

경우에 따라서는 병렬 맵 (concurrency::parallel_transform)과 감소 (동시성:: parallel_reduce)를 통해 combinable 를 넘는 성능 향상을 제공할 수 있습니다. 매핑 과 작업을 줄여 같은 결과를 생성하는 예제를 보려면, 병렬 알고리즘을 참조하십시오.

다음 예제에서는 std::accumulate 함수를 사용하여 배열에서 소수 요소의 합계를 계산합니다. 이 예제에서 aarray 개체이고 is_prime 함수는 입력 값이 소수인지 여부를 확인합니다.


prime_sum = accumulate(begin(a), end(a), 0, [&](int acc, int i) {
   return acc + (is_prime(i) ? i : 0);
});


다음 예제에서는 이전 예제를 병렬화하는 간단한 방법을 보여 줍니다. 이 예제에서는 concurrency::parallel_for_each 알고리즘을 사용하여 배열을 병렬로 처리하고 concurrency::critical_section 개체를 사용하여 prime_sum 변수에 대한 액세스를 동기화합니다. 공유 리소스를 사용할 수 있을 때까지 각 스레드가 기다려야 하므로 이 예제를 확장하지 않습니다.


critical_section cs;
prime_sum = 0;
parallel_for_each(begin(a), end(a), [&](int i) {
   cs.lock();
   prime_sum += (is_prime(i) ? i : 0);
   cs.unlock();
});


다음 예제에서는 combinable 개체를 사용하여 이전 예제의 성능을 향상시킵니다. 이 예제에서는 동기화 개체를 사용할 필요가 없으며 combinable 개체를 사용하여 각 스레드에서 개별적으로 작업을 수행할 수 있으므로 확장됩니다.

일반적으로 combinable 개체는 두 단계로 사용됩니다. 먼저 작업을 병렬로 수행하여 세분화된 일련의 계산을 만듭니다. 그런 다음 계산을 최종 결과로 결합하거나 줄입니다. 이 예제에서는 concurrency::combinable::local 메서드를 사용하여 로컬 합계에 대한 참조를 가져옵니다. 그런 다음 concurrency::combinable::combine 메서드 및 std::plus 개체를 사용하여 로컬 계산을 최종 결과로 결합합니다.


combinable<int> sum;
parallel_for_each(begin(a), end(a), [&](int i) {
   sum.local() += (is_prime(i) ? i : 0);
});
prime_sum = sum.combine(plus<int>());


다음 전체 예제에서는 소수의 합계를 연속 및 병렬 방식으로 모두 계산합니다. 또한 두 계산을 모두 수행하는 데 필요한 시간을 콘솔에 출력합니다.


// parallel-sum-of-primes.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <array>
#include <numeric>
#include <iostream>

using namespace concurrency;
using namespace std;

// Calls the provided work function and returns the number of milliseconds 
// that it takes to call that function.
template <class Function>
__int64 time_call(Function&& f)
{
   __int64 begin = GetTickCount();
   f();
   return GetTickCount() - begin;
}

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

int wmain()
{   
   // Create an array object that contains 200000 integers.
   array<int, 200000> a;

   // Initialize the array such that a[i] == i.
   iota(begin(a), end(a), 0);

   int prime_sum;
   __int64 elapsed;

   // Compute the sum of the numbers in the array that are prime.
   elapsed = time_call([&] {
      prime_sum = accumulate(begin(a), end(a), 0, [&](int acc, int i) {
         return acc + (is_prime(i) ? i : 0);
      });
   });   
   wcout << prime_sum << endl;   
   wcout << L"serial time: " << elapsed << L" ms" << endl << endl;

   // Now perform the same task in parallel.
   elapsed = time_call([&] {
      combinable<int> sum;
      parallel_for_each(begin(a), end(a), [&](int i) {
         sum.local() += (is_prime(i) ? i : 0);
      });
      prime_sum = sum.combine(plus<int>());
   });
   wcout << prime_sum << endl;
   wcout << L"parallel time: " << elapsed << L" ms" << endl << endl;
}


다음 샘플은 프로세서가 4개인 컴퓨터에 대한 출력입니다.

            
              1709600813
직렬 시간: 6178 ms

1709600813
병렬 시간: 1638 ms
            
          

코드를 컴파일하려면 코드를 복사한 다음, Visual Studio 프로젝트 또는 parallel-sum-of-primes.cpp 파일에 붙여넣고 Visual Studio 명령 프롬프트 창에서 다음 명령을 실행합니다.

cl.exe /EHsc parallel-sum-of-primes.cpp

매핑과 작업을 줄여 동일한 결과 생성하는 예제를 보려면 병렬 알고리즘을 확인하십시오.

커뮤니티 추가 항목

표시:
© 2014 Microsoft