[펜티엄 프로젝트] ② 32비트와 64비트의 공통점과 차이점

일반입력 :2005/09/26 06:50

김태훈 (인터데브 차장)

64비트는 두 배 빠른 컴퓨터?

언젠가 신문에서 컴퓨터 두 배 빨라진다는 헤드라인의 기사를 본 적이 있다.

무슨 말인가 싶어 자세히 읽어보니 32비트에서 64비트로 CPU의 기술 전환이 이뤄지고 있다는 말이었다. 32비트에서 64비트로 시스템이 이전되면 정말 두 배 빠른 컴퓨터가 나타날 것인가? 사실은 그렇지 않다.

8비트에서 16비트, 16비트에서 32비트로 컴퓨터의 비트 수가 올라가는 것은 메모리와 직결돼 있다.

컴퓨터가 32비트라는 말은 레지스터 버스의 크기가 32비트라는 의미와 연결되며, 평면 메모리 모델을 사용하는 경우 2의 32제곱의 메모리 공간을 확보할 수 있다. 이는 32비트로 표현할 수 있는 수치적인 메모리 공간이며, 환산하면 4GB의 공간이 나타난다.

32비트가 처음 나타난 1980년대만 하더라도 이 메모리 공간은 엄청나게 큰 것이었다. 그러나 메모리 가격이 점차 하락해 지금은 개인용 컴퓨터조차도 1GB 이상의 메모리를 탑재하고 있고, 작은 프로그램 하나의 실행 파일 크기가 수십 메가바이트 이상이 되는 경우가 허다해졌다.

빠른 속도로 프로그램이 진화하면서 4GB의 한계가 점차 드러나기 시작했다.

64비트는 2의 64제곱의 메모리 주소를 지칭할 수 있다. 이는 이론적으로는 1.8E19 정도의 메모리를 탑재할 수 있으며, 실제 64비트 윈도우는 16TB의 가상 공간을 할당할 수 있다. 이 가상 공간은 추후 더 늘어날 수 있을 것이다.

가상 공간으로 16TB를 지원하고 있기는 하지만 현재 버전의 물리적인 메모리는 1TB밖에 지원하지 않는다. 버전이 올라가면서 점차 더 많은 메모리를 지원하겠지만, 이 정도로도 몇 년간은 시스템을 운용하는 데 무리가 없을 것이다.

64비트를 도입하면 입·출력을 한 번에 64비트씩 처리할 수 있으며, 지금보다 훨씬 큰 메모리 공간을 확보할 수 있다는 장점이 있다. 64비트를 도입하는 가장 큰 이유 중 하나는 메모리 공간의 확보다.

메모리 공간의 확대와 성능

인텔의 노트북용 CPU는 데스크톱 CPU 클록의 절반 수준밖에는 되지 않는다. 그러나 실제 성능은 두 배 정도 되는 데스크톱 CPU와 엇비슷하게 나타난다. 노트북용 CPU의 캐시에 그 비밀이 있다.

시스템의 클록이 빠른 것은 높은 성능을 내는 시스템에 유리하다. 하지만, 시스템 클록의 상당 부분을 입·출력 작업에 뺏긴다면 실제 예측한 성능이 나타나지 않는다. 또한 페이지 파일과 워킹 세트 문제도 동일한 개념으로 적용된다.

32비트 컴퓨터에서는 워킹 세트 자체의 크기가 작았기 때문에 어쩔 수 없는 페이징이 반복됐으며, 이는 메모리의 탑재 유무와 상관없이 시스템의 성능을 저하시키는 요인이 됐다.

따라서, 메모리를 다소 낭비하는 프로그램이 결합할 경우, 시스템은 페이지 파일을 엄청나게 긁어대는 상황이 벌어지며, 전체 시스템의 성능을 떨어뜨리는 주요인이 됐다.

64비트 윈도우에서는 이러한 측면이 많이 해소됐다. 일단 전체 크기가 128GB 정도로 확장됐으며, 시스템 캐시는 1TB까지 사용할 수 있다.

만일 1TB의 메모리를 탑재했다면, 현재 사용되고 있는 많은 애플리케이션을 그대로 64비트로 이전했을 때 페이지 파일의 사용 빈도는 현저히 줄어들게 되며, 이는 그 자체로도 상당한 시스템 성능 향상을 가져올 수 있다.

메모리를 많이 사용하는 시스템-특히 닷넷이 그러하다-일수록 페이지 파일의 동작 자체는 전체 성능을 떨어뜨린다는 것을 의미한다. 또한 닷넷은 GC(Garbage Collection)의 동작에 의해 메모리를 회수하는 형태로 운영되며, 일종의 가상 머신과 같은 형태이기 때문에 생각보다 많은 메모리를 차지한다.

