다음을 통해 공유


병렬 컨테이너 및 개체

PPL(병렬 패턴 라이브러리)에는 스레드로부터 안전한 방식으로 요소에 액세스할 수 있도록 하는 몇 가지 컨테이너 및 개체가 포함되어 있습니다.

동시 컨테이너를 사용하면 가장 중요한 작업에 동시성이 보장된 방식으로 액세스할 수 있습니다.이러한 컨테이너의 기능은 STL(표준 템플릿 라이브러리)에서 제공하는 컨테이너와 유사합니다.예를 들어,는 concurrency::concurrent_vector 클래스와 유사한는 std::vector 제외 하 고는 클래스는 concurrent_vector 클래스를 사용 하면 동시에 요소를 추가 합니다.같은 컨테이너에 읽기 및 쓰기 권한이 둘 다 필요한 병렬 코드가 있는 경우 동시 컨테이너를 사용하십시오.

동시 개체는 구성 요소 사이에서 동시에 공유됩니다.동시 개체의 상태를 병렬로 계산하는 프로세스는 같은 상태를 순차적으로 계산하는 다른 프로세스와 같은 결과가 나타납니다.Concurrency::combinable 클래스 동시 개체 형식의 한 가지 예입니다.combinable 클래스를 사용하면 계산을 병렬로 수행한 다음, 이러한 계산을 최종 결과로 결합할 수 있습니다.뮤텍스와 같은 동기화 메커니즘을 사용하여 공유 변수 또는 리소스에 대한 액세스를 동기화해야 하는 경우 동시 개체를 사용하십시오.

단원

이 항목에서는 다음과 같은 병렬 컨테이너 및 개체에 대해 자세히 설명합니다.

동시 컨테이너

  • concurrent_vector 클래스

    • concurrent_vector와 vector의 차이

    • 동시성 보장 작업

    • 예외 안전성

  • concurrent_queue 클래스

    • concurrent_queue와 queue의 차이

    • 동시성 보장 작업

    • 반복기 지원

  • concurrent_unordered_map 클래스

    • 사이의 차이 concurrent_unordered_map 및 unordered_map

    • 동시성 보장 작업

  • concurrent_unordered_multimap 클래스

  • concurrent_unordered_set 클래스

  • concurrent_unordered_multiset 클래스

동시 개체

  • combinable 클래스

    • 메서드 및 기능

    • 예제

concurrent_vector 클래스

Concurrency::concurrent_vector 클래스인 것 처럼 시퀀스 컨테이너 클래스의 std::vector 클래스, 해당 요소에 임의로 액세스할 수 있습니다.concurrent_vector 클래스를 사용하면 동시성이 보장된 방식으로 추가 및 요소 액세스 작업을 수행할 수 있습니다.추가 작업은 기존 포인터 또는 반복기를 무효화하지 않습니다.반복기 액세스 및 트래버스 작업도 동시성이 보장됩니다.

Dd504906.collapse_all(ko-kr,VS.110).gifconcurrent_vector와 vector의 차이

