Author : Daeguen Lee

(Any action violating either copyright laws or CCL policy of the original source is strictly prohibited)

 

(image source : Micron Crucial)

 

오늘날 컴퓨터 하드웨어의 발전속도가 정체되었음을 시사하는 지표는 한두 가지가 아닙니다. 익숙한 인텔 CPU는 벌써 몇 세대째 한자릿수의 성능향상률을 기록하는데 그쳐 있고, 5년 전 공랭식 쿨러의 최고봉이라 일컬어지던 것들은 현재까지도 그 위상에 흔들림이 없으며, 디스플레이나 파워 용량, 하다못해 널리 사용되는 하드디스크의 평균 용량까지도 분명 과거에 비하면 더디게 발전하고 있습니다. 이러한 현상은 PC의 역사에 비춰 봐도 분명 이례적인 흐름입니다.


이 글을 읽는 독자 여러분 가운데는 최근 주류 시장에 등장한 DDR4의 존재가 익숙치 않고 혼란스러운 분이 계시리라 짐작합니다. 오랫동안 DDR3에 익숙해져 있었는데 메모리 규격이 바뀐다니 괜히 번거로운 일만 생긴 것 같고 그러시죠. 하지만 분명한 것은 DDR3의 10년에 달하는 장기집권이 메모리 역사를 통틀어 유례없는 사건이었다는 점입니다. 그리고 이러한 정체는 당연히 주류 하드웨어 시장의 정체에 맞물린 것이었습니다.


이 글에서는 2000년 이후 메모리의 진화 과정을 간단히 짚어보고, 이론으로부터 실제 성능을 이끌어낼 수 있는 수학적 모델을 구상한 후 그것을 토대로 오늘날의 메모리 시장을 재평가해 보려 합니다. 다소 딱딱한 내용과 맞물려 글이 대체 어느 방향으로 흘러가는지, 읽다 보면 어지러워질 때가 있겠지만, 인내심을 가지고 읽다 보면 여러분께 어떤 명쾌한 시사점이 시나브로 가 닿으리라 기대하며 글의 첫머리를 써 봅니다. 

 

 

<목차>

 

1. 메모리 규격의 진화

2. 램타이밍 항목의 이해 (1) : Command Rate, tRAS, tRP, tRCD, CL - 이론

3. 램타이밍 항목의 이해 (2) : Command Rate, tRAS, tRP, tRCD, CL - 실제

4. 램타이밍 항목의 이해 (3) : Refresh Time, tRFC

5. 성능 시뮬레이션 모델 만들기 (1) : 클럭, 램타이밍

6. 성능 시뮬레이션 모델 만들기 (2) : DDR 규격

 

 

1. 메모리 규격의 진화


오늘날 메모리 규격의 대전제가 되는 아키텍처는 'SDRAM' 이라는 것입니다. 풀어서 쓰면 Synchronized Dynamic Random Access Memory 인 이것을 깊이 설명하는 것은 이 글의 본질에서 비껴나는 관계로 이 글에서는 생략합니다. 어차피 여기서 다룰 메모리는 2000년 이후의 규격들 - Single Date Rate (SDR) SDRAM, Double Date Rate (DDR) SDRAM 및 그 뒤를 잇는 DDR2, DDR3, DDR4 SDRAM들이기 때문에 SDRAM이 아닌 게 없습니다. 이들 규격의 '차이' 를 알아보고자 하는 것이니 공통점에 관해 장황하게 설명할 필요는 없겠죠.

 

메모리의 구조에 대해 설명하기 앞서 이 점을 숙지합시다. 메모리의 작동을 설명하기 위해서는 최소한 3가지의 클럭 도메인이 관여됩니다. 이들은 아래와 같습니다.

 

1. 셀 (메모리 내 비트가 저장되는 최소단위) 클럭

2. 입출력 버퍼 클럭

3. 외견상 클럭 (유효클럭)

 

SDR로부터 DDR4에 이르기까지, 대표적인 클럭 표준마다 위 세가지 클럭이 각각 어떻게 진화해 왔는지 살펴보는 것이 이 글의 첫번째 포인트입니다. 아래의 표를 보시죠.

 

 

위 표에 나타난 가장 놀라운 사실은 2000년대 이래 셀의 작동속도가 100~200MHz 범위를 벗어난 적이 거의 없다는 것입니다. 외견상 표시되는 유효클럭은 과거의 100MHz에서 오늘날 3200MHz까지 무려 32배 이상 성장해 왔으나 가장 기초적인 셀 단위에서는 고작 2배 정도의 성장에 그쳤다는 점, 많은 분들의 상식을 깨는 첫번째 진실입니다.

 

