동시성 런타임 개요

업데이트: 2010년 7월

이 문서에서는 동시성 런타임에 대한 개요를 제공합니다. 그리고 동시성 런타임의 이점, 동시성 런타임의 용도 및 동시성 런타임의 구성 요소가 서로 또는 운영 체제 및 응용 프로그램과 상호 작용하는 방법에 대해 설명합니다.

단원

이 문서에는 다음과 같은 단원이 포함되어 있습니다.

  • 동시성 런타임이 중요한 이유

  • 아키텍처

  • C++ 람다 식

  • 요구 사항

동시성 런타임이 중요한 이유

동시성 런타임은 동시에 실행되는 응용 프로그램 및 응용 프로그램 구성 요소에 균일성과 예측 가능성을 제공합니다. 동시성 런타임의 이점 중 특히 협조적 작업 예약과 협조적 차단을 예로 들 수 있습니다.

동시성 런타임은 작업 가로채기 알고리즘을 구현하여 컴퓨팅 리소스 간에 효율적으로 작업을 분배하는 협조적 작업 스케줄러를 사용합니다. 예를 들어 모두 같은 런타임에서 관리되는 두 개의 스레드가 있는 응용 프로그램을 가정해 봅니다. 한 스레드에서 예약된 작업이 끝나면 이 스레드는 다른 스레드에서 작업을 오프로드할 수 있습니다. 이 메커니즘은 응용 프로그램의 전체 작업 부하를 분산시킵니다.

또한 동시성 런타임은 협조적 차단을 사용하는 동기화 기본 형식을 제공하여 리소스에 대한 액세스를 동기화합니다. 예를 들어 공유 리소스에 단독으로 액세스해야 하는 작업을 가정해 봅니다. 협조적으로 차단하면 런타임에서는 첫 번째 작업이 리소스를 기다리는 동안 남은 퀀텀을 사용하여 다른 작업을 수행할 수 있습니다. 이 메커니즘은 컴퓨팅 리소스를 최대한 사용할 수 있도록 활성화합니다.

[맨 위로 이동]

아키텍처

동시성 런타임은 PPL(병렬 패턴 라이브러리), 비동기 에이전트 라이브러리, 작업 스케줄러 및 리소스 관리자라는 4가지 구성 요소로 나눌 수 있습니다. 이러한 구성 요소는 운영 체제와 응용 프로그램 사이에 있습니다. 다음 그림에서는 운영 체제와 응용 프로그램 사이에서 동시성 런타임 구성 요소가 상호 작용하는 방식을 보여 줍니다.

동시성 런타임 아키텍처

동시성 런타임 아키텍처

동시성 런타임은 구성 가능성이 높습니다. 즉, 기존 기능을 결합하여 그 이상을 수행할 수 있습니다. 동시성 런타임은 하위 수준 구성 요소에서 병렬 알고리즘과 같은 많은 기능을 구성합니다.

또한 동시성 런타임은 협조적 차단을 사용하는 동기화 기본 형식을 제공하여 리소스에 대한 액세스를 동기화합니다. 이러한 동기화 기본 형식에 대한 자세한 내용은 동기화 데이터 구조를 참조하십시오.

다음 단원에서는 각 구성 요소에 대한 간략한 내용 및 해당 구성 요소를 사용하는 경우에 대해 설명합니다.

병렬 패턴 라이브러리

PPL(병렬 패턴 라이브러리)은 세부적인 병렬 처리를 수행하기 위해 일반적으로 사용되는 컨테이너 및 알고리즘을 제공합니다. PPL에서는 전체 컴퓨팅 리소스에서 데이터 집합 또는 컬렉션에 대한 계산을 분배하는 병렬 알고리즘을 제공하여 명령적 데이터 병렬 처리가 가능합니다. 또한 전체 컴퓨팅 리소스에서 여러 개의 독립 작업을 분배하는 작업 개체를 제공하여 작업 병렬 처리도 가능합니다.

로컬 계산을 병렬로 실행하면 더 유용한 경우 병렬 패턴 라이브러리를 사용합니다. 예를 들어 Concurrency::parallel_for 알고리즘을 사용하면 기존 for 루프를 병렬로 동작하도록 변환할 수 있습니다.

병렬 패턴 라이브러리에 대한 자세한 내용은 PPL(병렬 패턴 라이브러리)을 참조하십시오.

비동기 에이전트 라이브러리

비동기 에이전트 라이브러리(에이전트 라이브러리라고도 함)는 정교하지 않은 데이터 흐름 및 파이프라인 작업을 위해 행위자 기반 프로그래밍 모델과 메시지 전달 인터페이스를 둘 다 제공합니다. 비동기 에이전트를 사용하면 다른 구성 요소가 데이터를 기다리는 동안 작업을 수행하여 대기 시간을 생산적으로 활용할 수 있습니다.

서로 비동기적으로 통신하는 엔터티가 여러 개 있는 경우 에이전트 라이브러리를 사용합니다. 예를 들어 파일 또는 네트워크 연결에서 데이터를 읽은 다음, 메시지 전달 인터페이스를 사용하여 해당 데이터를 다른 에이전트에 보내는 에이전트를 만들 수 있습니다.

에이전트 라이브러리에 대한 자세한 내용은 비동기 에이전트 라이브러리를 참조하십시오.

