캐시 메모리
1. 개요[편집]
Cache memory.
컴퓨터 시스템의 성능을 향상시키기 위해 주로 CPU 칩 안에 포함되는 빠르고 작고 비싼 메모리이다. 프로그램에서 직접적으로 읽거나 쓸 수 없고 하드웨어의 메모리 관리 시스템이 내부적으로 제어한다. 대부분 프로그램은 한 번 사용한 데이터를 다시 사용할 가능성이 높고, 그 주변의 데이터도 곧 사용할 가능성이 높은 데이터 지역성을 가지고 있다. 데이터 지역성을 활용하여 캐시보다는 느리지만 용량이 큰 메인 메모리에 있는 데이터를 캐시 메모리에 불러와 두고, CPU가 필요한 데이터를 캐시에서 먼저 찾도록 하면 시스템 성능을 향상시킬 수 있다.
흔히 1단계 캐시(L1 캐시)와 레지스터를 혼동하는데 완전히 다른 개념이다. L1 캐시에 있는 데이터도 궁극적으로는 레지스터에 올라가야 CPU에서 처리할 수 있으며, 레지스터 내 데이터는 프로그램 코드에서 직접 제어할 수 있다. 메모리 형태를 가지고 있는 L1 캐시와는 다르게 레지스터는 CPU 아키텍처에 따라서 종류와 의미가 다르다.
또한 가상메모리에서는 DRAM이 디스크의 캐시로서 동작한다.
2. 배경[편집]
CPU의 클럭 속도가 매우 빨라짐에 따라 CPU 밖에 있는 DRAM과의 속도 차이가 현저하게 증가하였는데, 이 때문에 CPU 클럭 속도를 아무리 올려도 DRAM에서 데이터를 빠르게 제공해 주지 못하여 전체 시스템 성능이 증가하기 어렵게 되었다. 메모리 기술은 주로 DRAM 기술, SRAM 기술로 나뉘는데, DRAM은 가격은 싸지만 속도가 느리고, SRAM은 속도는 빠르지만 가격이 비싸다는 단점이 있었다. 그래서 SRAM을 사용자가 직접 장착하게 하는 대신, CPU와 DRAM 사이에 SRAM을 별도로 두어서 DRAM의 데이터를 직접 접근하는 것보다는 빠르게 접근할 수 있도록 했다. 여기에 사용하는 SRAM을 캐시 메모리라고 한다. 폰 노이만 은 1946년 그의 논문 "Preliminary Discussion of the Logical Design of an Electronic Computing Instrument" 에서 캐시 메모리의 필요성을 예견했다. 역시 굇수 혼자 다 해먹네
3. 작동 원리[편집]
캐시 메모리는 데이터 지역성(Locality)의 원리를 사용한다. 데이터 지역성은 대표적으로 시간 지역성(Temporal locality)과 공간 지역성(Spatial Locality)으로 나뉘는데, 시간 지역성이란 for나 while 같은 반복문에 사용하는 조건 변수처럼 한 번 참조된 데이터는 잠시 후에 또 참조될 가능성이 높다는 것이고, 공간 지역성이란 A[0], A[1]과 같은 데이터 배열에 연속으로 접근할 때 참조된 데이터 근처에 있는 데이터가 잠시 후에 사용될 가능성이 높다는 것이다.
쉽게 예를 들자면 무지하게 지랄맞고 부지런한 상사가 2010년 재무결산 보고서를 가져오라고 했을 때, 무슨 일인지는 몰라도 또 가져오라고 할지도 모르니까 2010년 재무결산보고서를 일단 준비해 놓고, 2009년이나 2011년, 2012년 재무결산보고서도 가져오라고 할지 모르니까 그것도 준비해 놓는 식이다.
또 다른 예로는 캐시는 지갑이라고 생각하면 된다. 지갑 혹은 주머니가 없다면 우리가 현금이 필요할 때마다 매번 은행이나 ATM에 가야 할 것이다. 이는 당연히 매우 귀찮고 시간도 많이 걸린다. 하지만 우리가 현금을 지갑에 넣고 다님으로써 시간을 절약할 수 있다.
CPU가 메모리에 데이터를 요청할 때, DRAM에 접근하기 전에 일단 캐시 메모리에 접근하여 데이터 존재 여부를 확인한다. 캐시 메모리는 메인 메모리인 DRAM보다는 그 사이즈가 매우 작아서 데이터를 모두 저장할 수 없다. DRAM이 보통 4~16GB 정도인데 인텔 i5, i7에 들어가는 캐시 메모리는 32KB ~ 8MB 정도이다. 캐시 메모리는 DRAM의 데이터 일부를 가지고 있다가 CPU가 요청한 데이터가 캐시 메모리에 없으면 CPU를 잠시 기다리게 한 후 DRAM에서 해당 데이터를 가져온 후 CPU에게 넘겨 준다. CPU는 캐시의 존재를 알고 있지만, 그 위에서 실행되는 프로그램은 메모리 주소만 지정할 수 있지 프로그래머가 캐시를 직접 지정할 수는 없다. 이렇게 그 존재가 외부에 드러나지 않기 때문에 캐시 메모리는 CPU에 투명(transparent)하다고 한다. 투명하지 않은 작은 온칩 메모리는 Scratchpad Memory라고 부른다.
캐시에 데이터를 저장할 때 공간 지역성을 최대한 활용하기 위해 해당 데이터뿐만 아니라 옆 주소의 데이터도 같이 가져와 미래에 쓰일 것을 대비한다. DRAM에는 프로그램을 수행하는 명령어(Instruction)와 그 명령이 실행되는 데이터(Data)가 함께 들어 있는데, 명령어는 읽기만 하고 데이터는 읽기와 쓰기를 동시에 하므로 캐시 메모리 내에 이들을 각각 I-Cache(Instruction Cache)와 D-Cache(Data Cache)에 저장한다. 보통 L1 캐시에는 I-Cache와 D-Cache가 따로 있고, L2 캐시는 딱히 둘의 구분 없이 하나의 캐시 메모리로 구성된다. L1 캐시는 CPU에 직접 데이터를 공급해 주기 때문에 빠른 접근 지연 시간(Access latency)이 매우 중요한데, 명령어는 보통 공간 지역성이 높고 데이터는 보통 시간 지역성이 높다. 이 둘을 나누어 서로 다른 지역성을 이용할 수 있다. 또한 명령어와 데이터를 동시에 읽어올 수 있게 함으로써 CPU의 파이프라이닝 성능을 향상시킬 수 있다.
CPU가 데이터를 요청했을 때 캐시 메모리가 해당 데이터를 가지고 있다면 이를 캐시 히트라 부르고, 해당 데이터가 없어서 DRAM에서 가져와야 한다면 캐시 미스라 부른다.
캐시 미스 발생시의 처리 방법은 캐시 정책에 따라 다르며, 데이터를 읽어 오는 시점으로 사용하기도 한다.
캐시 미스가 나는 경우는 대부분의 경우 3가지로 나눌 수 있는데
Compulsory miss(또는 cold miss) : 해당 메모리 주소를 처음 불렀기 때문에 나는 미스. 예를 들어 프로그램을 새로 켜거나 하는 경우 발생한다. 간혹 사용할 데이터를 미리 프리페치하는 경우가 아닌 이상 사실상 예방이 불가능한 캐시미스지만, 전체 컴퓨터 이용 시간에 비하면 굉장히 드물게 나는 미스 유형이라 전체적인 성능에 영향을 미치는 정도는 작다.
Conflict miss : 캐시 메모리에 A 데이터와 B 데이터를 저장해야 하는데, A와 B가 같은 캐시 메모리 주소에 할당되어서 나는 캐시 미스다. 예를 들어 내가 휴대폰과 따뜻한 커피캔은 항상 외투 오른쪽 주머니에만 넣는 습관이 있다고 하자. 평상시에는 오른쪽 주머니에 휴대폰만 넣고 다니는데, 어느날 친구에게 커피캔을 받아서 잠시 휴대폰을 가방 속에 넣어두고 커피캔을 오른쪽 주머니에 넣었다. 이때 휴대폰을 오른쪽 주머니에서 찾으려고 한다면 그때 conflict miss가 난다. direct mapped cache에서 가장 발생빈도가 높고, n-associative cache에서 n이 커질수록 발생빈도가 낮아지지만 대신 n이 커질수록 캐시 속도가 느려지고 파워도 많이 먹는다.
Capacity miss : 캐시 메모리에 공간이 부족해서 나는 캐시 미스. 위의 conflict miss는 캐시에 공간이 남아도는데도 불구하고 주소 할당때문에 나는 미스지만, capacity miss는 주소 할당이 잘 되어있더라도 공간이 부족하면 나는 미스다. 캐시 공간이 작아서 벌어지는 일이므로 캐시 크기를 키우면 해결되지만, 캐시 크기를 키우면 캐시 접근속도가 느려지고 파워를 많이 먹는다는 단점이 생긴다.
만약 대부분의 메모리 요청이 캐시 미스라면 캐시 메모리를 안 쓰는 게 더 빠르다. 하지만 다행히도 캐시 미스 비율이 대체로 평균 10% 안쪽이기 때문에 캐시 메모리를 통해 컴퓨터 시스템의 평균 성능을 크게 향상시킬 수 있으며 클럭 속도, 코어 개수와 함께 컴퓨터 성능에서 매우 큰 비중을 차지한다. 그러나 많은 사람들이 캐시 메모리에 대해 잘 모르며 이름부터 생소하니까 실제 캐시 메모리가 없이 클럭 속도가 더 높은 CPU가 클럭 속도는 낮지만 캐시 메모리가 있는 CPU보다 대체로 더 나쁜 성능을 보여준다. 셀러론이 싼데는 다 이유가
어떤 이는 컴퓨터에 사용된 도박의 원리라고 하기도 하는데, 이는 캐시 메모리의 작동 원리가 도박에서 돈을 거는 것과 유사하기 때문이다. 캐시 미스 비율 (질 확률)이 매우 낮아 거의 항상 이기는 도박이라 할 수 있다.
4. 구조와 작동 방식[편집]
Direct Mapped Cache
가장 기본적인 캐시 구조. DRAM의 여러 주소가 캐시 메모리의 한 주소에 대응되는 다대일(n:1) 방식이다. 그림을 참고해서 간단히 설명하자면, 메모리의 공간이 32개(00000₂부터 11111₂)이고, 캐시 메모리의 공간이 8개(000₂부터 111₂)이면 메모리의 주소가 00000₂, 01000₂, 10000₂, 11000₂인 곳의 데이터를 캐시 메모리의 주소가 000₂인 곳에만 읽고 쓰는 방식이다. 이때 000₂을 인덱스 필드(Index Field), 인덱스를 제외한 나머지 비트 00₂, 01₂, 10₂, 11₂을 태그 필드(Tag Field)라 하고, 기본적으로 태그 비트와 인덱스 비트 뒤에 데이터를 저장하는 데이터 필드(Data Field)가 붙어있는 구조를 갖고 있다.
Direct Mapped Cache의 작동 방식은 간단하지않게 예를 들어, 캐시 메모리가 비워진 상태로 CPU가 메인 메모리의 00000₂ 주소의 데이터를 두 번 연속해서 읽는다고 하자. CPU는 먼저 캐시 메모리를 뒤적이는데 요청한 주소가 00000₂이므로 캐시 메모리의 주소가 000₂인 곳을 확인한다. 확인 후 아무것도 없는 것을 확인하고 직접 메인 메모리의 00000₂주소를 참조하여 데이터를 읽어온다. 이때 또 쓸지도 모르니까 캐시 메모리의 000₂인 공간에 00₂태그비트와 아까 읽은 메인 메모리 00000₂의 데이터를 저장해 놓는다. 그 다음 바로 같은 동작을 수행하면서 똑같이 캐시 메모리의 000₂ 인 곳을 확인하는데 이번엔 데이터가 들어있으니 그 데이터가 CPU가 요구한 주소의 데이터와 일치하는지 태그 비트를 비교하는 검사를 한 뒤 태그 비트마저 일치하면 캐시 메모리에서 데이터를 가져온다.
Set Associative Cache
Fully Associative Cache
5. 역사[편집]
초창기 캐시 메모리는 메인보드에 붙어서 CPU와 메인 메모리 사이에 존재했으나, CPU 집적도가 높아지면서 CPU 안에 캐시 메모리가 포함되게 되었다 오오 무어. 펜티엄용 메인보드는 CPU 근처에 별도의 캐시 메모리 슬롯이 있어서 필요한 경우에 L2 캐시 메모리를 증설할 수도 있었다. CPU 외부에 별도 장착되는 캐시 메모리는 CPU 속도와는 별개로 작동했기 때문에, 캐시 메모리 속도가 시스템 속도에 영향을 주었다.
펜티엄 이후 CPU에서 L2 이상의 캐시를 CPU 칩 패키징 내에 넣으려는 시도가 있었고, x86 아키텍처 중 인텔에서는 1995년 11월 출시된 펜티엄 프로에서, AMD에서는 1999년 출시된 K6-III에서 최초로 실현되었다. L2 캐시가 CPU 내에 통합되기 시작한 시기에는 캐시 메모리가 실장된 형태가 On-die, On-package로 구분되어 있었다. On-die 캐시는 하나의 다이 안에 CPU 코어와 L2 캐시가 함께 포함되어 있는 것이고, On-package 및 그와 유사한 용어는 CPU 코어와 L2 캐시 다이는 서로 나뉘어 있지만 하나의 패키징된 칩 안에서 서로 연결된 형태를 가리킨다.
인텔은 펜티엄 프로에서 하나의 칩 안에 CPU 코어와 L2 캐시 다이를 모두 올리는 형태를 사용했다. 그러나 가격 문제 때문에 일반 사용자를 대상으로 한 펜티엄 2와 초기 펜티엄 3 카트마이 및 셀러론 모델에서는 CPU 코어와 L2 캐시를 별도 칩으로 분리했고, CPU 형태도 소켓에서 슬롯으로 바꾸었다. 슬롯 1이 사용되던 시기의 인텔 CPU에서는 CPU 코어와 별개로 외부 제조사에서 만든 캐시용 SRAM이 붙어 있었고, 셀러론은 캐시 메모리가 붙어 있지 않거나 용량이 더 작았다. AMD는 K6-III에서 On-die L2 캐시를 도입했으나, 인텔과 같은 이유로 인해서 초기형 애슬론은 슬롯 형태로 전환했다. 그러나 기술이 발전하여 On-die 캐시를 만들기 쉬워졌고, 외부 캐시 메모리의 속도를 끌어 올리는 데에는 한계가 있기 때문에 인텔은 펜티엄 3 코퍼마인, AMD는 애슬론 선더버드부터 On-die L2 캐시로 복귀했다. 슬롯이 다시 소켓으로 돌아간 것은 보너스.
인텔은 초창기의 셀러론에서 L2 캐시를 없앴다가 엄청난 성능 저하를 보였다. 이후 인텔은 아무리 저가형 모델이라고 하더라도 L2 캐시는 용량이 작더라도 항상 달고 나오기 시작했다. 2015년 시점에서는 최소 2단계, 보통 3단계까지 존재한다. 3단계 캐시가 있는 CPU는 인텔은 펜티엄 4 Extreme Edition[1], 인텔 코어 i 시리즈가 있으며 AMD는 AMD 페넘 시리즈에서 최초로 L3 캐시를 도입한 후, AMD 페넘 II 시리즈, AMD FX 시리즈 등이 있다. 당연히 단계가 내려갈수록 속도는 상대적으로 떨어지게 되며, 반대급부로 용량은 증가한다. 물론 코어2 쿼드 같이 2단계 캐시가 12MB나 달린 깡패가 있긴 하다 인텔의 브로드웰에 와서는 4단계 캐시인 128MB eDRAM이 적용되었다. 이는 주로 내장그래픽 칩셋에서 사용한다. 속도가 빠르고 대역폭도 넓다보니 기존의 HD시리즈와는 차원이 다른 성능을 보여줬다.
6. 유사한 것[편집]
하드 디스크 사이의 속도 향상을 위해서 보통 16MB~64MB 정도의 메모리를 달아서 좀 더 빠른 입출력이 가능하도록 지원한다. 이를 '버퍼' 또는 '버퍼 메모리'라고 부르는데 캐시 메모리와 완전히 같진 않지만 거의 유사한 방식으로 동작한다.
SSD에도 동일한 개념의 버퍼 메모리가 달려 있다. SSHD의 경우 하드 디스크의 버퍼를 아예 저용량의 SSD랑 섞어버린 것.
메인 메모리의 일부를 떼어서 HDD/SSD의 데이터를 캐싱하는것도 가능하며 이를 '디스크 캐시'라고 한다. DOS 시절 1M 메모리가 달린 286 이상의 컴퓨터에는 640kiB를 넘어가는 상위 메모리 영역의 일부를 디스크 캐시로 사용할 수 있도록 해 주는 유틸리티가 여러 종류 있었다. 이후 Windows 95로 넘어오면서 운영체제에서 자체적으로 디스크 캐시를 제공하게 되었다. Linux 등의 유닉스 계열 운영체제도 디스크 캐시를 기본 기능으로 보유하고 있다.
출처 : https://namu.wiki/w/%EC%BA%90%EC%8B%9C%20%EB%A9%94%EB%AA%A8%EB%A6%AC
'운영체제 & 병렬처리 > 시스템프로그래밍' 카테고리의 다른 글
리눅스에서의 가상메모리란? (0) | 2017.01.28 |
---|---|
OS내부동작원리 - 멀티 프로그램을 위한 메모리 관리(Context Switching, Swapping) (0) | 2017.01.27 |
malloc() 으로 메모리를 할동 받는 작동 원리 (0) | 2017.01.05 |
캐쉬 미스와 페이지 폴트를 줄이는 방법, Array (0) | 2017.01.05 |
프로세스 힙, CRT 힙 에 LFH(Low fragmentation Heap) 생성방법 (0) | 2013.09.27 |