multithreading

CPU의 코어개수가 늘면서 multithreading을 하는 것이 보편적이 되었고 그걸 못해서 처리 속도가 느려지면 바보같은 application이 된다고 볼 수도 있을 것 같다.

어쨌든 CPU core를 충분히 활용해서 일을 빠르게 처리하기 위해서 multithreading을 한다고 하면, 대략적으로 다음과 같이 정리한다.

기본 절차

일단 thread를 create한다. 이때 multithreading하려는 function의 주소가 날아가고 해당 function에 주어질 argument가 같이 보내질 수 있다.

그 다음 thread join을 해준다. 이게 뭘 뜻하느냐면 벌려놓은 thread가 모두 실행 완료될 때까지 기다리는 작업이라고 볼 수 있다.

thread가 생겨나면 모든 CPU에 골고루 뿌려주는 일은 OS가 알아서 한다. 일단 thread를 만들어놓자.

C/C++

고전적인 방법은 pthread.h에 정의된 API를 이용하는 방법이다. 방법은 간단하다. thread create하고 thread join하면 된다.

C++가 c++11에서는 thread를 위한 class가 별도로 있어서 pthread를 쓰지 않아도 되는데 (그렇지만 그게 그거다) 그래도 사실상 pthread와 큰 차이는 없다. 모양새가 thread라는 클래스를 불러다 쓰는 것일 뿐.

그외 script 언어들

대부분 multithread를 위한 api가 제공되고 사용하는 방법도 같다. 따라서 core 개수가 충분히 많다면 아무리 단순 작업이라고 하더라도 multithreading을 하면 수행속도가 엄청나게 빨라지니까 사용할만하다. 대개의 desktop에서는 4개 이상의 thread를 큰 성능저하 없이 쓸 수 있고, 조금 좋다면 16개, 심하면 32개까지 벌릴 수 있으니까. 명백히 16배, 32배까진 아니더라도 충분히 빨리 수행하게 할 수 있다.

동기화(?)/공유 변수

thread 동기화 (synchronization)에 대한 이야기를 많이 하는데 난 정확히 뭘 동기화하겠다는 것인지 모르겠다. thread간 통신을 한다는 소리도 있는데 여전히 잘 모르겠고. 어차피 shared memory를 하나 정해놓고 그곳에 데이터를 쓰고 읽고 하는 식으로 통신을 하는 것이고 동기화라고 하는 것 마찬가지로 공통 메모리를 하나 놓고 그곳에 상태변수를 넣어놓고 모든 thread가 고립되지 않고 동작하게 한다는 뜻으로 이해할 수 있다.

이런 상태가 되면 정해진 자원을 여러 개의 thread가 동시에 사용하려고 할 수 있는데, 이 때 이 충돌(?)을 막아주는 역할을 하는 게 mutex와 semaphore 같은 것이다. 단순히 mutex는 하나의 자원을 하나의 thread가 독점할 수 밖에 없는 경우에 사용하고 semaphore는 N개의 thread가 동시에 사용할 수 있는 경우에 사용한다고 보면 된다.

그러니까 공통 메모리에 특정 자원에 대한 현재 점유 현황을 적어놓고 각각의 thread에서 해당 자원을 사용할 때 이 값을 참조해서 threshold를 넘어가면 해당 변수를 모니터링하면서 대기하고 그렇지 않으면 사용하게끔 하는 식인 것이다. c++이든 다른 스크립트 언어이든 이런 기능은 기본 제공되고 있다.

multithreading이 뭔가 엄청나게 꼼꼼하게 하겠다면 복잡해질 수 있지만 단순히 내가 하려는 일을 N개의 처리기에 병렬로 돌리겠다고 하면 단순히 코드 몇 줄 더 넣는 것으로 쉽게 해결된다. 다만 그 개념이 쉽게 파악되지 않아서 실행하지 못하고 있을 뿐. 일단 어느 정도 개념을 파악하고 돌려보고 하면 이만큼 일을 쉽고 편하게 할 수 있게 하는 것도 없다.