셀, 그러니까 본질적으로 이것을 구현하는 컨덴서(캐퍼시터)는 전하를 저장하고 (=1) 방전시키는 (=0) 일련의 동작으로 2진수 데이터를 표현하는 장치입니다. 여기서 물리적으로 전하가 충전되고 방전되는데 시간이 소요되기 때문에 작동속도가 일정 수준 이상으로 올라가기 어렵습니다. 이를 해소하는 가장 쉬운 방법은 개별 컨덴서의 충전용량을 줄이는 것이지만 이 경우 셀 전체의 안정성이 저해되는 문제가 있습니다.

 

앞서 짚었듯 SDR부터 DDR4에 이르기까지 셀의 작동속도는 최대 266MHz 수준을 넘지 못했고, 이마저도 DDR2/3 집권기의 후반에 반짝 등장했을 뿐 대부분의 기간 동안 200MHz를 상한으로 해 왔습니다. 셀의 느린 작동속도를 극복하고 메모리의 속도를 끌어올리기 위해 도입된 방법은 바로 2, 4, 8개의 셀을 병렬로 묶어 직렬 스트림을 생성하는 것이었습니다. 보조기억장치의 경우에도 유사한 적용례가 있으니 바로 'RAID' 라는 기술입니다. 다시 말해 개별 셀 차원에서 일종의 RAID를 구성해 대역폭을 늘리기 시작한 것입니다. 이로써 셀의 작동속도보다 입출력 버퍼의 작동속도를 상대적으로 높여 가게 된 것이죠.

 

 

 

(image source : Synopsys)

 

DDR 규격에서 Prefetch 구성이 2n이 되었고 DDR2는 4n, DDR3은 8n이 되었습니다. 즉 DDRx 구성이 2^x개의 셀을 RAID로 묶어 온 전례를 따르자면 DDR4는 16n RAID를 구현해야 했겠지만 어쩐 일인지 DDR4는 8n 구성을 채택하고 있습니다. 대신 그대로 DDR3 수준에 머물러 있는 것은 아닙니다. 정확히 말하자면 DDR4는 (행, 열과 함께 메모리의 주소를 정의하는 단위인) '뱅크' 레벨에서 일종의 2n RAID를 재차 구현하고 있습니다. 즉 8 x 2 = 16의 효과를 얻는 것입니다.

 

왜 직관적으로 16n Prefetch를 도입하지 않고 8n x 2 구조를 채택했을까요? 이렇게 된 이유를 전부 알 수는 없지만 짐작은 해볼 수 있습니다. 바로 '셀 묶음'의 크기가 커질수록 발생가능한 오버헤드가 그에 비례해 커질 것이기 때문이죠. 여기서 오버헤드란 성능뿐 아니라 물리적인 복잡도까지 포함하는 개념입니다. (멀티플렉서의 입출력단이 두배 증가하면 이를 위한 '연결'은 그보다 훨씬 큰 비율로 증가합니다.)

 

다시 말해, 설령 최초 개발단계에서 기술자들이 16n 구성을 염두에 두었더라도 막상 만들고 보니 그들이 상상한 만큼의 성능으로 환산되지 않았거나, 적어도 비용투입 대비 산출이 현저히 떨어지는 문제가 있었을 수 있습니다. 어쨌든 확실한 것은 현재 표준화되어 출시된 DDR4는 메모리 내부적으로 '듀얼채널'이 구현된 DDR3이라 보아도 틀리지 않다는 점입니다. 이것을 '뱅크 그룹'이라 하는데 GDDR5 규격에서 처음 도입된 기술이 이식된 것으로, 이에 관해 더 깊이 파고들면 글의 주제를 벗어나는 관계로 생략합니다. 단지 이 대목에서 GDDR5의 유효클럭이 실 클럭의 4배라는 점을 떠올리셨다면 완벽히 이해하신 겁니다.

 

한편, 다시 십여년 전으로 돌아가 봅시다. 타임머신의 조그셔틀을 맞출 지점은 SDR에서 DDR로 막 넘어가던 시점입니다.

 

 

