intel Threading Building Block

멀티스레드 프로그래밍을 할 때마다 느끼는거지만, 실제로 겪게 되는 작업 중 상당수가 굉장히 저수준low-level의 무언가라고 느낄 때가 많다. 특히 일일이 락lock을 잡고 락 순서 문제를 해결하고, 각각의 동기화된 작업들을 연동도 시켜줘야하고, 특정 컨테이너들이 동시 접근할 때 어떻게 처리되어야 할지도 일일이 결정해줘야 한다. 이런 방식의 문제는 이렇게 일일이 안해주면 성능이 안나오는 경우가 있다 라는 것인데, 저수준 작업을 최대한 줄이고, C++ 패러다임에 맞는 형태로 프로그래밍하려는 노력으로 intel에서 제공하는 intel Threading Building Block (이하 intel TBB ) 이라는 라이브러리가 있다.

일단 intel TBB를 쓰면서 기본적으로 느끼게 되는 장점은,

  • C++ 패러다임으로 작성되어서 이질감이 없고1, STL에서 많이 겪어본 이터레이터(iterat
  • or) 패러다임을 이용합니다. 즉, template을 사용한 일반화 프로그래밍generic-programming이 주가 된다.
  • 스레드 보다 한단계 높은 추상화로 Task 를 제안하고, 스케쥴러가 이 것들을 실제 실행 중에 사용 가능한 CPU 코어 수에 맞춰서 이용하게 한다.
  • Iterator 개념을 약간 재귀적으로 재해석해서 많은 양의 데이터를 처리하는 - 특히 1차원 배열/2차원 배열 - 데 특화 되어있다.
  • User-level - 그러니까 kernel mode 전환 없이 사용가능한 - 동기화 객체들을 제공한다.
  • Task 기반의 intel TBB 스레드를 사용하지 않아도, 그냥 스레드 팩키지처럼 쓸 수 있다.
  • 심지어 이런 스레드를 쓰지 않고도 thread-safe한 generic container를 제공한다. (이게 가장 큰 장점!)
  • 다른 스레딩 팩키지와 혼합이 쉽다.

하지만 문제가 없는 것도 아니다. 내가 해야되는 멀티스레드 프로그래밍은 많은 양의 I/O를 수반하는데 intel TBB의 태스크 기반의 스케쥴링은 데이터가 많은 경우에 중점을 둔다. 그래서 내가 지금 직업으로 하고 있는 작업에는 아주 큰 도움이 되기는 힘든 것 같다 - 적어도 현재 판단하기는 그렇다. 특히나 데이터 간에 대기나 기타 요인으로 알고리즘 적인 분해decomposition를 해야하는 경우에는 사실 라이브러리의 문제가 아닌 고차원적인 문제이기 때문에 별로 도움이 될 수 없다 - 그렇지만 어차피 라이브러리에 기대하는건 저수준 문제를 그나마 줄이자니까. 덤으로 “하나의 스레드만으로 돌 때도 제대로 돌 것"이라는 가정을 하고 있기 때문에, 여러 개의 스레드를 사실상 가정하는 대용량 I/O 서버에서는 약간 적용이 힘들기도 하다.

일단 동시 접근이 가능한 컨테이너 류 - concurrent map, hash, vector, list, queue - 는 STL과 거의 같은 형태고 바로 적용이 가능한 수준이기 때문에, 별다른 부담없이 특정 공유 _데이터에 대한 병목을 제거_할 수 있다. 그리고 이런 부분들은 많은 량의 I/O가 있는 응용이나 게임 서버같은 류의 멀티스레드 프로그래밍에서도 쉽게 쓸 수 있고 성능 향상도 기대할 수 있다 - STL을 쓰면서 보통 맨 처음 느끼게 되는 것은 흔히 사용하는 컨테이너를 프로그래밍 오류없이 적용한다 가 아닐까 생각하는데, intel TBB는 멀티스레딩에서 그런 장점을 제공해준다.

일단 이 포스팅에선 여기까지. 그리고 앞으로 한동안 이 intel TBB에 관해서 삽질하고 느낀 것들을 좀 적어보려고한다.


  1. 많은 스레딩 팩키지들이 매크로나 전처리기 등을 사용해서 C++같지 않은 개발 환경 을 만들어 낸다. ‡ Compiler 기술을 가지고 있는 intel에서 만든다는 점에서 약간의 신뢰도 상승이 있고, 사용 가능한 플랫폼이 나름대로 많다는 점도 + 요인. ↩︎