꾸준히
스레드를 사용하는 이유 본문
CPU 성능 향상의 한계
스레드 프로그래밍이 많이 쓰이는 이유는 CPU의 성능과 효율에 기술적 한계가 보이기 시작했기 때문이다.
과거에는 프로그래머가 비효율적인 코드를 작성하더라도 새로 개발된 CPU 및 주변 장치로 교체해주면 성능 문제가 해결되는 경우가 많았다. 하지만 시간이 지나면서 클럭 속도를 4GHz 이상 올리기 시작하자 심각한 전력 소비 현상과 더불어 발열 문제가 발생했다.
원래 CPU의 성능을 올리기 위한 기초적인 방법은 작동 클럭을 올리는 것이다. 하지만 클럭의 한계점이 보이기 시작하자 벤더들은 분업의 원리를 적용한 멀티코어를 만들었다. 이는 프로세서 1개의 성능 향상이 한계에 부딪히자 2개 이상의 프로세서가 작업을 나눠서 실행하도록 하는 병렬 처리 힌트에서 파생된 것이다.
공정 기술의 향상으로 인해 미세 공정이 가능해졌고, 이는 프로세서 코어를 더 작게 만들 수 있게 하였다 따라서 프로세서를 추가할 수 있는 공간을 확보할 수 있게 되었다.
이렇게 한 개의 칩에 복수 개의 CPU 코어를 넣은 것을 CMP(Chip Multi Processor)라고 부른다.
일반적으로 시스템에 다수의 프로세서가 존재하면 운영체제에서 실행되는 수많은 프로그램이 각각 개별적인 프로세서를 할당받아 작동할 수 있게 된다. 따라서 시스템 전체의 성능이 올라갈 가능성이 커진다.
그러나 시스템 전체의 성능과 개별 프로그램의 성능은 또 다른 형태의 문제다. 만일 개별 프로그램에 스레드나 비동기 처리가 포함되어 있지 않다면 프로세스 자체의 성능은 개선되지 않는다
이러한 배경 때문에 개별 프로그램 1개의 처리 성능이나 응답을 높이기 위해서 멀티 스레드와 같은 비동기적 처리 기법의 당위성이 주목받기 시작했다.
멀티 스레딩과 성능 향상
병렬 처리란 동시에 복수의 작업을 처리하는 것이고, 동시 처리는 복수의 작업을 짧은 간격으로 번갈아 가면서 처리하는 방식을 의미한다.
일반적으로 CPU는 한 번에 한 개의 작업만 가능하기 때문에, 싱글 코어에 CPU가 1개라면 병렬 처리를 할 수 없다.
그러면 CPU의 개수가 1개라면 멀티 스레드가 소용없는 것일까? 그렇지는 않다. CPU의 개수가 1개라도 멀티 스레드를 사용하면 효과를 볼 수 있는 경우도 있다.
- 1개의 CPU에서 2개의 작업을 동기적으로 진행하는 경우
2개의 작업이 순서대로 진행되는 흐름을 보여주고 있다. 이 작업이 하나의 함수가 실행되는 것으로 생각하면 이해가 쉬울 것이다. 작업1은 3초, 작업2는 5초의 시간이 소요됐다고 가정하면 총 8초의 시간이 소요되었다. 하지만, 멀티 스레드를 도입하여 각각의 작업을 독립적으로 실행한다면 달라진다.
- 2개의 CPU에서 작동되는 멀티 스레드의 예시
CPU의 개수가 스레드의 개수와 같거나 많으면 동시 작업이 가능해지므로 예시 그림처럼 전체 실행 시간이 줄어들 수 있다. 위 그림처럼 완전히 동시에 실행되는 것이 병렬 처리다. 실제 환경에서는 완벽하게 따로 작동하지는 않을 수 있다.
또한, 병렬 처리를 하더라도 로드 밸런싱에 실패하여 한쪽 스레드에 일이 몰리게 되면 성능 향상이 없을 수도 있다
- 1개의 CPU에서 작동되는 멀티 스레드의 예시
위 그림처럼 운영체제는 멀티태스킹을 위해 작은 단이 시간으로 작업을 쪼개어 작동할 수 있다. 이렇게 시분할로 쪼개진 작업이 번갈아가면서 실행되면 거의 동시에 실행되는 것처럼 느낄 수 있다.
이처럼 실제로는 동시에 실행되지는 않지만, 번갈아가면서 실행하여 마치 동시에 작동되는 것처럼 하는 것을 동시 처리라고 할 수 있다. 그리고 멀티 스레드를 사용하여 동시 처리를 하게 되면 레이턴시 하이딩 효과에 의해 성능 향상이 있을 수 있다.
레이턴시 하이딩
레이턴시란 요청 후 실제 응답이 오기까지 걸리는 대기 시간으로 장치들 간의 처리속도 차에 의해 발생한다.
예를들어 CPU의 응답속도가 메모리나 하드디스크와 비교하면 훨씬 빠르기 때문에 레이턴시가 발생하는 것이다. 그러므로 CPU의 처리 속도보다 느린 I/O 처리를 기다리는 시간을 효율적으로 다른 작업에 분배하면 CPU 사용률이 높아져서 전체적으로는 성능 향상을 가져올 수 있다.
1개의 CPU에서 작동되는 멀티 스레드 그림과 같이 레이턴시가 다른 작업에 의해 숨겨지는 것처럼 보이기 때문에 레이턴시 하이딩 이라고 부른다.
멀티 스레드 vs 멀티 프로세스
성능을 올리기 위해 멀티 스레드나 멀티 프로세스를 도입하는 기본 원리는 분업이라고 할 수 있다.
그렇다면 프로세스 단위의 멀티 태스킹이 있음에도 멀티 스레드가 나온 이유는 프로세스 단위의 분업은 시스템 전체의 효율은 올릴 수 있지만, 프로세스 1개의 성능 향상에는 연관이 없기 때문이다.
다시 말해, 프로세스의 내부 성능을 향상하려면 프로세스 내부에 분업을 도입해야 하고 이를 위해 멀티 스레딩이 필요하게 된 것이다. 하지만 멀티 스레딩이라고 항상 좋은 것은 아니다.
멀티 프로세스의 장점은 각각 독립된 프로세스로 작동하기 때문에, 메모리 영역이 보호되는 장점이 있고 동기적 프로그래밍 모델을 사용하므로 디버깅의 편리함 같은 많은 장점이 있다.
하지만 멀티 프로세스 방식은 IPC를 사용할 수밖에 없기 때문에 분업을 위해 작업을 쪼개면 쪼갤수록 지속적으로 I/O 대역폭을 소모하게 되어 한계 성능에 부딪히는 시점이 오게 된다.
그러나 멀티 스레드 방식은 각 스레드가 통신하는 비용을 획기적으로 줄일 수 있다. 왜냐하면, 각 스레드는 프로세스 내부에서 메모리 주소 공간을 공유하기 때문이다. 따라서 굳이 IPC를 쓰지 않아도 데이터의 주소만 넘겨주어도 통신할 수 있다.