셀 차원에서 2n RAID 구성을 구상하게 되고, 일거에 메모리 대역폭이 두 배 가까이 늘게 되었는데 이는 곧 입출력 버퍼의 작동속도가 그에 비례해 늘어나야 했음을 의미합니다. 다시 말해 셀과 똑같이 100~133MHz로 작동하던 입출력 버퍼의 작동속도가 단숨에 200~266MHz로 뛰어올라야 했다는 것입니다. 하지만 그렇게까지 급격히 클럭을 올릴 수 없는 (당시로서는) 물리적인 한계가 있었고 이에 대응방안으로 모색된 것이 입출력 버퍼의 클럭을 유지하되, 클럭 사이클의 라이징 엣지 (0->1) 와 폴링 엣지 (1->0) 양쪽 모두에 데이터를 전송하도록 하는 아이디어였습니다. 이것이 Double Date Rate (DDR) 의 기원입니다.


 

2. 램타이밍 항목의 이해 (1) : Command Rate, tRAS, tRP, tRCD, CL - 이론


이전 장에서 메모리 규격의 변천사를 간단히 살펴보았습니다. 이 장에서는 메모리의 작동 원리에 관해 살펴보도록 하겠습니다.

 

장 제목은 램타이밍 항목의 이해인데 왜 생뚱맞게 작동원리를 보자는 걸까, 궁금한 분이 계실지 모르겠습니다. 램타이밍이라는 것은 실은 메모리의 작동원리를 각 스테이지별로 분절해 설명하는 도구에 가까운 것이기 때문입니다. 즉 각 램타이밍 항목이 무엇을 의미하는지 살펴보면 자연스레 메모리의 작동 원리로 이어지게 되고, 반대로 메모리의 작동 원리를 스텝 바이 스텝으로 이해하면 그것이 곧 램타이밍 항목들에 대한 이해가 됩니다. 최대한 간단하고 쉬운 말로 설명해 보도록 노력하겠습니다.

 

메모리는 뇌가 없습니다. 무슨 말인고 하니 메모리는 독자적으로 판단하거나 연산하는 장치가 아니라는 뜻입니다. 이러한 역할을 맡는 장치로는 아주 유명한 CPU라는 것이 있죠. 메모리는 본질적으로 CPU의 명령을 받아 CPU가 필요로 하는 명령어 스트림이나 데이터 스트림을 인출해 주는 (또는 CPU가 쓰라고 명령한 것을 기록하는) 장치입니다. 이러한 상하관계에서 CPU의 명령을 받아 메모리를 컨트롤하는 장치를 '메모리 컨트롤러' 라고 합니다. 편의상 메모리 컨트롤러 역시 CPU의 일부인 것으로 간주하고 설명을 이어갑니다.

 

...그러니까 메모리는 메모리 컨트롤러로부터 명령을 받아 읽기/쓰기를 수행합니다. 한편 메모리 칩을 구성하는 셀은 마치 스프레드시트처럼 행 (Raw) 과 열 (Column) 로 구성되어 있습니다. 메모리컨트롤러가 무언가를 읽거나 쓰기 위해 셀에 접근하려면, 행 주소를 찾아낸 후 그 행 안에서 열 주소를 찾아 최종적으로 목적지인 셀에 도착하게 됩니다. 이 과정을 도식화하면 아래와 같습니다.

 

 

위 그림을 마음 속에 담아두고 아래의 설명을 보도록 합시다. 이 간단한 그림에서부터 Command Rate, tRAS, tRP, tRCD, CL의 다섯가지 램타이밍 항목이 설명됩니다.

 

Command Rate : 메모리 컨트롤러가 발행한 명령이 메모리에 접수되기까지의 소요시간을 의미합니다. 표기되는 값의 단위는 작동속도(클럭)의 한 사이클입니다. 즉 CR2로 정의되었다면 두 클럭사이클이 경과한 후 메모리컨트롤러의 명령이 메모리에 가 닿는다는 뜻이 되겠죠. 사이클 단위를 실제 시간 단위(초)로 환산하려면 사이클 값을 작동속도로 나눠 주어야 합니다. 예컨대 CR2인 메모리가 1000MHz의 유효클럭으로 작동한다면 실제 소요되는 시간은 2(사이클) ÷ 1,000,000,000(Hz) = 0.000000002초 = 2ns가 됩니다. 이 값은 작을수록 성능이 좋으며, 램타이밍 항목 중 성능에 영향을 가장 크게 미치는 것이기도 합니다.