concurrent_vector 클래스는 vector 클래스와 매우 유사합니다.concurrent_vector 개체에 대한 추가, 요소 액세스 및 반복기 액세스 작업의 복잡성은 vector 개체의 경우와 동일합니다.다음은 concurrent_vectorvector와 다른 점에 대한 설명입니다.

  • concurrent_vector 개체에 대한 추가, 요소 액세스, 반복기 액세스 및 반복기 트래버스 작업은 동시성이 보장됩니다.

  • concurrent_vector 개체의 끝에만 요소를 추가할 수 있습니다.concurrent_vector 클래스는 insert 메서드를 제공하지 않습니다.

  • concurrent_vector 개체에 추가하는 경우 이 개체에는 의미 체계 이동이 사용되지 않습니다.

  • concurrent_vector 클래스는 erase 또는 pop_back 메서드를 제공하지 않습니다.vector와 마찬가지로 clear 메서드를 사용하여 concurrent_vector 개체에서 모든 요소를 제거합니다.

  • concurrent_vector 클래스는 요소를 메모리에 연속적으로 저장하지 않습니다.따라서 배열을 사용할 수 있는 모든 방법으로 concurrent_vector 클래스를 사용할 수 없습니다.예를 들어 concurrent_vector 형식의 v라는 변수가 있는 경우 &v[0]+2 식을 실행하면 정의되지 않은 동작이 발생합니다.

  • concurrent_vector 클래스는 grow_bygrow_to_at_least 메서드를 정의합니다.이러한 메서드는 동시성이 보장된다는 점을 제외하면 resize 메서드와 유사합니다.

  • concurrent_vector 개체는 추가하거나 크기를 조정할 때 해당 요소를 재배치하지 않습니다.이렇게 하면 기존 포인터 및 반복기에서 동시 작업 중에 유효한 상태를 유지할 수 있습니다.

  • 런타임에서는 bool 형식에 대한 특수화된 버전의 concurrent_vector를 정의하지 않습니다.

Dd504906.collapse_all(ko-kr,VS.110).gif동시성 보장 작업

concurrent_vector 개체에 추가하거나 개체의 크기를 증가시키고 concurrent_vector 개체의 요소에 액세스하는 모든 메서드는 동시성이 보장됩니다.이 규칙이 적용되지 않는 메서드는 resize뿐입니다.

다음 표에서는 동시성이 보장되는 일반적인 concurrent_vector 메서드와 연산자를 보여 줍니다.

at

end

operator[]

begin

front

push_back

back

grow_by

rbegin

capacity

grow_to_at_least

rend

empty

max_size

size

런타임 호환 STL, 예를 들어, 제공 하는 작업 reserve, 동시성에 적합 하지 않습니다.다음 표에서는 동시성이 보장되지 않는 일반적인 메서드와 연산자를 보여 줍니다.

assign

reserve

clear

resize

operator=

shrink_to_fit

기존 요소의 값을 수정하는 작업은 동시성이 보장되지 않습니다.같은 데이터 요소에 대한 동시 읽기 및 쓰기 권한을 동기화하려면 reader_writer_lock 개체와 같은 동기화 개체를 사용합니다.동기화 개체에 대한 자세한 내용은 동기화 데이터 구조를 참조하십시오.

vector를 사용하는 기존 코드를 concurrent_vector를 사용하도록 변환하는 경우 동시 작업을 수행하면 응용 프로그램의 동작이 변경될 수 있습니다.예를 들어 concurrent_vector 개체에 대해 동시에 두 작업을 수행하는 다음 프로그램을 가정해 봅니다.첫 번째 작업은 concurrent_vector 개체에 요소를 추가합니다.두 번째 작업은 동일한 개체에 있는 모든 요소의 합계를 계산합니다.

// parallel-vector-sum.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_vector.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain()
{
   // Create a concurrent_vector object that contains a few
   // initial elements.
   concurrent_vector<int> v;
   v.push_back(2);
   v.push_back(3);
   v.push_back(4);

   // Perform two tasks in parallel.
   // The first task appends additional elements to the concurrent_vector object.
   // The second task computes the sum of all elements in the same object.

   parallel_invoke(
      [&v] { 
         for(int i = 0; i < 10000; ++i)
         {
            v.push_back(i);
         }
      },
      [&v] {
         combinable<int> sums;
         for(auto i = begin(v); i != end(v); ++i) 
         {
            sums.local() += *i;
         }     
         wcout << L"sum = " << sums.combine(plus<int>()) << endl;
      }
   );
}

end 메서드는 동시성이 보장되지만 push_back 메서드에 대한 동시 호출 결과 end에서 반환되는 값이 변경됩니다.반복기에서 트래버스하는 요소의 수가 결정되지 않습니다.따라서 이 프로그램을 실행할 때마다 다른 결과가 생성될 수 있습니다.

