PPL(병렬 패턴 라이브러리)Parallel Patterns Library (PPL)

PPL(병렬 패턴 라이브러리)은 여러 애플리케이션을 동시에 개발할 수 있도록 편의성과 확장성을 높이는 명령적 프로그래밍 모델을 제공합니다.The Parallel Patterns Library (PPL) provides an imperative programming model that promotes scalability and ease-of-use for developing concurrent applications. PPL은 동시성 런타임의 예약 및 리소스 관리 구성 요소를 기반으로 빌드됩니다.The PPL builds on the scheduling and resource management components of the Concurrency Runtime. 또한 데이터에 대해 병렬로 작동하는 형식이 안전한 일반 알고리즘과 컨테이너를 제공함으로써 애플리케이션 코드와 기본 스레딩 메커니즘 간의 추상화 수준을 높입니다.It raises the level of abstraction between your application code and the underlying threading mechanism by providing generic, type-safe algorithms and containers that act on data in parallel. 또한 PPL을 사용하면 공유 상태 대신 사용할 수 있는 옵션을 제공하여 확장 가능한 애플리케이션을 개발할 수 있습니다.The PPL also lets you develop applications that scale by providing alternatives to shared state.

PPL은 다음과 같은 기능을 제공합니다.The PPL provides the following features:

  • 작업 병렬 처리: 동시에 여러 작업 항목 (작업)를 실행 하 여 Windows ThreadPool을 기반으로 작동 하는 메커니즘Task Parallelism: a mechanism that works on top of the Windows ThreadPool to execute several work items (tasks) in parallel

  • 병렬 알고리즘: 병렬로 데이터 컬렉션에 대해 작동 하는 동시성 런타임 위에서 작동 하는 일반 알고리즘Parallel algorithms: generic algorithms that works on top of the Concurrency Runtime to act on collections of data in parallel

  • 병렬 컨테이너 및 개체: 해당 요소에 안전한 동시 액세스를 제공 하는 일반 컨테이너 형식Parallel containers and objects: generic container types that provide safe concurrent access to their elements

예제Example

PPL은 유사한 프로그래밍 모델을 제공 합니다 C++ 표준 라이브러리입니다.The PPL provides a programming model that resembles the C++ Standard Library. 다음 예제에서는 PPL의 여러 기능을 보여 줍니다.The following example demonstrates many features of the PPL. 이 예제에서는 여러 피보나치 수를 직렬 및 병렬로 계산합니다.It computes several Fibonacci numbers serially and in parallel. 두 계산 작업을 std:: array 개체입니다.Both computations act on a std::array object. 또한 두 계산을 모두 수행하는 데 필요한 시간을 콘솔에 출력합니다.The example also prints to the console the time that is required to perform both computations.

직렬 버전을 사용 하 여는 C++ 표준 라이브러리 std:: for_each 배열을 트래버스하 고 알고리즘에서 결과 저장 하 고를 std:: vector 개체입니다.The serial version uses the C++ Standard Library std::for_each algorithm to traverse the array and stores the results in a std::vector object. 병렬 버전을 동일한 작업을 수행 하지만 PPL을 사용 하 여 concurrency:: parallel_for_each 알고리즘의 결과 저장 하 고는 concurrency:: concurrent_vector 개체입니다.The parallel version performs the same task, but uses the PPL concurrency::parallel_for_each algorithm and stores the results in a concurrency::concurrent_vector object. concurrent_vector 클래스를 사용하면 컨테이너에 대한 쓰기 권한을 동기화하지 않아도 각 루프 반복이 요소를 동시에 추가할 수 있습니다.The concurrent_vector class enables each loop iteration to concurrently add elements without the requirement to synchronize write access to the container.

parallel_for_each는 동시에 동작하므로 이 예제의 병렬 버전은 직렬 버전과 같은 결과를 생성하기 위해 concurrent_vector 개체를 정렬해야 합니다.Because parallel_for_each acts concurrently, the parallel version of this example must sort the concurrent_vector object to produce the same results as the serial version.