Row Address Strobe Time : 줄여서 tRAS라 불리는 값입니다. 셀이 액세스되는 동안 그 셀이 속한 행은 반드시 액티브 상태로 유지되어야 하는데, 이를 위해 (액세스 전) 미리 Precharge 된 행이 액티브 상태를 유지해야만 하는 최소한의 시간을 규정한 것입니다. 다시 말해 Precharge와 Precharge 사이의 주기를 규정한 값이고, 재차 다시 말하자면 이 시간 이내에 셀 액세스가 끝날 수 있도록 나머지 램타이밍 값이 설정되어 있어야 합니다. 따라서 보통 CL + tRCD + tRP의 합보다 넉넉히 크게 주어지고, CL + tRCD + tRP와 조화를 이룰 경우 성능에 미치는 영향이 드러나지 않으나 지나치게 크면 성능이 떨어집니다. CR과 마찬가지로 사이클 단위로 매겨집니다.


RAS Precharge Time : 줄여서 tRP라 불리는 값입니다. 앞서 tRAS 값을 주기로 하여 행 Precharge ("Row Adress Strobe Precharge") 가 수행된다고 했는데 그 소요시간을 의미합니다. 역시 사이클 단위로 표기되며 작을수록 성능이 좋습니다.


Row Address to Column Address Delay Time : 줄여서 tRCD라 불리는 값입니다. 위에서 그림으로 설명할 당시 메모리컨트롤러는 셀을 액세스하기 위해 행 주소를 찾고, 그 후 열 주소를 찾는다고 했었죠. 여기에 소요되는 딜레이를 의미합니다. 역시 사이클 단위로 표기되며 작을수록 성능이 좋습니다.


Column Access Strobe Latency : 줄여서 CAS Latency, 더욱 줄여 "CL" 이라 부르는 값으로 한 행 내에서 첫 열부터 마지막 열까지를 액세스하는 데 소요되는 총 시간을 의미합니다. 역시 사이클 단위로 표기되며 작을수록 성능이 좋습니다. CR과 함께 성능에 영향을 크게 미치는 항목 중 하나입니다. 아래 표는 시중에서 흔히 구할 수 있는 DDR3/4 규격별 클럭/CL값 조합에 따른 CL의 시간값을 나타낸 것입니다. 같은 색으로 칠해진 것들을 비교해 보면 더 높은 클럭+더 느슨한 CL값을 갖는 제품이 낮은 클럭+타이트한 CL값을 갖는 것보다 CL의 시간값 자체는 오히려 더 타이트하기도 하다는 점을 보여주고 있습니다.

 

 

 

 

3. 램타이밍 항목의 이해 (2) : Refresh Time, tRFC


지금까지 살펴본 5종의 램타이밍이 메모리의 작동과정을 어떻게 구성하는지 그림으로 나타내 보겠습니다.

 

 

 

 

위 그림을 말로 풀어 설명하면 메모리컨트롤러가 셀 액세스 명령을 발행하고 / 행 주소를 찾고 / 열 주소를 찾아서 / 해당 셀을 액세스하는 일련의 과정입니다. 보통 램 타이밍을 대표하는 항목은 위에서 살펴본 것의 역순인 CL-tRCD-tRP-tRAS-CR 순으로 나타내어 지는 경우가 많습니다. 예컨대 CL9-10-10-27-1T 따위로 나타내어지는 양식은 그러한 순서를 반영한 것입니다. 그렇다면 왜 뒤집어 놓은 것일까요? 이를 위해서는 몇 가지 작동 시나리오를 생각해 보아야 합니다. 8개의 셀을 액세스하는 경우를 가정해 보겠습니다.

 

 

첫째로, 위 그림과 같은 상황을 생각해볼 수 있습니다. 메모리컨트롤러가 접근하고자 하는 셀이 운 좋게도 이미 열려있는 행 안에 있다면 앞서 행을 열기까지 수행한 tRP, tRCD를 생략할 수 있습니다. 이 과정에서는 CL만이 반복되는데 보통 파이프라인이 구현되어 있어 최초 1회 이후에는 CL에 의한 영향이 그리 드러나는 편도 아닙니다. 이러한 작동을 '버스트 모드' 라고 하며 일반적으로 전체 워크로드의 50% 가량을 차지합니다.

 

 

 