그래서 닷넷의 최적화 측면에서도 단순히 클록만을 최적화하는 방법론을 쓸 수는 없다.

웹 시스템의 경우 할당 가능한 메모리의 60% 이상을 하나의 프로세스(워커 프로세스)가 사용하면 시스템의 안정성을 크게 해친다.

이 경우를 대비해 순간적으로 웹 동작을 멈춰 워커 프로세스를 중단해 메모리를 리셋한 후 자동으로 재생하도록 프로그램이 만들어져 있다. 특히 32비트에서는 메모리와 관련된 민감한 문제들이 닷넷의 등장 이후 계속 논란거리가 돼 왔다.

마치 16비트의 세그먼트와 옵셋 구조가 갖는 문제점들이 1980년대 후반 등장해 1990년대 초반 32비트로 모든 시스템이 이전한 것과 같은 경우이다. 물론 이러한 문제는, 아직은 고용량 서버군에서만 발생하고 있다.

클록과 메모리, 어떤 토끼를 잡을 것인가?

전통적인 자료구조론에서는 시스템의 탐색 성능과 사용되는 메모리의 양, 두 가지 토끼를 놓고 항상 고민했다.

그런데 32비트 시스템에서는 클록과 메모리가 서로 독립적이지 않은 개념이다. 단일 프로그램에서 메모리를 다소 낭비해 클록을 덜 사용하는 방식으로 프로그램을 최적화했더라도 이 프로그램이 실제 운영될 경우에는 시스템의 한정적인 워킹 세트를 놓고 다른 프로세서와 경쟁에 돌입하게 되기 때문이다.

워킹 세트는 FIFO(First-in, First-out)로 설계됐기 때문에, 잦은 대용량 메모리 입·출력이 이뤄진다면 결국 이는 시스템의 스왑 파일을 건드릴 수밖에 없고, 시스템은 계속 하드디스크를 긁어대는 사태를 야기하게 된다.

32비트에서는 메모리 크기의 한계 때문에 콤팩트한 프로그램이 가장 빠른 프로그램으로 통용될 수 있다. 그러나 64비트 시스템에서는 이런 상황이 다소 느슨해진다. 실제 메모리를 많이 탑재하고 있어야 하기는 하지만, 메모리를 많이 사용하는 프로그램이 있더라도 크게 눈에 띄지 않는다.

이러한 방법론은 앞서 말한 노트북용 CPU의 개념과 비슷하다. CPU의 역할을 단순 입·출력에서 해방시켜 준다면 시스템은 그만큼 빨라진다는 것이다.

프레젠테이션 프로그램, 혹은 한정된 크기의 데이터

RDBMS에서 가변 데이터를 받아온 뒤 이 데이터를 유지하기 위해서 데이터를 어떤 형태로 받는 것이 가장 유리할까?

이러한 측면은 주로 프레젠테이션 계층을 운영하기 위해 사용된다. 가장 단순하게 생각할 수 있는 것이 어레이리스트(ArrayList) 혹은 배열일 수 있다. 그 다음으로 연결 리스트(Linked List)를 고려해 볼 수 있다. 그렇다면 가장 빠르고 효율적인 것은 어레이리스트, 어레이(Array), 연력 리스트 중 어떤 것일까?

전통적인 방식에서는 연결 리스트를 주로 꼽을 것이다.

연결 리스트는, 가변 데이터의 경우 메모리의 낭비가 비교적 적으며, 데이터 노드의 객체 크기가 비교적 크다면 포인터를 위해 사용되는 2개의 포인터 바이트는 무시할 수 있을 정도의 용량이기 때문이다.

그러나 64비트로 이전할 때에도 이것이 항상 정답은 아니다. 대부분 단순한 배열이 속도가 더 빠른 경우를 나타내며(어레이리스트보다는 어레이가 훨씬 속도가 빠르다), 클래스 배열의 경우 각 배열의 항목 단위로 생성을 처리해 줘야 하기 때문에, 실제 배열을 잡으면 생성 부하는 걸리지 않는다.

같은 이유로 닷넷의 큐를 쓰는 것보다 배열로 만들어서 선후를 지정한 자료 구조에서 단순한 큐가 훨씬 빠르다.

64비트에서 이런 방식이 훨씬 속도를 나타내는 것은 앞서 말한 대로 단순히 메모리를 충분히 잡을 수 있기 때문이다.

