[IT에 한 걸음 더 다가가기] 연산처리의 성능 한계에 도전하는 병렬컴퓨팅 (4편)
지난 3편에서는 멀티코어 시대의 병렬컴퓨팅 기법에 대해 소개 드렸습니다. [관련기사 바로 가기 : 병렬컴퓨팅의 다양한 기법 II] 멀티코어는 싱글코어의 하드웨어적인 제약과 병렬화의 한계를 극복하면서 컴퓨터 성능 향상을 위한 기본 요소가 되었으며, 현재는 대부분의 PC가 멀티코어 기반으로 만들어지고 있다는 말씀을 드렸죠? 이번 편에서는 이러한 멀티코어의 모체가 되는 병렬컴퓨터에 대하여 자세하게 다뤄보도록 하겠습니다.
멀티코어는 갑자기 등장한 기술이 아닙니다. 컴퓨터가 탄생한 시기부터 성능 향상을 위해 지속적으로 연구되어 온 병렬 컴퓨터의 한 형태라고 할 수 있습니다. 그럼 병렬컴퓨터가 어떻게 탄생하게 되었는지 그 배경과 역사부터 살펴보도록 하겠습니다.
현재 우리는 첨단과학과 공학 기술이 제공하는 양분 위에서 문명을 마음껏 누리면서 살고 있습니다. 그리고 이러한 문명의 발전 속도는 하루가 다르게 빠르게 진행되어 가고 있습니다. 컴퓨터는 바로 이러한 세상을 열게 해준 가장 큰 공헌자라고 볼 수 있습니다. 1946년 최초의 전자식 컴퓨터인 ENIAC 탄생 이후, 첨단 과학 분야에서의 컴퓨터의 활약은 대단했으며, 그 당시까지 처리할 수 없었던 복잡하고 거대한 규모의 연산을 컴퓨터가 처리함으로써 컴퓨터에 대한 사람들의 기대감은 갈수록 커지게 되었습니다.
이러한 기대감을 등에 업고 미국에는 많은 컴퓨터 회사들이 생겨났고 IBM과 같은 컴퓨터 회사들은 다양한 상업용 컴퓨터를 시장에 내놓게 됩니다. 이러한 컴퓨터들은 사회 각 분야에서 진가를 발휘하며 없어서는 안될 필수적인 요소로 자리를 잡게 되었으며, 컴퓨터의 성능에 대한 욕심 또한 점점 커지게 되었습니다. 그렇게 해서 본격적으로 슈퍼컴퓨터에 대한 연구가 되었습니다.
세계 2차 대전이 끝나고 뛰어난 기술을 가진 해군의 퇴역 장교들로 구성된 ‘컨트롤 데이터’라는 회사는 슈퍼컴퓨터 개발에 가장 적극적으로 뛰어들었습니다. 기술 담당 부사장으로 있던 세이머 크레이라는 사람은 1초에 300백만 개의 명령어를 처리할 수 있는 6600이라는 모델을 완성하였으며, 이 컴퓨터는 최초의 슈퍼컴퓨터라는 명칭을 얻게 되었습니다. 크레이는 ‘컨트롤 데이터’라는 회사를 그만둔 이후에도 ‘크레이 리서치’라는 회사를 직접 차려 슈퍼컴퓨터 개발에 끊임없는 노력을 기울여 1976년 “크레이 I”이라는 제품을 만들게 되었습니다. 하지만 이 무렵까지의 슈퍼컴퓨터는 CPU에 들어가는 반도체 칩의 집적도를 높이거나 CPU와 주변장치를 연결하는 배선을 짧게 줄이는 방식으로 성능을 높여왔으며, 전통적인 폰 노이만 구조에서는 벗어나지 못한 형태였습니다.
“폰 노이만 구조”란, 존 폰 노이만이라는 헝가리 출신의 과학자가 제안한 범용적인 컴퓨터 구조입니다. 폰 노이만은 컴퓨터의 구조를 기억장치, 중앙 처리 장치, 입출력 장치 3가지 형태로 제시하였으며, 프로그램과 데이터를 기억장치에 저장하여 사용하는 현대 소프트웨어의 근간이 되는 “프로그램 내장 방식”을 고안하였습니다.
하지만 폰 노이만의 구조에서는 컴퓨터는 한 번에 하나씩 데이터를 처리해야 한다는 순차적 처리라는 큰 단점이 존재하였습니다. 이러한 순차처리 구조는 컴퓨터의 성능 향상에 가장 큰 걸림돌이 되었습니다. 그래서 여러 컴퓨터 회사들은 기존 폰 노이만 구조의 컴퓨터 형태를 근본적으로 바꾸는 시도를 하게 되었으며 그렇게 탄생하게 된 것이 바로 병렬처리 기술입니다. 버로즈라는 회사는 세계에서 처음으로 병렬처리 기술을 적용한 “일리악”이라는 슈퍼컴퓨터를 개발하는데 성공을 하였으며, 이후 크레이 리서치에서도 1982년 “크레이 X-MP”라는 병렬처리 기반의 슈퍼컴퓨터 개발에 성공하게 됩니다. 현대의 슈퍼컴퓨터는 이러한 병렬컴퓨터 구조를 기본적으로 갖추고 있으며 2000년대 들어서는 일반 PC에도 멀티코어의 형태로 병렬컴퓨터 방식을 범용적으로 채택하게 됩니다.
1966년 스탠퍼드 대학교수인 마이클 J. 플린이라는 사람은 컴퓨터가 명령어와 데이터를 단일로 처리하는지, 아니면 복수로 처리하는지의 관점에서 “플린의 분류”라고 하는 컴퓨터 아키텍처 분류를 제시하였으며, 아키텍처를 SISD, SIMD, MISD, MIMD라는 4가지 형태로 분류하고 있습니다.
SISD는 하나의 명령에 하나의 데이터가 순차적으로 처리되는 전통적인 폰 노이만 구조를 따르며, 일반적인 싱글코어가 이 분류에 속하게 됩니다. SISD 구조에서는 성능을 향상시키기 위해 파이프 라이닝이나 슈퍼스칼라 등의 명령어 수준의 병렬컴퓨팅 기법을 사용합니다. 또한 최신 프로세서에는 하드웨어 수준의 멀티 스레드 방식을 통하여 하나의 물리적인 코어를 두 개의 논리적인 코어로 다루는 SMT(Simultaneous multithreading) 기술을 채택하고 있습니다. 이 방식을 사용하면 서로 의존성이 없는 두 개의 스레드가 동시에 파이프 라이닝을 수행함으로써 성능을 높일 수 있습니다. 인텔에서는 이 기술을 하이퍼스레딩이라고 부르며, 우리가 흔히 컴퓨터의 작업관리자에서 CPU 사용 현황을 조회할 때, 코어의 개수가 실제 물리적인 코어 개수보다 2배 더 많이 보이게 되는 것도 바로 이 SMT 기술 때문입니다.
SIMD는 하나의 명령에 여러 개의 데이터가 처리되는 구조입니다. 즉, 다수의 데이터에 적용되는 연산이 동일하고, 데이터 간의 의존성이 없는 경우 SIMD 구조를 적용하면 데이터 병렬처리를 통해 처리 성능을 획기적으로 높일 수 있습니다. 많은 슈퍼컴퓨터에서는 SIMD 연산을 위해 벡터 프로세서라는 구조를 갖추고 있으며, 인텔에서도 coprocessor(보조 프로세서) 형태로 SSE(Streaming SIMD Extensions)나 AVX(Advanced Vector eXtensions) 등의 SIMD 아키텍처를 지원하고 있습니다. 또한 다수의 ALU를 확보하고 있는 GPU도 기본적으로 SIMD 연산을 수행합니다.
MISD는 여러 개의 명령에 하나의 데이터가 처리되는 방식인데, 이 구조는 거의 쓰이지 않으며 상업적으로도 아직 구현된 바가 없습니다.
마지막으로 MIMD는 여러 개의 명령어들이 여러 개의 데이터들을 동시에 처리하는 방식이며, 우리가 일반적으로 부르는 멀티프로세서의 형태가 바로 MIMD입니다. 지금부터는 MIMD를 기준으로 병렬컴퓨터를 자세히 살펴보겠습니다.
MIMD 구조의 병렬컴퓨터는 프로세서들의 결합 형태에 따라 강 결합 구조와 약 결합 구조로 나눌 수 있습니다. 강 결합 구조는 다수의 프로세서들이 주기억 장치를 서로 공유하는 형태로써, 공유 메모리 시스템이라고도 부릅니다. 반면, 약 결합 구조는 각각의 프로세서가 독립적인 주기억 장치를 가진 형태인데 분산 메모리 시스템이라고도 부릅니다. 그럼 각각의 시스템에 대해서 살펴보겠습니다.
▲ 병렬컴퓨터 구조들의 분류
SMP (Symmetric Multiprocessor)
공유 메모리 시스템의 가장 대표적인 형태는 대칭적 멀티프로세서(SMP)입니다. SMP는 다수의 프로세서들이 주기억 장치와 I/O를 서로 공유하고 하나의 운영체제가 모든 프로세서를 관리하는 구조입니다. 여기서 “대칭적”이라는 말은 모든 프로세서가 동일한 종류로 되어 있으며, 동일한 기능을 수행한다는 의미가 담겨 있습니다. 따라서 SMP에서는 동일한 프로세서들의 협력을 통해 병렬처리를 수행함으로써, 단일 프로세서를 가진 시스템보다 뛰어난 성능을 발휘할 수 있게 됩니다. 컴퓨터 조립에 관심이 많으신 분들은 잘 아시겠지만 컴퓨터 내부의 메인보드에 CPU를 여러 개 꽂을 수 있도록 되어있는 컴퓨터를 보신 적이 있을 겁니다. 이렇게 여러 개의 CPU를 활용할 수 있도록 되어있는 구조를 바로 SMP라고 부릅니다. SMP 시스템에서는 여러 CPU들과 주변장치들이 버스나 크로스바 스위치 등을 통해 연결되며, QPI(Quick Path Interconnect, 인텔) 등의 버스 프로토콜을 통해 고속의 통신을 수행합니다.
▲ SMP (Symmetric MultiProcessor)
CMP (Chip Multiprocessor)
한편, SMP의 일종인 칩 멀티프로세서(CMP)란 하나의 칩에 여러 개의 코어를 장착한 형태의 프로세서입니다. SMP처럼 컴퓨터 내부에 CPU를 여러 개 장착하는 것이 아니라, 단일 CPU에 연산을 담당하는 코어를 여러 개 두어 공간적 활용성을 높이고 코어 간에 캐시를 공유 함으로써 처리 성능을 높일 수 있는 구조입니다. (물론, 고사양의 서버컴퓨터는 이러한 멀티코어를 다수 장착하여 SMP 형태로 구성하는 경우도 많습니다.)
▲ CMP (Chip MultiProcessor)
멀티코어가 바로 CMP를 가리키며, 현재 일반 PC에 가장 범용적으로 적용되고 있는 병렬컴퓨터 구조입니다. 멀티코어는 단일 칩에 장착된 코어의 개수에 따라 듀얼코어, 쿼드코어, 트리플 코어, 헥사코어, 마그니코어(도데카 코어)로 발전해 왔으며, 최근에는 수십 개에서 수백 개의 코어를 집적한 형태인 매니코어가 크게 부각되고 있습니다. 물론 매니코어는 동일한 종류의 코어로 구성되는 멀티코어와는 다르게 단순한 기능의 코어들을 집적하여 수치계산의 성능을 높이는 등 특수한 목적에 사용하는 경우가 많습니다. 한편,인텔은 60개의 core를 하나의 칩에 집적한 매니코어 프로세서인 제온 파이를 공개하며 최근 GPGPU가 주름잡고 있는 병렬컴퓨팅 시장에 적극적인 행보에 나서고 있습니다.
NUMA (Non-uniform Memory Access)
만약 공유 메모리 시스템에서 모든 프로세서에게 메모리 접근을 균일하게 제공한다면 프로세서가 많이 추가되는 경우, 메모리 자원을 공유하기 위한 경쟁이 심하게 발생하여 버스 상에 큰 병목현상이 발생할 수 있습니다. 이렇게 메모리에 대한 접근을 균일하게 제공하는 시스템을 UMA(Uniform Memory Access)라고 하는데, 이를 해결하기 위해 고안된 구조가 바로 NUMA(Non-uniform Memory Access)입니다.
▲ NUMA (Non-uniform Memory Access)
NUMA는 각 프로세서에 독립적인 메모리를 할당하여, NUMA 노드라는 하나의 그룹으로 묶어서 각 노드를 상호 연결하는 형태로 조직되어 있습니다. 따라서 각 프로세서는 자신에게 할당된 지역 메모리로는 빠르게 접근하며, 원격 메모리로는 느리게 접근하게 됩니다. 이렇게 NUMA 구조에서는 전체 프로세서가 물리적인 위치에 따라 메모리에 접근하는 시간이 불균일하게 주어짐으로써 메모리의 병목현상을 해소할 수 있게 됩니다.
분산 메모리 시스템은 노드라고 부르는 독립적인 컴퓨터를 고속의 네트워크로 연결한 형태를 가리킵니다. 클러스터나 그리드라고 부르는 컴퓨터 구조가 바로 분산 메모리 시스템이며, 노드는 SMP나 CMP 시스템으로 구성될 수 있습니다. 또한 각각의 노드는 메시지 교환을 통해 서로의 내용을 확인하고 협력적인 관계를 유지하게 됩니다.
▲ Cluster
얼핏 NUMA와 비슷해 보일 수도 있지만 분산 메모리 시스템의 각 노드는 운영체제를 개별적으로 탑재한 독립적인 PC로써 물리적으로 완전히 다른 구조입니다. 지난 3편에도 소개 드렸다시피, 분산컴퓨팅의 기반이 되는 구조가 바로 분산 메모리 시스템이며 수많은 PC를 수평 확장할 수 있어 대규모 대용량의 데이터를 처리하기 위한 가장 적합한 구조라고 할 수 있습니다.
지금까지 살펴본 병렬컴퓨터의 장점은 다수의 프로세서 혹은 코어의 협력에 의한 성능 향상이었습니다. 그렇다면 프로세서를 많이 추가하면 할수록 성능이 선형적으로 증가하게 된다는 것을 의미합니다. 하지만 이러한 병렬컴퓨터 또한 성능을 마냥 올리지 못하는 한계가 존재하고 있습니다. 그럼 어떤 문제점들이 있는지 하나씩 짚어보겠습니다.
실행하고자 하는 프로그램의 특정 부분은 병렬화가 가능하지만 나머지 부분이 순차적으로 실행되어야 한다면, 프로세서를 아무리 많이 추가한다고 해도 성능이 선형적으로 개선될 수는 없을 것입니다. 즉, 프로세서를 아무리 추가하더라도 성능 향상은 순차적인 부분에 의해 제한된다라고 하는 이 법칙이 바로 암달의 저주라고도 불리는 “암달의 법칙”입니다.
▲ 암달의 법칙
위 도표를 보면 병렬화의 비율이 높으면 높을수록 프로세서의 수가 많아지면 성능이 향상되는 것을 알 수 있습니다. 반대로 병렬화 비율이 낮으면 낮아질수록 프로세서의 수가 성능 향상에 큰 의미를 주지 않게 된다는 것을 알 수 있습니다. 예를 들어, 병렬화 비율이 50% (파란색 그래프)인 경우 프로세서의 수를 아무리 늘려봤자 2배 이상의 속도 향상을 내기 어렵다는 것을 도표는 보여주고 있습니다.
이에 반해 구스타프슨의 법칙은 이 문제를 조금 다른 시각에서 바라보고 있습니다. 구스타프슨은 암달의 법칙에서 주장하는 성능 한계를 처리량의 관점에서 극복할 수 있다고 주장하고 있습니다. 쉽게 말해, 암달의 법칙에서는 주어진 작업을 여러 프로세서에 나누어 처리하여 취할 수 있는 시간 단축 관점에서 성능 향상을 예측하였다면 구스타프슨의 법칙은 주어진 작업에 동일한 작업을 더 추가하여 더 많은 작업을 처리할 수 있는 처리량 관점에서 성능 향상을 예측하고 있습니다. 따라서 암달의 법칙과는 다르게 프로세서의 개수가 늘어나면 늘어날수록 처리량 또한 늘어나 성능을 향상할 수 있다는 법칙입니다. 물론 서로 성능 향상을 바라보는 관점이 다를 뿐이지 암달의 법칙은 여전히 유효하며 이 한계를 극복하기 위해서는 주어진 문제에 대해 효과적으로 병렬화하기 위한 노력이 반드시 필요합니다.
메모리 장벽이란 메모리의 성능이 CPU의 속도에 미치지 못해 발생하는 병목현상을 의미합니다. 이는 멀티코어뿐만 아니라 싱글코어에서도 존재하는 문제였습니다. 하지만 멀티코어 기반에서는 여러 개의 코어가 동시에 메모리에 접근함으로써 기존보다 병목현상이 더욱 심각해질 수밖에 없게 되었습니다. 여기서 가장 문제가 되는 부분은 메모리 대역폭인데, 사용 가능한 메모리 대역폭이 포화상태에 이르게 되면 코어의 수를 아무리 늘려도 성능 향상이 어려워지게 됩니다. 다중채널 메모리나 캐시 등을 이용해 대역폭 문제를 해소하기 위한 많은 노력들이 있지만 아직 개선해야 할 부분들이 많이 남아있습니다.
“공짜 점심의 시대는 끝났다.”
개발자이자 칼럼니스트로 활동 중인 캐나다 출신의 허브셔터라는 사람이 남긴 명언입니다. 과거 싱글코어가 주류였던 시절에는 하드웨어가 발전하면 개발자의 아무런 노력 없이 소프트웨어의 수행 성능이 자연히 따라 향상이 되었습니다. 하지만 멀티코어 시대로 넘어오면서 더 이상은 소프트웨어가 하드웨어에 의존하여 성능 향상을 기대하기 힘들어지게 되었습니다. 멀티코어가 성능 향상을 제대로 발휘하기 위해서는 소프트웨어적으로 코어들을 활용한 병렬처리가 필요하기 때문입니다. 따라서 멀티코어 시대의 개발자들은 소프트웨어의 성능 향상을 위해 끊임없는 노력을 해야 하는 처지에 이르게 되었습니다.
이제, 프로그래머가 멀티코어 시대에서 성능 향상을 위해 어떤 노력과 대가를 치러야 하는지 다음 편 “병렬프로그래밍”에서 본격적으로 다뤄보도록 하겠습니다.
<참고자료>
위키백과, http://ko.wikipedia.org
과학세대(1993). ‘두뇌에 도전하는 미래 컴퓨터’ 지학사
William Stallings (2010). ‘컴퓨터 시스템 구조론’ 진샘미디어
김민장(2010). ‘프로그래머가 몰랐던 멀티코어 CPU 이야기’ 한빛 미디어