두번째로는 같은 행에 존재하지는 않지만 같은 페이지에 존재하는 경우를 생각할 수 있습니다. 이 경우 행 주소를 다시 얻고, (약간의 딜레이를 거쳐) 열 주소를 얻어야 하므로 tRCD-CL 단계를 반복해야 합니다. 앞의 작동 시나리오와 비교하면 tRCD의 영향이 추가된 것입니다. 이러한 작동 시나리오는 전체 워크로드의 30% 가량을 차지합니다. 위의 두 그림 중 첫번째는 '그나마' 운 좋게 행 주소를 한번만 다시 얻은 경우이고, 두번째는 매번 새로 행 주소를 얻어야 하는 최악의 상황을 가정해 본 것입니다. 위의 경우 총 58사이클이 소요되었고 아래는 172사이클이 소요되었습니다.

 

 

 

마지막으로 데이터가 전혀 새로운 곳에 있어 tRP-tRCD-CL의 전 과정을 답습해야 하는 작동 시나리오가 있습니다. 이러한 작동 시나리오는 전체 워크로드의 20% 가량을 차지합니다. 운이 좋으면 전 과정을 한번만 반복해 68사이클만에 작업이 완료되지만 운이 나쁘면 전 과정을 일곱번 반복해야 할 수 있고, 이 경우 소요되는 사이클은 최장 242사이클이 됩니다.

 

(※ 이상의 3개 작동 시나리오는 8개의 셀만을 액세스하는 것으로 가정한 것입니다. 실제로는 더욱 다이나믹한 변화가 있을 수 있습니다.)

 

전체 작동 시나리오를 통틀어 보면 어쨌든 CL이 등장하는 횟수가 가장 많습니다. 버스트 모드에서마저 CL은 꼬박꼬박 사용되기 때문이죠. 반면 tRCD는 한 행 안에서 액세스될 때에는 생략 가능하고, tRP는 행이 다르더라도 페이지가 같으면 재차 생략 가능합니다. 따라서 CL에 의한 영향이 가장 크고, tRCD와 tRP가 차례로 그 뒤를 이음을 알 수 있습니다. 먼저 지적한 바 있듯 tRAS는 직접 성능에 관여하지는 않습니다. 따라서 메모리 스펙표에 CL-tRCD-tRP-tRAS 순으로 표기되는 것은 성능에 가장 영향을 많이 주는 것 순으로 나열한 합리적인 표기 순서라 할 수 있겠습니다.

 

 

4. 램타이밍 항목의 이해 (3) : Refresh Time, tRFC


이전 장에서 메모리 셀은 본질적으로 자연방전되는 특성이 있어 일정한 주기를 두고 덧써 (Refresh) 주어야 한다는 점을 지적했었습니다. JEDEC이 규정한 바에 따르면 메모리 셀은 적어도 수십~수백 ms에 한번씩은 덧쓰기를 수행해 주어야만 합니다. 하지만 메모리를 구성하는 수십억개의 셀 (메모리의 용량을 비트로 환산하면 그대로 셀의 갯수입니다) 을 단번에 충전하는 것은 엄청난 전력 소비를 동반하는데다 인터페이스 자체에도 무리를 줍니다. 따라서 SDRAM은 '페이지'를 한 단위로 하여, 보다 짧은 주기 (μs, ns 단위) 로 개별 페이지를 순회하며 덧쓰는 정책을 사용하고 있습니다.

 

램타이밍 항목 중 Refresh Time 또는 tREF라는 이름을 가진 것은 바로 이 주기 (개별 페이지를 순회하며 덧쓰는 주기) 를 정하는 변수입니다. 덧쓰는 주기가 짧을수록 데이터 안정성은 올라가지만 (=자주 덧써 주므로) 작동속도가 느려집니다. (=자주 덧써야 하므로) 다른 램타이밍 항목이 소요되는 클럭사이클 갯수를 단위로 삼은 것과 달리 이 값은 직접 시간값을 단위로 사용한다는 점, 그리고 값이 작을수록 성능이 떨어진다는 점을 기억하시기 바랍니다. 여타의 램타이밍 항목들과는 반대되는 성질이죠.

 

만약 셀의 충전주기 상한이 64ms이고 메모리 모듈 내에 존재하는 총 페이지 수가 16,384개라면 64(ms) ÷ 16,384 = 0.0039(ms), 즉 매 3.9μs마다 페이지를 순회하며 덧쓰기를 수행해야 합니다. 실제로 대부분의 메인보드는 3.9μs의 배수가 되게끔 tREF를 설정할 수 있도록 옵션을 제공하고 있습니다. 바이오스 표기상 ms로 나타나는 경우가 더러 있는데, 밀리초가 아니라 마이크로초 단위라는 점 유념해야겠습니다.

 

 

