Post

운영체제 - thread

thread

thread란 무엇인가요? 실이라는 의미를 가지고 있습니다. 스레드는 프로세스의 흐름이라고 이해하면 됩니다. 현대 컴퓨터는 멀티프로세싱을 합니다. 하나의 프로세스를 여러 흐름으로 만드는 기법을 멀티스레드 기법이라고 합니다. 예로, 쇼핑몰 서버가 있습니다. 하나의 공유 자원(서버)에 여러 손님들이 접근하려 합니다. 구매라는 여러 흐름이 한 번에 실행되지 않는다면, 쇼핑몰엔 큰 문제가 생길 것입니다.

image

왜 thread ?

사실 프로세스를 하나 더 만들면 되는 문제가 아니냐 싶습니다. 하지만 프로세스를 하나 더 만드는 것은 꽤나 무겁습니다. 심지어 중복되는 데이터 영역도 있을 것이고, 이는 메모리를 효율적으로 사용하지 못합니다(무겁습니다). 따라서, 하나의 프로세스 안에서 여러 흐름(thread)을 나누어 실행하자는 것이 thread의 의미입니다.

image

다른 프로세스끼리 통신(IPC)하지 않고, 프로세스 내부에서 자원을 공유하므로 구현이 쉽습니다. 또한, 프로세스끼리의 context-switching 방식보다 더 경제적입니다. 왜냐하면 프로세스 내부에서 thread를 switching하는 방식이기 때문입니다. 확장성이 좋을 뿐 아니라, 하나의 thread가 멈추더라도, 다른 작업은 진행이 계속 된다는 것에서 강점을 지닙니다. 또한 스레드의 스택들은, 프로세스 내부 스택에서 스레드들을 위해 공간을 할당합니다. 이는 스레드를 위한 공간을 프로세스 밖에 노출하지 않는다는 의미입니다.

multl에 대한 말, 말, 말

스레드를 더 알아보기에 앞서, 멀티라는 단어에 대해 좀 알아봅시다. 여러분들은 멀티코어와 멀티프로세서, 멀티스레드의 차이에 대해 잘 아시나요? 저는 가끔 헷갈리긴 하는데, 이 기회에 정리를 잘 해놔야겠습니다. 멀티프로세서 프로세서가 여러개 있는 형태고, 하나의 CPU에 여러 개의 코어가 들어있는 것을 멀티코어라고 합니다. 프로세서란 현대에 들어, CPU와 유사한 뜻으로 사용되고 있습니다.

image

그렇다면 하나 질문을 해보겠습니다. 하나의 프로세서에 2개의 코어가 들어있는 상황이 좋나요? 아니면 프로세서당 코어가 하나, 두 개의 프로세서가 있는 것이 좋나요?

코어의 수는 같지만, 프로세서가 하나 더 있는 후자가 더 좋아보이나요? 정답은 x입니다. 왜냐하면 하나의 프로세스를 처리할 때, 후자는 코어 하나로 처리하지만, 전자는 코어 2개를 사용하기 때문입니다.

이러한 멀티코어 상황에서, 하나의 process를 독립적인 영역으로 나누어, 코어들이 병렬적으로 독립적인 영역을 수행하면 병렬적으로 task를 처리할 수 있습니다. 또한 동시에 처리되는 것 같이 보여야 하기 때문에 multicore programming은 병렬성과 동시성을 모두 만족해야 합니다.

Concurrency and Parallelism

동시성(Concurrency)은 하나의 코어에서 사용되는 말입니다. 즉 하나의, 코어에서 하나의 흐름으로 여러 작업들이 번갈아 가며(context-switching) 수행되는 것을 말합니다. 하나의 코어기에, 여러 프로세스를 적절한 시간마다 context-switching하며 동시적이게 실행되어 보이도록 하는 기법을 말합니다.

image

병렬성(Parallelism)은 여러 코어에서 사용되는 말입니다. 여러 코어에서, 독립된 task들을 수행하는 것을 말합니다. 이 때, 코어에는 각자 별개의 독립된 프로세스를 수행합니다.

image

프로세스가 concurrency하게 수행된다면, 공유자원에 대한 문제가 생깁니다. 왜냐하면, 내가 하는 작업이 atomic하지 않을 수 있기 때문입니다. 덧셈도 따지고 보면, 레지스터에 값을 채우고, 그 값을 더한 다음, 다시 레지스터에 저장해서 메모리에 올리는 형식으로 구현됩니다. 만약, 내가 값을 가져오려는 순간, concurrency하게 다른 프로세스가 접근해서 내가 가져오려는 레지스터의 값을 바꿔버리면 문제가 생기는 것입니다. 이렇게 공유자원 문제가 생기는데 이를 해결하기 위해서 semaphore, mutex 등의 해결책이 연구되기 시작합니다.

Data and Task Parallelism

data parallelism이란 데이터들을 분할해, 여러 코어에서 동일한 작업을 수행합니다. 예를 들어 arr[1000000]이라는 배열의 모든 원소의 값을 1씩 올리고 싶을 때, 즉 코드로 작성하면

1
2
3
4
int arr[1000000]={0,};
for(int i=0;i<1000000;i++){
    arr[i]++;
}

를 할 때, 4코어라 가정하면 1번 코어에서 앞에서 0~249999번의 인덱스에 대해 연산하고, 2번 코어에는 250000~499999번의 인덱스에 대해 연산하는 ….. 병렬적인 방식을 data parallelism이라고 합니다.

task parallelism이란 task를 분할하는 방식입니다. 말 그대로 1번 코어에선 1번 스레드를 할당하고, 2번 코어에는 2번 스레드를 할당하고… 와 같은 방식으로 각 thread는 task를 분할해서 수행하는 방식을 task parallelism이라고 합니다.

사실 이렇게 parallel하게 작업을 수행하더라도, context-switching이라는 overhead는 존재하기에, 실제 성능이 코어의 수에 비례해서 상승하지는 않습니다. 이를 암달의 법칙(Amdahl’s Law)이라고 부릅니다.

image

암달의 법칙에 대해 자세하게 보고싶으면 여기를 참조해주세요. 출처 나무위키.

마무리하며

다음 글에선 thread에 대해 조금 더 알아보도록 하겠습니다.

This post is licensed under CC BY 4.0 by the author.