작업 스케줄러

작업 스케줄러는 런타임에 작업을 예약하고 조정합니다. 작업 스케줄러는 협조적이며 작업 가로채기 알고리즘을 사용하여 처리 리소스를 최대한 활용합니다.

동시성 런타임은 인프라 정보를 관리할 필요가 없도록 기본 스케줄러를 제공합니다. 그러나 응용 프로그램의 품질 요구를 충족시키기 위해 사용자 고유의 일정 정책을 제공하거나 작업에 따라 특정 스케줄러를 연결할 수도 있습니다.

작업 스케줄러에 대한 자세한 내용은 작업 스케줄러(동시성 런타임)를 참조하십시오.

리소스 관리자

리소스 관리자의 역할은 프로세서와 메모리 같은 컴퓨팅 리소스를 관리하는 것입니다. 리소스 관리자는 런타임에 작업 부하가 변경되면 가장 효과적인 위치에 리소스를 할당하여 이에 응답합니다.

리소스 관리자는 컴퓨팅 리소스에 대해 추상적인 역할을 하며 주로 작업 스케줄러와 상호 작용합니다. 리소스 관리자를 사용하여 라이브러리 및 응용 프로그램의 성능을 세부적으로 조정할 수 있지만 일반적으로는 병렬 패턴 라이브러리, 에이전트 라이브러리 및 작업 스케줄러에서 제공하는 기능을 사용합니다. 이러한 라이브러리는 작업 부하가 변경될 경우 리소스 관리자를 사용하여 동적으로 리소스를 다시 분산시킵니다.

[맨 위로 이동]

C++ 람다 식

동시성 런타임에 정의되어 있는 대부분의 형식 및 알고리즘은 C++ 템플릿으로 구현됩니다. 이러한 형식 및 알고리즘의 일부는 작업을 수행하는 루틴을 매개 변수로 사용합니다. 이 매개 변수는 람다 함수, 함수 개체 또는 함수 포인터가 될 수 있습니다. 이러한 엔터티를 작업 함수 또는 작업 루틴이라고도 합니다.

람다 식은 병렬 처리를 위한 작업 함수를 정의하는 간결한 방식을 제공하므로 중요한 새로운 Visual C++ 언어 기능입니다. 함수 개체 및 함수 포인터를 사용하면 기존 코드에 동시성 런타임을 사용할 수 있습니다. 그러나 람다 식을 사용할 경우 안전성과 생산성 이점이 있으므로 새로운 코드를 작성하는 경우 람다 식을 사용하는 것이 좋습니다.

다음 예제에서는 여러 호출에서 람다 함수, 함수 개체 및 함수 포인터의 구문을 Concurrency::parallel_for_each 알고리즘과 비교합니다. parallel_for_each에 대한 각 호출에서 서로 다른 방법을 사용하여 std::array 개체에 있는 각 요소의 제곱을 계산합니다.

// comparing-work-functions.cpp
// compile with: /EHsc
#include <ppl.h>
#include <array>
#include <iostream>

using namespace Concurrency;
using namespace std;

// Function object (functor) class that computes the square of its input.
template<class Ty>
class SquareFunctor
{
public:
   void operator()(Ty& n) const
   {
      n *= n;
   }
};

// Function that computes the square of its input.
template<class Ty>
void square_function(Ty& n)
{
   n *= n;
}

int wmain()
{
   // Create an array object that contains 5 values.
   array<int, 5> values = { 1, 2, 3, 4, 5 };

   // Use a lambda function, a function object, and a function pointer to 
   // compute the square of each element of the array in parallel.

   // Use a lambda function to square each element.
   parallel_for_each(values.begin(), values.end(), [](int& n){n *= n;});

   // Use a function object (functor) to square each element.
   parallel_for_each(values.begin(), values.end(), SquareFunctor<int>());

   // Use a function pointer to square each element.
   parallel_for_each(values.begin(), values.end(), &square_function<int>);

   // Print each element of the array to the console.
   for_each(values.begin(), values.end(), [](int& n) { 
      wcout << n << endl;
   });
}

이 예제의 결과는 다음과 같습니다.

1
256
6561
65536
390625

C++의 람다 함수에 대한 자세한 내용은 Lambda Expressions in C++을 참조하십시오.

[맨 위로 이동]

요구 사항

다음 표에서는 동시성 런타임의 각 구성 요소와 연결된 헤더 파일을 보여 줍니다.

구성 요소

헤더 파일

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

ppl.h

concurrent_queue.h

concurrent_vector.h

비동기 에이전트 라이브러리

agents.h

작업 스케줄러

concrt.h

리소스 관리자

concrtrm.h

동시성 런타임은 Concurrency 네임스페이스에 선언됩니다. Concurrency::details 네임스페이스는 동시성 런타임 프레임워크를 지원하며 사용자 코드에서 직접 사용할 수 없습니다.

동시성 런타임은 CRT(C 런타임 라이브러리)의 일부로 제공됩니다. CRT를 사용하는 응용 프로그램을 빌드하는 방법에 대한 자세한 내용은 C Run-Time Libraries를 참조하십시오.

[맨 위로 이동]

변경 기록

날짜

변경 내용

이유

2010년 7월

내용을 다시 구성했습니다.

향상된 기능 관련 정보