예제에서는 간단한 메서드를 사용하여 피보나치 수를 계산합니다. 그러나 이 방법은 동시성 런타임을 통해 긴 컴퓨팅의 성능을 개선하는 방법을 보여 줍니다.Note that the example uses a naïve method to compute the Fibonacci numbers; however, this method illustrates how the Concurrency Runtime can improve the performance of long computations.

// parallel-fibonacci.cpp
// compile with: /EHsc
#include <windows.h>
#include <ppl.h>
#include <concurrent_vector.h>
#include <array>
#include <vector>
#include <tuple>
#include <algorithm>
#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;
}

// Computes the nth Fibonacci number.
int fibonacci(int n)
{
   if(n < 2)
      return n;
   return fibonacci(n-1) + fibonacci(n-2);
}

int wmain()
{
   __int64 elapsed;

   // An array of Fibonacci numbers to compute.
   array<int, 4> a = { 24, 26, 41, 42 };

   // The results of the serial computation.
   vector<tuple<int,int>> results1;

   // The results of the parallel computation.
   concurrent_vector<tuple<int,int>> results2;

   // Use the for_each algorithm to compute the results serially.
   elapsed = time_call([&] 
   {
      for_each (begin(a), end(a), [&](int n) {
         results1.push_back(make_tuple(n, fibonacci(n)));
      });
   });   
   wcout << L"serial time: " << elapsed << L" ms" << endl;
   
   // Use the parallel_for_each algorithm to perform the same task.
   elapsed = time_call([&] 
   {
      parallel_for_each (begin(a), end(a), [&](int n) {
         results2.push_back(make_tuple(n, fibonacci(n)));
      });

      // Because parallel_for_each acts concurrently, the results do not 
      // have a pre-determined order. Sort the concurrent_vector object
      // so that the results match the serial version.
      sort(begin(results2), end(results2));
   });   
   wcout << L"parallel time: " << elapsed << L" ms" << endl << endl;

   // Print the results.
   for_each (begin(results2), end(results2), [](tuple<int,int>& pair) {
      wcout << L"fib(" << get<0>(pair) << L"): " << get<1>(pair) << endl;
   });
}

다음 샘플은 프로세서가 4개인 컴퓨터에 대한 출력입니다.The following sample output is for a computer that has four processors.

serial time: 9250 ms
parallel time: 5726 ms

fib(24): 46368
fib(26): 121393
fib(41): 165580141
fib(42): 267914296

루프의 각 반복을 완료하는 데 필요한 시간은 서로 다릅니다.Each iteration of the loop requires a different amount of time to finish. parallel_for_each의 성능은 마지막으로 완료되는 작업에 의해 제한됩니다.The performance of parallel_for_each is bounded by the operation that finishes last. 따라서 이 예제의 직렬 버전과 병렬 버전에서 성능이 일정하게 개선된다고 기대해서는 안 됩니다.Therefore, you should not expect linear performance improvements between the serial and parallel versions of this example.

제목Title 설명Description
작업 병렬 처리Task Parallelism PPL의 작업 및 작업 그룹 역할에 대해 설명합니다.Describes the role of tasks and task groups in the PPL.
병렬 알고리즘Parallel Algorithms parallel_forparallel_for_each와 같은 병렬 알고리즘을 사용하는 방법에 대해 설명합니다.Describes how to use parallel algorithms such as parallel_for and parallel_for_each.
병렬 컨테이너 및 개체Parallel Containers and Objects PPL에서 제공하는 여러 병렬 컨테이너 및 개체에 대해 설명합니다.Describes the various parallel containers and objects that are provided by the PPL.
PPL에서의 취소Cancellation in the PPL 병렬 알고리즘에서 수행 중인 작업을 취소하는 방법을 설명합니다.Explains how to cancel the work that is being performed by a parallel algorithm.
동시성 런타임Concurrency Runtime 병렬 프로그래밍을 간소화하는 동시성 런타임에 대해 설명하고 관련 항목의 링크를 제공합니다.Describes the Concurrency Runtime, which simplifies parallel programming, and contains links to related topics.