[tbb] concurrent_hash_map

2014. 6. 11. 10:16C++

http://sweeper.egloos.com/3053914



TBB Containers - concurrent_hash_map Intel TBB




1. 주요 특징
  • count, find, insert, erase 동작은 쓰레드 세이프하다.
  • count, find, insert, erase는 기존의 iterator를 무효화시킬 수 있다.

  • count, find, insert, erase를 제외한 모든 메써드가 쓰레드 세이프하지 않다.
  • 즉, 삽입/삭제가 일어날 수 있는 도중의 이터레이션이 쓰레드 세이프 하지 않다.

  • 러 쓰레드에서의 concurrent access를 위해 accessor라는 녀석을 사용한다.
  • accessor는 reader-writer spin lock을 사용하며, find, insert, erase에 사용된다.

map 자료 구조의 주요 동작 (삽입/조회/삭제/순회) 중 순회 기능이 쓰레드 세이프하지 않다.
따라서, 삽입/조회/삭제 뿐 아니라, 이터레이션 역시 주요 기능 중 하나라면, 아쉽지만 락을 사용하는 방식으로 전환해야 한다.

아래 표는 hash_map의 주요 함수들에 대해 쓰레드 세이프 여부에 대해 정리한 것이다.

메서드

 thread_safe

메서드 

 thread_safe

 메서드 

 thread_safe

count

O

find

O

insert

O

erase

O

get_allocator

X

swap

X

begin

X

cbegin

X

end

X

cend

X

equal_range

X

size

X

max_size

X

empty

X

bucket_count

X

rehash

X

clear

X





2. 샘플 코드

  1. #include <iostream>
  2. #include <algorithm>
  3. #include <tbb/parallel_for.h>
  4. #include <tbb/concurrent_hash_map.h>
  5.  
  6. int _tmain(int argc, _TCHAR* argv[])
  7. {
  8.     tbb::concurrent_hash_map<charint> map;
  9.  
  10.     // 멀티쓰레드 환경에서의 삽입 테스트를 위해 parallel_for 사용
  11.     tbb::parallel_for(010[&] (int i)
  12.     {
  13.         char key = 'a' + (% 9);
  14.         int value = i;
  15.  
  16.         // concurrent access를 위해 accessor 사용
  17.         tbb::concurrent_hash_map<charint>::accessor a;
  18.  
  19.         // insert시 accessor::lock (spin rw mutex)
  20.         // accessor는 writer lock의 개념
  21.         if (map.insert(a, key))
  22.         {
  23.             a->second = value;
  24.             // a.release();
  25.         }
  26.  
  27.         // 위에서 a.release()를 명시적으로 호출하지 않아도,
  28.         // accessor는 scoped lock 형태로 구현되어 있기에,
  29.         // 여기에서 accessor가 소멸되면서 암묵적인 accessor::release 수행
  30.     });
  31.  
  32.     tbb::parallel_for(010[&] (int i)
  33.     {
  34.         char key = 'a' + (% 9);
  35.  
  36.         // const_accessor 사용에 주목
  37.         tbb::concurrent_hash_map<charint>::const_accessor a;
  38.  
  39.         // find시 const_accessor::lock (spin rw mutex)
  40.         // const_accessor는 reader lock의 개념
  41.         if (map.find(a, key))
  42.         {
  43.             std::cout << "Found key:" << key << std::endl;
  44.         }
  45.     });
  46.  
  47.     tbb::parallel_for(010[&] (int i)
  48.     {
  49.         char key = 'a' + (% 9);
  50.  
  51.         tbb::concurrent_hash_map<charint>::accessor a;
  52.         if (map.erase(key))
  53.         {
  54.             std::cout << "Erased key:" << key << std::endl;
  55.         }
  56.     });
  57.  
  58.     return 0;
  59. }