한편, 이와 비슷한 이름의 tRFC (Refresh Cycle Time) 는 그 덧쓰기 자체에 소요되는 시간을 규정한 것으로 다시 사이클 단위를 채택합니다. 당연히 작을수록 성능이 높구요. 바로 위의 tREF와 함께 이 둘은 '메이저 램타이밍'을 제외한 나머지 중 성능에 큰 영향을 주는 유일한 요소입니다.

 

 

 

마지막으로, 램타이밍 값이 클럭사이클 단위로 나타내어질 경우 그 속도는 클럭에 대해 상대적인 값임을 다시 한번 강조하고자 합니다. 무조건 CL10보다 CL8이 좋은 게 아니라, 클럭에 대한 상대적인 비율로 따져야 한다는 뜻입니다.

 

예컨대 1000MHz CL8의 경우 CAS Latency 소요시간은 0.000000008초 (=8ns) 이지만 2000MHz CL10의 경우 그 소요시간은 0.000000005초 (=5ns) 로 오히려 더 짧습니다. 물론 클럭이 같은 경우에는 당연히 사이클값이 작은 쪽이 성능이 좋겠지요.

 

지금까지 살펴본 내용을 이미지로 표현하면 아래와 같습니다.

 


tREF는 보통 직접 시간값으로 나타내어지므로, 다른 램타이밍 항목값이나 메모리의 유효클럭이 어떻게 설정되든 관계없이 절대적으로 적용되는 일종의 '쿨타임' 주기에 비유할 수 있습니다. 쿨타임이 자주 돌아올수록 작업 수행이 중단되니 성능이 저하되는 것이 당연하고, 쿨타임의 지속시간은 tRFC 만큼입니다. 메모리가 정상적으로 작동되는 시간은 이 쿨타임을 제외한 나머지 시간 동안입니다.


따라서, 일정한 시간 동안 (=Δt) tRFC에 의한 지연은 "Δt ÷ tREF" 회 만큼 발생하고 한 회당 지속시간은 "tRFC ÷ 유효클럭" 이므로 총 지연시간은 아래와 같습니다.


총 Refresh 지연 시간

= (tRFC ÷ 유효클럭) x (Δt ÷ tREF) = tRFC·Δt / 유효클럭·tREF

 

 

5. 성능 시뮬레이션 모델 만들기 (1) : 클럭, 램타이밍


이전 장의 마지막 그림에서, 편의상 쿨타임을 한데 몰아 두고 나머지 시간 동안 메모리가 (쿨타임 없이) 연속적으로 작동한다고 가정합시다.

 


이 '나머지 시간'의 배분은 메모리 액세스의 형태가 시퀀셜인지 랜덤인지에 따라서 다시 크게 달라집니다. 시퀀셜의 경우 일단 한번 행이 Precharge되어 액티브하게 되면 계속 그 안의 셀을 읽고 쓸 수 있는데, 각 액세스마다 CL만큼의 지연시간이 있지만 파이프라인화 되어있기 때문에 결국 CL로 인한 오버헤드가 점차 0에 수렴합니다. 나아가 시퀀셜 액세스가 길어지면 길어질수록 CL뿐만 아니라 CR, tRP등으로 인한 오버헤드도 0에 수렴하게 되고 대신 대역폭을 결정짓는 유효클럭에의 의존도가 100%에 가깝게 됩니다. 반대로 랜덤 액세스의 경우 유효클럭보다 램타이밍의 영향을 상대적으로 더 많이 받게 되는데, 이를 간단한 시뮬레이션으로 알아봅시다.

 

 

위 그림은 메모리컨트롤러가 단 하나의 셀에 단 하나의 비트만을 읽거나 쓰도록 하는 경우를 나타냅니다. 즉 1비트 랜덤 액세스로 극단적인 랜덤 액세스 시나리오입니다. 보시다시피 유효클럭이 1600MHz와 2000MHz로 차이가 나는 경우라도, 램타이밍이 그에 정비례한다면 성능 차이가 거의 없으며 (1600 CL8과 2000 CL10의 성능이 비슷하게 나옴) 심지어 낮은 유효클럭이더라도 램타이밍이 그 이상으로 낮으면 성능이 더 좋기까지 합니다. 간단히 말해 극단적인 랜덤 액세스 시나리오 하에서는 램타이밍이 클럭보다 더 중요합니다.

 

 