배열은 처음부터 메모리를 할당받고 들어가기 때문에 연결 리스트보다 메모리 소모량이 훨씬 많으며, 32비트에서는 일정 크기 이상을 잡은 프로그램이 멀티스레딩으로 운영될 때 필연적으로 페이징이 나타날 수밖에 없었다. 32비트에서는 절충안으로 어레이리스트를 사용하는 것을 권장한다.

Int32, Int64의 활용

64비트가 int64를 사용할 수 있다는 것은 어떻게 보면 행운이다. 만일 인사관리 프로그램에서 다음과 같은 직원의 데이터를 사용한다고 생각해 보자.

이런 식으로 'bool'형의 데이터가 수십 개일 때, 데이터베이스 설계를 어떻게 처리할 것인가?

필자의 경우 현장에서 설계된 많은 데이터들 중 이런 bool형 데이터가 수십 개 이상이 나열돼 있는 멋진(?) ERD를 흔히 보았다. 하지만 이러한 데이터 설계는 엄청난 낭비와 시스템 부하를 초래한다.

예를 들어 64가지의 서로 다른 bool형 데이터를 사용할 필요가 있다면, 이를 64개로 쪼개 데이터베이스를 설계하는 것이 아니라 int64형 하나로 설계한다. 그 다음 이들의 비트 연산을 통해서 새로운 값들을 만들어낼 수 있다.

가령 혼인 여부를 1, 흡연 여부를 2, 성별을 4라는 값을 주면, 미혼이며 흡연자 남자는 0

32비트를 사용하면 이런 조합이 부족한 경우가 많아, 두 개씩 묶어 하나의 구조체로 사용했으며 닷넷의 등장으로 int64를 사용해 이런 문제가 조금 쉬워졌다.

64비트라면 64개의 서로 다른 조건은 하나의 클록에서 해결된다. 따라서, 조건이 32개 이상일 경우 원하는 조건을 찾기 위한 연산 수행 속도가 절반 이하로 줄어드는 장점이 있다.

이런 측면은 32비트부터 도입됐어야 했다. 가령, 특정 동호회에 특정 사용자가 가입돼 있는지 여부, 그리고 그 동호회에서 그 사용자가 어떤 권한을 갖고 있는지에 대한 권한 계산 같은 작업이 이런 방법을 이용해 비트 연산 몇 개로 수행된다.

특히 닷넷 기반의 웹서비스를 운영할 경우 VBScript-ASP에서 제공되지 않던 비트 밀기 연산(bit shift operation)이 기본적으로 제공되기 때문에 이러한 최적화 방법론은 더욱 편리하게 사용될 수 있다. 또한 클래스를 가급적 작게 만들어야 생성과 소멸 부하에서 상당부분 이득을 취할 수 있다.

64비트, CPU 가용성을 중심으로

64비트 개인용 컴퓨터의 본격적인 등장은 그렇게 빨리 다가오지 않을 것이다. 64비트 애플리케이션의 개발도 쉽지 않을 것이며, 많은 사용자들이 현재의 32비트 성능에 대체로 만족하고 있기 때문이다.

그러나, 인터넷 서비스를 담당하는 서버군에는 날이 갈수록 과부하가 걸릴 것이다. 사용자의 늘어나는 요구를 충족하기 위해서는 이전에 행해지지 않았던 많은 개인화 서비스를 수행해야 하며, 이 개인화 서비스는 필연적으로 서버의 과부하를 수반한다.

현재 운용되고 있는 많은 기업용 서버에서 이미 32비트가 감당해 낼 수 있는 최적 지점을 벗어난 상황들을 많이 볼 수 있다. 특히 닷넷이 탑재되면서 CPU의 가용성은 올라갔지만 메모리의 가용성은 훨씬 떨어지는 결과를 낳게 된다(그렇다고 닷넷이 운용 도구로써 좋지 않다는 것은 아니다. 성능이 좋은 시스템을 얻기 위해서 C로 모든 코드를 작성할 수는 없는 것이 현실이다).

닷넷 자체의 목적은 비즈니스의 적시성에 있다. 따라서, 어느 정도 성능을 희생할 수밖에 없었으며, 현재 주된 희생양은 메모리다.

그런데 32비트 시스템의 가용 메모리 크기와 워킹 세트 크기는 발전하고 있는 인터넷 시스템의 요구를 수반할 만큼 충분하지 않다. 자연스럽게 64비트 컴퓨팅을 사용할 수밖에 없는 것이다.

64비트 시스템은 32비트에 비교할 수 없을 만큼 넓은 메모리 공간을 갖고 있다. 따라서, 이러한 장점을 최대한 활용한다면 아주 효율적인 비즈니스 응용 프로그램을 제작할 수 있다.

다음 회에서는 64비트의 최적화된 CPU 활용 전략을 32비트와 비교해 설명하겠다. @