Dd504906.collapse_all(ko-kr,VS.110).gif예외 안전성

증가 또는 할당 작업에서 예외가 throw되면 concurrent_vector 개체의 상태가 유효하지 않게 됩니다.상태가 유효하지 않은 concurrent_vector 개체의 동작은 별도로 지정된 경우가 아니면 정의되지 않습니다.그러나 소멸자는 개체의 상태가 유효하지 않더라도 해당 개체에서 할당하는 메모리를 항상 해제합니다.

벡터 요소 _Ty의 데이터 형식은 다음과 같은 요구 사항을 충족시켜야 합니다.그렇지 않으면 concurrent_vector 클래스의 동작이 정의되지 않습니다.

  • 소멸자는 throw하지 않아야 합니다.

  • 기본 또는 복사 생성자에서 throw하는 경우 소멸자는 virtual 키워드를 사용하여 선언되지 않아야 하며 0으로 초기화된 메모리에서 올바르게 동작해야 합니다.

Top

concurrent_queue 클래스

Concurrency::concurrent_queue 처럼 클래스는 std::queue 클래스, 그 앞에 액세스 하 고 요소를 백업할 수 있습니다.concurrent_queue 클래스를 사용하면 동시성이 보장된 방식으로 큐에 대기시키거나 큐에서 제거하는 작업을 수행할 수 있습니다.또한 concurrent_queue 클래스는 동시성이 보장되지 않는 반복기 지원도 제공합니다.

Dd504906.collapse_all(ko-kr,VS.110).gifconcurrent_queue와 queue의 차이

concurrent_queue 클래스는 queue 클래스와 매우 유사합니다.다음은 concurrent_queuequeue와 다른 점에 대한 설명입니다.

  • concurrent_queue 개체에 대한 큐에 대기시키기 및 큐에서 제거 작업은 동시성이 보장됩니다.

  • concurrent_queue 클래스는 동시성이 보장되지 않는 반복기 지원을 제공합니다.

  • concurrent_queue 클래스는 front 또는 pop 메서드를 제공하지 않습니다.concurrent_queue 클래스는 try_pop 메서드를 정의하여 이러한 메서드를 대체합니다.

  • concurrent_queue 클래스는 back 메서드를 제공하지 않습니다.따라서 큐의 끝을 참조할 수 없습니다.

  • concurrent_queue 클래스는 size 메서드 대신 unsafe_size 메서드를 제공합니다.unsafe_size 메서드는 동시성이 보장되지 않습니다.

Dd504906.collapse_all(ko-kr,VS.110).gif동시성 보장 작업

concurrent_queue 개체에서 큐에 대기시키거나 큐에서 제거하는 모든 메서드는 동시성이 보장됩니다.

다음 표에서는 동시성이 보장되는 일반적인 concurrent_queue 메서드와 연산자를 보여 줍니다.

empty

push

get_allocator

try_pop

empty 메서드는 동시성이 보장되지만 동시 작업을 수행하면 empty 메서드가 반환되기 전에 큐가 확장 또는 축소될 수 있습니다.

다음 표에서는 동시성이 보장되지 않는 일반적인 메서드와 연산자를 보여 줍니다.

clear

unsafe_end

unsafe_begin

unsafe_size

Dd504906.collapse_all(ko-kr,VS.110).gif반복기 지원

concurrent_queue는 동시성이 보장되지 않는 반복기를 제공합니다.디버깅 용도로만 이러한 반복기를 사용하는 것이 좋습니다.

concurrent_queue 반복기는 요소를 앞으로만 트래버스합니다.다음 표에서는 각 반복기에서 지원하는 연산자를 보여 줍니다.

Operator

설명

operator++

큐에서 다음 항목으로 이동합니다.이 연산자는 전위 증가 및 후위 증가 의미 체계를 둘 다 제공하도록 오버로드됩니다.

operator*

현재 항목에 대한 참조를 검색합니다.

operator->

현재 항목에 대한 포인터를 검색합니다.