위 그림은 메모리컨트롤러가 한 행 안에서 8비트를 순차적으로 쓰는 경우입니다. 읽기/쓰기가 이뤄지는 시간이 유효클럭에 비례해 줄어들면서, 앞서 살펴본 시나리오보다 클럭에 의존하는 경향이 다소 늘었고 그 결과 2000 CL8 메모리의 성능이 1600 CL6을 앞지르기 시작했습니다. 또한 클럭과 램타이밍의 비율이 엇비슷한 1600 CL8과 2000 CL10도 클럭이 높은 쪽의 성능이 더 좋아지고 있습니다.

 

 

위 그림은 메모리컨트롤러가 한 행 안에서 64비트를 순차적으로 쓰는 경우입니다. 이제는 램타이밍이 가장 느슨한 2000MHz 메모리조차 가장 타이트한 램타이밍을 갖는 1600MHz 메모리보다 좋은 성능을 보이는 것을 확인할 수 있습니다. 지금까지의 결과를 요약하자면 시퀀셜 액세스의 비중이 클수록 클럭의 영향력이 커지며 랜덤 액세스의 비중이 클수록 램타이밍의 영향력이 커집니다.

 

앞의 시나리오와 이 시나리오를 살펴보면, 버스트 모드로 작동할 때 메모리의 총 소요 사이클을 구하는 식은 대략 아래와 같이 나타낼 수 있습니다.

 

버스트 모드 총 소요 사이클

= Command Rate + tRP + tRCD + CL + 비트 수 - 1

 

시퀀셜 액세스의 크기가 증가할수록 총 작업시간은 그에 정비례하는 방향으로 수렴해 갑니다. 시퀀셜 액세스의 수행시간은 유효클럭에 정확히 반비례하기 때문에 총 작업시간 역시 유효클럭의 반비례에 수렴하게 됩니다. 극단적으로 버스트 모드로 액세스되는 비트의 수가 무한대에 가까워진다면, 램타이밍에 의한 영향은 완전히 사라지고 클럭에만 비례하는 성능을 보이게 될 것입니다.

 

버스트 모드가 아닌 경우는 다소 변수가 많아지는데, 행이 다르지만 페이지가 같은 경우 tRP 단계를 생략할 수 있음을 살펴본 바 있습니다. 이 경우는 아래와 같아지겠습니다.

 

페이지 내 액세스시 총 소요 사이클

= Command Rate + (최초 행 진입 : tRP + tRCD + CL + 비트 수 - 1)

+ (두번째 행 진입 : tRCD + CL + 비트 수 - 1)+ ...

 

마지막으로, 서로 다른 페이지간 액세스는 가장 복잡한 형태가 됩니다.

 

페이지간 액세스시 총 소요 사이클

= Command Rate + {최초 페이지 진입 : (최초 행 진입 : tRP + tRCD + CL + 비트 수 - 1) + ...}

+ {두번째 페이지 진입 : (최초 행 진입 + tRP + tRCD + CL + 비트 수 - 1) + ...} + ...

 

 

6. 성능 시뮬레이션 모델 만들기 (2) : DDR 규격


이전 장에서 만든 모델이 썩 괜찮아 보이지만, 아직 중요한 마지막 단계가 남았습니다. 바로 DDR 규격별 성능 차를 반영하는 것입니다.

 

DDR 규격별 성능 차를 계산하는 수식을 만들려면 우선 각 규격간의 차이를 살펴보아야 합니다. 마침 저희는 1장에서 이에 관해 충분히 살펴본 내용이 있습니다. 요점을 다시 정리하자면 각 규격별로 주요한 차이가 되는 것은 셀의 작동속도, 그리고 한 Prefetch 그룹으로 묶인 셀의 갯수입니다. (DDR4의 경우 뱅크 그룹을 고려해야 하나 여기서는 생략합니다.)

 

이 두 변수를 성능에 영향을 주는 것으로 만들기 위해 우리는 두 가지를 가정해야 합니다. 첫째로 셀 자체에서 발생하는 딜레이가 있으며, 이는 셀의 작동속도에 비례한다는 가정입니다. 다시 말해 DDR2-800과 DDR3-800의 경우 앞 장의 모델에로는 성능 차를 구할 수 없지만, 새로 만드는 모델에서는 둘의 셀 클럭이 다른 만큼 딜레이의 차이가 발생하고 결과적으로 성능 차이로 이어질 것입니다. 이들의 경우 DDR2-800의 셀 클럭은 200MHz, DDR3-800의 셀 클럭은 100MHz이므로 DDR3쪽이 딜레이가 두배 길어집니다. 당연히 성능이 더 낮아지겠죠.

 


또한 셀 레벨에서의 Prefetch 병렬화에 따른 오버헤드는 'RAID'로 묶인 셀 갯수에 비례한다고 가정할 수 있겠습니다. DDR은 2n, DDR2는 4n, DDR3/4는 8n이니 각각 SDR 대비 2배, 4배, 8배씩의 오버헤드가 있다고 보면 DDR 규격이 진화할수록 성능 계산에서는 불리해지는 결과가 나타납니다. 단 하나, DDR4만이 DDR3 대비 '크게' 불리하지 않은 결과를 보일 것입니다. (※ 실제로는 뱅크 그룹 구현에 따른 딜레이가 있을 수 있지만, 16n의 복잡도보다는 8n+1이 훨씬 작다고 가정한 것입니다.)

 


셀 차원에서의 딜레이 및 Prefetch 복잡도에 따른 오버헤드 항들을 앞 장의 모델에 단순 합산해줄 경우 식은 아래와 같은 모양이 됩니다.

 

총 소요시간

= 총 Refresh 지연 시간

+ (셀 딜레이 사이클 + Prefetch 오버헤드 사이클 + 메모리 작동 총 소요 사이클(버스트, 페이지내, 페이지간 비율 반영)) ÷ 유효클럭

 

이 글에서는 더 자세하게 들어가지는 않겠습니다만, 지금까지 만든 모델을 통해 얻은 시뮬레이션 결과는 상당히 혼란스럽습니다. 매 세대 새로운 DDR 규격이 등장했을 때, 새로운 규격의 최하위 표준은 이전 규격의 최상위보다 확실히 빠르다고 보기는 어렵습니다. 심지어 유효클럭이 앞서는 경우라도 말이죠. 오히려 '경계선'에 한해서만큼은 매 세대마다 전세대가 성능이 더 좋은 '세대 절벽'을 보였다고 보는 편이 더 가까울 것입니다.

 

이는 그간 새로운 DDR 규격의 (도로 낮아진) 낮은 셀 클럭과 Prefetch 병렬화 심화에 따른 오버헤드 증가, 그리고 높아진 유효클럭의 반대급부로 풀어진 램타이밍 등이 복합적으로 작용한 결과입니다. 다만 셀 클럭이 도로 낮아지고 램타이밍이 느슨해지면서 향후 유효클럭을 끌어올릴 여력이 확보되어 장기적으로 새 규격으로의 세대교체가 가능했던 것이죠. 메모리를 제외한 나머지의 발전속도가 더뎌서 메모리가 이런 '반보 전진' 만으로도 발맞춰올 수 있던 것인지, 메모리가 느리게 나아간 덕분에 전체 PC시장의 발전이 더뎠던 것인지를 따지는 것은 닭이 먼저인지, 알이 먼저인지를 따지는 것만큼이나 의미없는 논쟁일 것입니다. 분명한 것은 현상 그 자체뿐입니다.


설상가상 DDR4부터는 여러 오버헤드로 인해 Prefetch 병렬화를 심화하는 길도 사실상 막혔습니다. 비슷한 구조를 가졌던 GDDR5의 미래는 DDR4에게 실마리가 될 수 있었겠지만 지금으로써는 아예 HBM에 자리를 내 주며 시장에서 퇴출되는 것이 시간 문제인 실정입니다. DDR4 역시 같은 전철을 밟게 될까요. 사실상 물리적 구조 변경을 배제하고는 구조 혁신을 논할 수 없게 된 가운데, 미래의 메모리는 어떤 방향으로 발전해갈지에 대해서도 추후 다뤄볼 기회가 있길 바랍니다.

 

이상으로 글을 마칩니다. 읽어 주셔서 감사합니다.

 

 

※ 이 글에서 사용된 모델의 개발과정, Raw Data 및 이용 문의는 ChiefArchitect [at] InsideYourDevice.com 으로 주시기 바랍니다.

 

//

 

저작자 표시 비영리 동일 조건 변경 허락
신고