Top

concurrent_unordered_map 클래스

Concurrency::concurrent_unordered_map 클래스인 처럼는 결합형 컨테이너 클래스의 std::unordered_map 클래스, 가변 길이 형식의 요소 시퀀스 제어 std::pair < const 키, Ty >.사전 키 / 값 쌍을 추가 하거나 키 값을 찾을 수 부호가 지도 생각할.이 클래스는 여러 개의 스레드나 작업을 동시에 공유 하는 컨테이너에 액세스를, 삽입 또는 업데이트 하는 경우에 유용 합니다.

다음 예제에서는 사용 하는 기본 구조를 보여 줍니다. concurrent_unordered_map.['A', ' i'] 범위에서 문자 키를 삽입 하는이 예제입니다.작업 순서 결정 이므로 각 키에 대 한 최종 값도 결정있지 않습니다.그러나 안전 하 게 삽입을 병렬로 수행할 수 있습니다.

// unordered-map-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_map.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the map in parallel.

    concurrent_unordered_map<char, int> map; 

    parallel_for(0, 1000, [&map](int i) {
        char key = 'a' + (i%9); // Geneate a key in the range [a,i].
        int value = i;          // Set the value to i.
        map.insert(make_pair(key, value));
    });

    // Print the elements in the map.
    for_each(begin(map), end(map), [](const pair<char, int>& pr) {
        wcout << L"[" << pr.first << L", " << pr.second << L"] ";
    });
}
/* Sample output:
    [e, 751] [i, 755] [a, 756] [c, 758] [g, 753] [f, 752] [b, 757] [d, 750] [h, 754]
*/

사용 하는 예를 들어 concurrent_unordered_map 지도 수행 하 고 작업을 동시에 줄이는을 참조 하십시오. 방법: 매핑 수행 및 병렬 작업 줄이기.

Dd504906.collapse_all(ko-kr,VS.110).gif사이의 차이 concurrent_unordered_map 및 unordered_map

concurrent_unordered_map 클래스는 unordered_map 클래스와 매우 유사합니다.다음은 concurrent_unordered_mapunordered_map와 다른 점에 대한 설명입니다.

  • The erase, bucket, bucket_count, and bucket_size methods are named unsafe_erase, unsafe_bucket, unsafe_bucket_count, and unsafe_bucket_size, respectively.unsafe_ 명명 규칙을 나타내는 이러한 메서드 동시성이 보장 되지 않습니다.안전성에 대 한 자세한 내용은 참조 하십시오. 동시성 안전한 작업.

  • Insert 작업이 기존 포인터 또는 반복기를 무효화 하지 않으며는 맵에 이미 존재 하는 항목의 순서를 변경 하지 마십시오.삽입 및 이동 작업이 동시에 발생할 수 있습니다.

  • concurrent_unordered_map지원 반복만을 전달합니다.

  • 삽입 무효화 하거나 반복기에서 반환 되는 업데이트 하지 equal_range.삽입 범위 끝에 다른 항목을 추가할 수 있습니다.Begin 반복기와 같은 항목을 가리킵니다.

방법이의 교착 상태를 방지 하는 데 concurrent_unordered_map 메모리 할당자, 해시 함수, 또는 다른 사용자 정의 코드를 호출할 때 잠금을 유지 합니다.또한, 해시 함수에는 항상 동일한 키 동일한 값으로 계산 되어야 합니다.최적의 해시 함수 키 해시 코드 공간 전체를 균일 하 게 배포합니다.

Dd504906.collapse_all(ko-kr,VS.110).gif동시성 보장 작업

concurrent_unordered_map 클래스 동시성 안전한 삽입 및 요소 액세스 작업을 수 있습니다.삽입 작업은 기존 포인터 또는 반복기를 무효화 하지 않습니다.반복기 액세스 및 트래버스 작업도 동시성이 보장됩니다.다음 표에서 자주 사용 되는 보여 줍니다. concurrent_unordered_map 메서드 및 동시성이 보장 되는 연산자입니다.

at

count

find

key_eq

begin

empty

get_allocator

max_size

cbegin

end

hash_function

operator[]

cend

equal_range

삽입

size

하지만 count 메서드 호출 안전 하 게 실행 스레드를 동시에, 서로 다른 스레드에서 동시에 컨테이너에 새 값을 삽입 하면 다른 결과가 받을 수 있습니다.

다음 표에서 자주 사용 되는 메서드 및 동시성에 적합 하지 않은 연산자를 보여 줍니다.

clear

max_load_factor

rehash

load_factor

operator=

스왑

이러한 방법 외에 모든 메서드는 시작으로 unsafe_ 도 동시성에 적합 하지 않은.

Top

concurrent_unordered_multimap 클래스

Concurrency::concurrent_unordered_multimap 클래스의 유사한는 concurrent_unordered_map 같은 키에 매핑할 수 있는 여러 값을 허용을 제외 하 고 클래스입니다.또한 다릅니다 concurrent_unordered_map 를 사용할 수 있습니다.

  • Concurrent_unordered_multimap::insert 메서드 대신 반복기를 반환 합니다. std::pair<iterator, bool>.

  • concurrent_unordered_multimap 클래스는 제공 하지 않습니다 operator[] 나는 at 메서드.

다음 예제에서는 사용 하는 기본 구조를 보여 줍니다. concurrent_unordered_multimap.['A', ' i'] 범위에서 문자 키를 삽입 하는이 예제입니다.concurrent_unordered_multimap여러 값이 있는 키를 수 있습니다.

// unordered-multimap-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_map.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the map in parallel.

    concurrent_unordered_multimap<char, int> map; 

    parallel_for(0, 10, [&map](int i) {
        char key = 'a' + (i%9); // Geneate a key in the range [a,i].
        int value = i;          // Set the value to i.
        map.insert(make_pair(key, value));
    });

    // Print the elements in the map.
    for_each(begin(map), end(map), [](const pair<char, int>& pr) {
        wcout << L"[" << pr.first << L", " << pr.second << L"] ";
    });
}
/* Sample output:
    [e, 4] [i, 8] [a, 9] [a, 0] [c, 2] [g, 6] [f, 5] [b, 1] [d, 3] [h, 7]
*/

Top

concurrent_unordered_set 클래스

Concurrency::concurrent_unordered_set 클래스의 유사한는 concurrent_unordered_map 값을 키 / 값 쌍 대신 관리를 제외 하 고 클래스입니다.concurrent_unordered_set 클래스는 제공 하지 않습니다 operator[] 나는 at 메서드.

다음 예제에서는 사용 하는 기본 구조를 보여 줍니다. concurrent_unordered_set.['A', ' i'] 범위에서 문자 값을 삽입 하는이 예제입니다.안전 하 게 삽입을 병렬로 수행할 수 있습니다.

// unordered-set-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_set.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the set in parallel.

    concurrent_unordered_set<char> set; 

    parallel_for(0, 10000, [&set](int i) {
        set.insert('a' + (i%9)); // Geneate a value in the range [a,i].
    });

    // Print the elements in the set.
    for_each(begin(set), end(set), [](char c) {
        wcout << L"[" << c << L"] ";
    });
}
/* Sample output:
    [e] [i] [a] [c] [g] [f] [b] [d] [h]
*/

Top

concurrent_unordered_multiset 클래스

Concurrency::concurrent_unordered_multiset 클래스의 유사한는 concurrent_unordered_set 허용에 대 한 중복 값을 제외 하 고 클래스입니다.또한 다릅니다 concurrent_unordered_set 를 사용할 수 있습니다.

  • Concurrent_unordered_multiset::insert 메서드 대신 반복기를 반환 합니다. std::pair<iterator, bool>.

  • concurrent_unordered_multiset 클래스는 제공 하지 않습니다 operator[] 나는 at 메서드.

다음 예제에서는 사용 하는 기본 구조를 보여 줍니다. concurrent_unordered_multiset.['A', ' i'] 범위에서 문자 값을 삽입 하는이 예제입니다.concurrent_unordered_multiset값을 여러 번 발생할 수 있습니다.

// unordered-set-structure.cpp
// compile with: /EHsc
#include <ppl.h>
#include <concurrent_unordered_set.h>
#include <iostream>

using namespace concurrency;
using namespace std;

int wmain() 
{
    //
    // Insert a number of items into the set in parallel.

    concurrent_unordered_multiset<char> set; 

    parallel_for(0, 40, [&set](int i) {
        set.insert('a' + (i%9)); // Geneate a value in the range [a,i].
    });

    // Print the elements in the set.
    for_each(begin(set), end(set), [](char c) {
        wcout << L"[" << c << L"] ";
    });
}
/* Sample output:
    [e] [e] [e] [e] [i] [i] [i] [i] [a] [a] [a] [a] [a] [c] [c] [c] [c] [c] [g] [g]
    [g] [g] [f] [f] [f] [f] [b] [b] [b] [b] [b] [d] [d] [d] [d] [d] [h] [h] [h] [h]
*/

Top

combinable 클래스

Concurrency::combinable 세밀 한 계산을 수행 하 고 다음 이러한 계산의 최종 결과에 병합할 수 있도록 재사용 가능한, 스레드 로컬 저장소 클래스를 제공 합니다.combinable 개체를 환산(reduction) 변수로 생각할 수 있습니다.

combinable 클래스는 여러 스레드 또는 작업 사이에서 리소스가 공유되는 경우에 유용합니다.combinable 클래스를 사용하면 잠금이 필요 없는 방식으로 공유 리소스에 액세스할 수 있으므로 공유 상태를 제거할 수 있습니다.따라서 이 클래스는 여러 스레드에서 공유 데이터에 대한 액세스를 동기화할 때 뮤텍스와 같은 동기화 메커니즘 대신 사용할 수 있습니다.

Dd504906.collapse_all(ko-kr,VS.110).gif메서드 및 기능

다음 표에서는 combinable 클래스의 중요한 메서드 중 일부를 보여 줍니다.모든 combinable 클래스 메서드에 대한 자세한 내용은 combinable 클래스를 참조하십시오.

메서드

설명

local

현재 스레드 컨텍스트와 연결된 지역 변수에 대한 참조를 검색합니다.

clear

combinable 개체에서 모든 스레드 로컬 변수를 제거합니다.

combine

combine_each

제공된 combine 함수를 사용하여 모든 스레드 로컬 계산 집합에서 최종 값을 생성합니다.

combinable 클래스는 병합된 최종 결과에서 매개 변수화된 템플릿 클래스입니다.기본 생성자를 호출하는 경우 _Ty 템플릿 매개 변수 형식에는 기본 생성자 및 복사 생성자가 있어야 합니다._Ty 템플릿 매개 변수 형식에 기본 생성자가 없으면 초기화 함수를 매개 변수로 사용하는 오버로드된 버전의 생성자를 호출하십시오.

combine 또는 combine_each 메서드를 호출한 후 추가 데이터를 combinable 개체에 저장할 수 있습니다.combinecombine_each 메서드를 여러 번 호출할 수도 있습니다.combinable 개체의 로컬 값이 변경되지 않으면 combinecombine_each 메서드를 호출할 때마다 같은 결과가 나타납니다.

Dd504906.collapse_all(ko-kr,VS.110).gif예제

combinable 클래스를 사용하는 방법에 대한 예제를 보려면 다음 항목을 참조하십시오.

Top

관련 항목

참조

concurrent_vector 클래스

concurrent_queue 클래스

concurrent_unordered_map 클래스

concurrent_unordered_multimap 클래스

concurrent_unordered_set 클래스

concurrent_unordered_multiset 클래스

combinable 클래스