minkylee

[컴퓨터구조] RISC-V 메모리 계층 2.Cache 본문

CSE/컴퓨터구조

[컴퓨터구조] RISC-V 메모리 계층 2.Cache

minkylee 2024. 6. 18. 20:39

Cache

 

메인 메모리와 프로세서 사이의 메모리 계층을 나타내기 위해서 사용된 용어이다.

요즘에는 데이터 접근의 Locality를 이용해서 관리되는 모든 기억장치를 부르는 데에도 사용된다. 

 

 

SRAM의 종류 중 하나로, 작고 빠르다. 그래서 메모리에 있는 데이터의 작은 부분만 cache에 저장 가능하다. 

L1, L2, L3 Cache로 구성되어 있으며 Processor는 Cache에서 가장 먼저 데이터를 찾는다. (없으면 memory로 이동한다.)

 

 

 

단순한 캐시를 먼저 예시로 보자

 

캐시에 없는 데이터를 요청하기 전과 후

 

요청하기 전의 캐시에는 최근에 접근한 $X_1, X_2, ... , X_{n-1} $ 이 존재하고 프로세서는 캐시에 없는 데이터 $X_n$을 요청했다.

이 요청은 실패 (Cache Miss)를 발생시키고, 워드 $X_n$을 메모리에서 캐시로 가져오게 된다. 

 

그렇다면 Processor는 찾는 데이터가 존재하는지, 존재한다면 어디에 있는지를 알아야 한다.

 

 

 

 

 

 

 

Direct mapping

 

 

Cache를 하나하나 순차적으로 찾는 것은 너무 비효율적이기 때문에, 이를 해결하는 방법이 mapping 기법이다.

 

 

memory 주소에 따라 cache에 넣을 수 있는 공간을 제한한다. 1:1 대응
특정 memory 주소는 특정 cache의 block에만 들어갈 수 있다.

Direct Cache가 메모리 주소를 캐시 내부의 위치로 변환하는 방법은 대부분 간단하며, 예시는 다음과 같다.

 

(Block address) modulo (#Blocks in cache)

블록 주소 modulo (캐시가 포함할 수 있는 블록 수)

 

 

캐시 내의 블록 수가 2의 거듭제곱인 경우, 주소의 하위 $log_2$ 개수의 비트를 취하는 것으로 Modulo 연산을 취할 수 있다.

따라서 8블록 캐시는 블록 주소의 하위 3비트를 사용한다.

 

예를 들어 블록의 메모리 주소가 001101이고, 블럭이 최대 8개(1000)개의 블록을 포함할 수 있다면

해당 블록의 캐시 내의 위치는 001100 modulo 1000 = 101이 된다.

 

 

이처럼 간단하게 mapping을 할 수 있지만, 두 개의 단점이 있다.

 

  1. 빈 공간이 있다.
    • 만약 001로 끝나는 메모리 주소만 사용한다면 남은 공간은 빈 공간이 되어 비효율적이다.
  2. 데이터가 쓰레기인지 아닌지, 메모리의 어떤 주소에서 온 건지에 대한 정보도 알고 있어야 한다.
    • Cache를 처음 초기화 할 때는 쓰레기 값이 들어간다. 만약 Cache가 memory와 mapping 되지 않았다면, 쓰레기 값이 계속 존재한다.
    • Cache의 값이 쓰레기인지 아니면 원하는 데이터인지 알 수 없다. 
    • 만약 쓰레기 값이 아니여도 데이터가 존재하는 것은 알았지만 어디서 온 데이터인지 알 수 없다. 

이런 문제를 해결하기 위해 TagVaild Bit가 존재한다.

 

 

 

Tags and Vaild Bit

태그는 캐시 내의 블록이 프로세서가 요청한 것인지 아닌지를 식별하는 데 필요한 주소 정보를 포함한다. 

 

캐시 인덱스로 사용되지 않은, 주소의 상위 부분 비트들로 구성된다.

 

예를 들어 110101 주소의 데이터가 캐시의 101에 위치해 있다면 태그는 캐시 인덱스로 사용되지 않은 001이 된다.

Cache 안에 들어가 있는 데이터의 구조는 다음과 같다.

 

index와 offset은 아래 address reference에서 더 자세히 알아보자!

 

 

Vaild Bits 의미 없는 데이터와 tag를 구별하기 위해 추가되었다.

초기화를 할 때, 각 cache의 위치한 vaild bit는 0이 되며, 이는 곧 해당 cache의 값이 쓰레기임을 의미한다.

 

반대로 vaild bit가 1이라면, 해당 cache의 값이 유효하다.

 

Cache access 예제

 

비어있는 블록 8개로 구성된 캐시에 대하여, 메모리 참조에 따른 캐시 내용의 변화를 살펴보자

 

블록에는 1word의 데이터를 저장할 수 있고, 메모리 주소의 하위 3비트만이 캐시 블록 번호로 사용된다.

 

또한 주소의 기본 단위를 워드라고 한다.

 

최초 캐시 상태는 다음과 같다.

 

 

 

 

 

처음으로 참조되는 데이터는 메모리 주소로 22에 존재하는 데이터이다.

캐시에 존재하지 않으므로 Cache Miss가 일어나며, 이후 메모리에서 해당 데이터를 가져오게 된다.  (가지고 오는 데이터는 블럭 단위)

22 메모리를 가져온다.

 

 

 

 

이후 참조되는 데이터는 메모리 주소로 26에 위치하는 데이터이다.

캐시에 존재하지 않으므로 Cache Miss가 일어나며, 이후 메모리에서 해당 데이터를 가져오게 된다.

26 메모리를 가져온다.

 

 

 

 

 

이후 다시 메모리 주소 22와 26에 존재하는 데이터에 접근하며, 이 둘은 모두 캐시에 존재하므로 Cache Hit이다.

메모리 22와 26 접근

 

 

 

 

 

이후 16(Miss), 3(Miss), 16(Hit)의 순서로 참조가 발생한다.

 

 

 

 

 

 

마지막으로 18(Miss), 16(Hit), 26(Hit) 순서로 참조가 발생한다.

 

 

 

 

Reference address

 

Reference address는 총 3개로 나눌 수 있다.

 

  • tag field : cache를 tag field의 값과 비교하기 위해 사용한다. (상위 비트)
  • cache index : block을 선택한다. 즉, 하위 비트를 저장하고 있다. 
    • cache에서는 $2^n$개의 블록이 있어서, 주소의 n비트가 cache block의 index로 사용된다.
  • Byte offset : 하나의 word에는 4개의 byte로 이루어져 있으므로, word 안에 몇 번째 byte인지 명시한다. 

 

메모리 주소 = cache index + tag field + byte offset

 

 

 

 

 

 

 

우선 cache index를 이용하여 Index 위치로 이동한다.

이후 cache의 tag field 와 reference address의 tag field가 같고, vaild가 1이라면 Hit이므로, byte offset에 대한 Data가 반환된다.

 

이 때 Block size는 4 byte로 가정한다. (Block은 Vaild, Tag를 제외한 Data를 위한 공간이다.)

 

따라서 cache index가 10bit이므로, Cache Size는 1024 * 4 byte = 4KB이다.

(10 bit는 $2^10$ 개의 주소를 지정할 수 있으므로, cache size 는 $2^12$ byte)

 

32 bit address를 사용하고, cache가 $2^n$ 개의 block과 block은 $2^m$개의 word ($2^m + 2$의 byte)를 가지고 있다고 가정해보자. 따라서 cache index는 n개가 필요하고, offset은 m + 2개의 bit가 필요하다.

 

  • Tab field size : 32 - (n + m + 2)
  • Total bits of cache = $2^n$ * (block size + tag size + vaild field size)
  • the number of bits = $2^n * (2^m * 32 + (32 - n - m - 2) + 1) = 2^n * (2^m * 32 + 31 -n -m)
  • block 개수 * (block size + tag size + vaild field size)

16 byte인 block 64개로 구성된 cache의 reference address를 보자

block이 64개이므로, cache index bit는 6개다.

또한 block size가 16 byte이므로 4개의 bit로 byte offset을 표시할 수 있다.

 

예를 들어 메모리 주소 1204는 1204 / 16 = 메모리의 75번 블록에 위치한다. 1204 modulo 64 = 11번 캐시에 저장한다. 

 

 

 

Block의 크기와 실패율

Block이 크다면 공간적 지역성(Spatial Locality)을 잘 활용하기 때문에 실패율이 감소한다.

그러나 전송해야 할 Block의 양이 많아지기 때문에 miss penalty가 증가한다.

 

Block이 작다면 miss rate가 증가한다. 그러나 전송해야 할 Block의 양이 적어지므로 Miss penalty가 감소한다.

 

위 그림에서 보이는 것처럼 Block 크기를 늘리면 대게 miss rate는 줄어든다.

 

하지만 Block이 너무 커져 Block하나가 캐시의 상당 부분을 차지하게 된다면 miss rate가 오히려 커질 수도 있다. 왜냐하면 캐시 내의 Block 개수가 적어지기 때문에, 경쟁이 심화되어서

 

결과적으로 Block 내의 워드를 별로 사용하지도 못했는데 그 Block이 캐시에서 쫒겨나는 상황이 발생한다.

-> Block의 크기가 너무 커질 경우 오히려 공간적 지역성이 감소하여 miss rate가 증가한다.

 

Block 크기가 증가하면 발생하는 더 심각한 문제는 miss penalty가 증가하는 것

miss penalty는 메모리 계층 구조의 다음 하위 계층에서 Block을 가져와서 캐시에 적재하는데 걸리는 시간에 의해 결정된다.

 

 

Block을 가져오는데 걸리는 시간은 두 부분으로 나누어 볼 수 있다.

 

  • 접근 지연 (latency) : 첫 번째 워드를 가져오는데 걸리는 시간
  • 전송 시간 : Block의 나머지 부분 전송

 

Block 크기가 커지면 전송시간도 증가한다. => 실패 손실이 증가한다. => 캐시의 성능이 감소한다.

 

 

early restart

큰 Block의 penalty 중 latency 부분에 대해서는 조치를 취하기 어렵지만 전송시간은 일부를 보이지 않게 해서 penalty를 줄일 수 있다.

 

이렇게 하는 가장 간단한 방법으로 early restart가 있다.

 

이는 Block 전체를 기다리지 않고 요청된 워드가 도달하면 곧바로 실행을 시작하는 것

 

그러나 이러한 방법은 Data Cache에 대해서는 덜 효과적인데, Block 내의 워드 요청이 예측하기 어려운 방식으로 이루어지는 경향이 있고, 데이터 전송이 다 끝나기도 전에 다른 캐시 Block의 워드를 필요로 할 가능성이 높기 때문이다.

 

전송이 진행 중이라 프로세서가 Data cache에 접근할 수 없으면 프로세서는 지연될 수 밖에 없다.

 

 

 

request word first

요청한 워드가 메모리에서 캐시로 제일 먼저 전송되도록 메모리를 구성하는 방법

 

이후 요청된 워드의 다음 주소부터 순서대로 전송하고, Block 끝까지 전송한 후에는 다시 블록의 처음 워드부터 남은 워드들을 순차적으로 전송한다.

 

이 기법을 요구 워드 우선, 또는 중요 워드 우선 방식이라 부르며, early restart 보다는 조금 빠르지만 여전히 같은 한계점을 가지고 있다.

 

 

Handling Cache Miss

 

Cache miss를 해결하기 위해 캐시를 위한 Control이 존재한다.

Control unit은 메모리 접근을 시작하고 캐시를 채우는 일을 한다.

예외나 인터럽트는 모든 레지스터의 상태를 저장해야 하지만, 캐시 실패의 처리는 파이프라인 지연(stall)만을 발생시킵니다.

 

캐시 실패 발생 시에는 임시 레지스터와 프로그래머에게 보이는 레지스터의 내용을 그대로 유지한 채 메모리에서 데이터가 오기를 기다리면서 전체 시스템을 지연시킨다.

 

이때 miss가 발생한다면 CPU Control은 다음과 같이 수행된다.

 

  1. CPU pipeline을 stall 한다.
  2. 메모리에서 Block을 반입한다.
  3. 만약 Instruction cache가 miss라면 instruction을 다시 반입한다.
  4. 만약 data cache가 miss라면 데이터에 다시 access한다.

 

 

Handling Writes

 

캐시의 데이터들은 모두 메모리에 있는 데이터의 subset이기 때문에 캐시의 값을 바꾼다면 반드시 메모리의 값도 바꿔줘야 한다.

 

여기서 메모리에 값을 입력하는 세 가지 방법이 있다. 

 

Write-Through

 

캐시와 메모리를 불일치를 해결하기 위한 가장 간단한 방법이다.

 

캐시에 데이터를 쓸 때, 동시에 메모리에도 값을 입력함으로써 해결한다.

하지만 이렇게 된다면 속도가 매우 느려진다.

 

Write Buffer

 

write-through의 느린 속도를 해결하기 위한 방법이다.

 

만약 CPI = 1이고, 명령어의 10%가 cycle인 write라고 생각한다면, 실제 CPI는 1 + 0.1 * 100 = 11이 된다.

이를 해결하기 위해 캐시에 데이터를 쓴다면, 이를 바로 메모리에 쓰지 않고 write buffer라는 곳에 저장한다.

 

write buffer는 processor가 캐시(데이터)를 쓰지 않을 때, 혹은 buffer가 가득 찼을 때 메모리에 값을 입력한다.

 

그럼에도 불구하고 write buffer에 데이터를 입력하는 시간이 존재하고, wirte buffer의 값을 메모리에 입력할 때 stall이 발생한다.

 

Write-Back

 

 

write-back은 위의 문제를 해결한다.

 

data-write hit이 발생하면, processor는 캐시의 그냥 Block을 업데이트 한다. 

추가적으로 캐시의 dirty bit을 생성하여, 해당 캐시가 업데이트 되었다는 것을 알린다.

dirty bit은 processor가 캐시에 write 할 때 생성된다.

 

쉽게 말하면 쓰기가 발생했을 때 새로운 값은 캐시 내의 Block에만 썼다가, 나중에 캐시에서 쫒겨날 때 쓰기에 의해 내용이 바뀌었으면 이 Block을 하위 메모리 계층에 써주는 방식이다. 

 

 

Main Memory Supporting Caches

 

컴퓨터의 Main memory는 캐시 메모리를 지원하기 위해 어떻게 작동할까

 

main memory로 DRAM을 사용한다. DRAM은 값이 자주 갱신되어야 하지만 용량이 크고 가격이 저렴하다.

 

main memory는 고정된 폭의 데이터 전송 방식을 사용한다.

Bus는 CPU와 주 메모리를 연결하는 통로로, 일정한 폭의 데이터를 전송한다. 일반적으로 Bus의 Clock 속도는 CPU의 Clock 속도보다 느리다.

 

Cache Block 읽기 예시

 

캐시 블록을 읽을 때 걸리는 시간(Bus Cycle)은 다음과 같다.

 

  1. 주소 전송 : 주소를 전송하는 데 1 Bus Cycle이 걸린다.
  2. DRAM 접근 : DRAM에 접근하는 데 15 Bus Cycle이 걸린다.
  3. 데이터 전송 : 1 Bus Cycle이 걸린다.

4워드의 Block을 읽는다고 할때 1워드 폭의 DRAM을 사용한다고 가정하자. 

 

그럼 각 단계별로

 

  1. 주소 전송 : 1 Bus Cycle
  2. DRAM 접근 : 각 워드를 읽기 위해 15 Bus Cycle이 필요하며 4개의 워드를 읽어와야 하므로 4 X 15 Bus Cycle
  3. 데이터 전송 : 각 워드를 전송하는데 1 버스 사이클이 필요하며, 4개의 워드를 전송해야 하므로 4 X 1 Bus Cycle

 

이 과정을 모두 합치면 Miss Penalty = 65 Bus Cycle이 된다. 대역폭(Bandwidth, 일정시간동안 전송할 수 있는 데이터의 양)은 16Byte / 65 Cycle = 0.25 Byte/Cycle이 된다.

 

 

 

 

캐시 성능 측정

 

CPU Time은 프로그램 실행 사이클, 메모리 스톨 사이클 두 개로 나눌 수 있다.

 

프로그램 실행 사이클은 프로그램이 실행되는 동안 CPU가 사용하는 기본 Cycle 수 이다. 여기에는 캐시 Hit 시간이 포함된다.

 

메모리 스톨 사이클은 캐시 미스로 인해 발생하는 추가시간이다. 주로 캐시 미스로 인해 메모리에서 데이터를 가져오는 데 걸리는 시간을 표현한다.

 

 

CPU time = 프로그램 실행 사이클 + 메모리 스톨 사이클

 

프로그램의 명령어 수, miss rate, miss penalty를 가지고 메모리 스톨 사이클을 계산하면 아래와 같다.

 

$$ 메모리 스톨 사이클 = 프로그램의 명령어 수 X 메모리 접근 비율 X miss rate  X miss penalty $$

 

 

만약 프로그램이 $1.0 * 10^6$개의 명령어를 실행하고, 메모리 접근 비율이 30%, miss rate가 5%, miss penalty가 100 cycle이라고 가정해보자

 

메모리 스톨 사이클을 계산하면 

 

$$ 10 X 10^6 X 0.30 X 0.05 X 100 = 1.5 X 10^6 사이클 $$

 

프로그램 실행 중 총 $1.5 X 10^5$ 사이클이 캐시 미스로 인해 추가된다는 의미다.

 

이를 통해 CPU time을 계산할 수 있다.

 

 

또 다른 예제를 하나 더 살펴보자

 

  • I cache(instruction cache) miss rate = 2%
  • D cache(Data cache) miss rate = 4%
  • Miss penalty = 100 cycle
  • ideal CPI (Cache가 이상적인 경우)
  • Load, Store 명령 비율 = 36%

이 때 I cache miss로 인해 추가되는 사이클 수는 $0.02 X 100 = 2 cycle$ 이고

D cache miss로 인해 추가되는 사이클 수는 $0.36 X 0.04 X 100) = 1.44 cycle$ 이다.

 

실제 CPI를 계산해보자

ideal CPI에 I cache 와 D cache로 인해 추가되는 사이클을 더한다.

$2 + 2 + 1.44 = 5.44$ 따라서 ideal CPI가 $5.44 / 2 = 2.72$ 배 더 빠르다.

 

 

따라서 CPU 성능이 증가할 때 Cache miss가 시스템 성능에 미치는 영향이 더 커진다. CPU 성능이 향상되면서 기본 CPI가 감소하고 메모리 대기시간의 비중이 증가하기 때문이다. 

 

왜냐하면 CPU가 더 빠르게 동작하기 위해 클럭 속도가 증가하면서 메모리 대기 사이클 수가 증가하고, 상대적으로 느린 메모리 접근으로 인한 대기 시간이 더 큰 영향을 미치게 된다. 이는 메모리 대기가 성능 저하의 주요 원인이 될 수 있음을 의미한다.

 

 

 

 

 

 

 

 


 

 

 

 

 

 

Associative Mapping

 

유연한 블록 배치를 통해 Miss rate를 줄이자

 

Direct Mapping 방식의 단점 중 하나가 바로 빈 공간이 존재한다. 이다.

하나의 Block은 하나의 공간에만 들어갈 수 있고, 사용하지 않는 다른 공간은 빈 공간으로 남아있기 때문에

 

이를 해결하기 위한 방식이 있는데 Associative Cache

 

Associative CacheFully Associative CacheSet Associative Cache로 나뉜다.

 

먼저 Fully Associative Cache를 보자.

 

 

Fully Associative 

 

Block이 캐시의 어느 곳에나 들어갈 수 있도록 하는 캐시 구조

 

 

다만 이 방식의 단점으로는

 

  1. 모든 entry를 검색해야 한다.
    • 어떤 Block이 캐시의 어느 위치에 있는지 모르기 때문에 캐시의 모든 entry를 검색해야 한다.
  2. 하드웨어 크기 증가
    • 각각의 캐시에 comparator(비교기)를 넣어서 병렬적으로 비교해야하기 때문에 크기가 증가한다는 단점이 있다.

각 캐시 아래에 보이는게 comparator

따라서 나온 방식이 Direct와 Fully Associative의 중간인 Set Associative Cache이다.

 

 

Set Assocative Cache

 

한 Block이 들어갈 수 있는 자리의 개수가 고정되어 있다.

 

각 Block 당 n개의 배치 가능한 위치를 갖는 set associative cache를 n-way set associative cache라고 한다. 

 

그렇다면 Cache가 총 8개의 Block으로 구성되어 있고 2-way set associative cache 방식을 사용하면 4개의 set으로 구분될 것이다. 

 

메모리에 있는 Block은 cache의 특정한 set에 mapping되고, 해당 Block은 set 안의 아무 위치에 들어갈 수 있다. 

 

검색 시에는 Block이 존재하는 set을 찾고, set 내의 모든 block을 검색하여 일치하는 것을 찾는다. 

 

 

3가지 mapping 방법을 비교해보자 메모리 주소가 12인 데이터의 경우

  • Direct : 12 % 8 = 4 번 Block
  • Set associative : 4개의 set이 있으므로 12 % 4 = 0 번 set의 아무 Block
  • Fully associative : 무작위

set associative cache에서는 Block이 set 내에서 어느곳에나 존재할 수 있기 때문에, set 안의 모든 블록의 태그를 전부 검사해야 한다.

 

fully associative cache는 Block이 어느 곳에나 위치할 수 있으므로, cache 내 모든 Block의 태그를 다 검색해야 한다.

 

모든 Block 배치 방식을 set associative 방식의 변형이라고 생각할 수 있다. (n = 1이면 Direct mapping이고 n = Block 개수면 fully associative 이니까)

 

예를 들어 Block의 개수가 8개인 캐시에서 가능한 associativity (연관 정도) 구조는 다음과 같다.

 

 

 

 

associativity를 늘리는 것은 대게 miss rate가 줄어든다는 것이고 단점으로는 hit time이 증가한다는 것이다.

 

 

 

Mapping 방식의 비교

 

위에서 n-way set associative cache에서 n이 증가 / 감소함에 따라 miss rate와 hit time이 달라진다고 했다.

 

어떻게 달라지는지 예시를 통해 알아보자

 

Example

 

 

4개의 Block을 가지고 있는 cache가 있다.

입력되는 memory block address는 0, 8, 0, 6, 8이다.

Direct Mapping

0과 8이 번갈아가면서 들어와 Miss가 5번 발생한다. 

 

 

2-way set associative cache

 

모든 block이 0번 set에 mapping된다.

들어가야하는 block은 3개인데 0번 set에는 entry가 2개 밖에 없어 한 개는 교체되어야 한다.

따라서 4번 cache miss가 발생한다.

 

 

Fully associative cache

 

아무 위치에 mapping 될 수 있기 때문에 한 번 cache에 들어가면 자리가 꽉 차서 교체되기 전까지는 HIT이 발생한다.

 

16-word block을 가지고 있는 64KB data cache를 대상으로 시뮬레이션 돌린 결과는 다음과 같다. 

 

  • 1-way: 10.3%
  • 2-way: 8.6%
  • 4-way: 8.3%
  • 8-way: 8.1%

n이 증가할 수록 Miss rate가 감소한다. 대신 참조 시간도 증가한다.

 

 

Set Associative Cache Organization

 

 n-way cache는 n개의 comparator와 n-to-1 multiplexer를 가지고 있다. 

 

4-way set associative cache

 

 

 

address의 Index field를 비교해서 어떤 set에 존재하는지 찾는다. 

그리고 tag field를 비교하여 어느 set이 참조 값을 가지고 있는지 비교한다.

그리고 4-to-1 multiplexer를 통해 원하는 데이터를 뽑아낸다.

 

 

 

 

 


 

 

 

 

 

 

 

Replacement Policy

 

캐시 미스가 발생했을 때 메모리에서 데이터를 가져와야한다. 하지만 이미 Block이 다 차있다면? 

 

어떤 Cache부터 교체해야할까?

 

LRU

지금까지 본 Cache mapping 예시에서 사용한 방법이다.

 

최근에 사용되지 않은 Block을 우선적으로 교체하는 방법이다. 

 

direct mapping 방식에서는 누군가가 Block을 소유하고 있으면 교체하면 된다.

fully mapping에서는 모든 Block이 교체의 대상이 된다.

 

무작위로 교체하는 Random 방법도 있다. LRU와 성능 차이가 거의 나지 않는다고 한다.

 

 

 

 

Multi Level Caches

 

miss penalty를 감소시켜 성능을 높이는 방법

 

대부분의 MIcro processor는 additional level of caching을 지원한다.

프로세서의 빠른 속도와 상대적으로 점점 느려지는 DRAM의 접근시간의 차이를 더욱 줄이기 위해서

 

  • L1 Cache : 프로세서와 가장 가까운 캐시, 속도를 위해 I cache와 D cache로 나뉜다.
    • Instruction cache : 메모리의 TEXT 영역 데이터를 다루는 캐시
    • Data cache: TEXT 영역을 제외한 모든 데이터를 다루는 캐시
  • L2 Cache : 용량이 큰 캐시, miss rate를 줄이는 것이 중점을 둔다. 보통 마이크로프로세서와 같은 칩에 있다.
  • L3 Cache: 일부 고급 시스템에서 사용, 멀티 코어 시스템에서 여러 코어가 공유하는 캐시

 

L2 Cache는 L1 Cache에서 실패가 발생하면 접근한다. 

만약 원하는 데이터가 L1에는 없으며 L2에 존재할 때 Miss penalty는 L2 Cache의 접근시간이 되며, 이 값은 메인 메모리 접근 시간보다 훨씬 짧다. 

 

그러나 L1 Cache와 L2 Cache 모두 데이터를 갖고 있지 않은 경우, 메인 메모리 접근이 필요하며, 이 경우에는 더 큰 miss panelty가 발생한다. (L2 miss penalty + memory miss penalty)

 

얼마나 성능이 향상되는지 예시를 통해 알아보자 

 

Example

 

클럭 속도가 4GHz고 모든 참조가 L1 Cache에서 적중된다고 가정했을 때의 기본 CPI가 1인 프로세서를 생각해보자

 

실패 처리까지 포함하여 메인 메모리 접근시간이 100ns이고, L1 Cache에서 명령어 하나당 실패율이 2%라고 가정한다.

 

접근 시간이 5ns인 L2 Cache를 충분히 많이 추가하여 메인 메모리까지 가야 하는 실패의 비율을 0.5%로 낮출 수 있는 경우, 프로세서의 성능이 얼마나 빨라질까?

 

메인 메모리로 가는 경우의 miss penalty : 100ns X 4GHz = 400 Clock Cycle

 

Cache가 한 계층만 있는 경우 유효 CPI는 다음과 같다.

 

전체 CPI = 기본 CPI + 명령어 하나당 메모리 지연 사이클 수이므로 

 

1 + 400 X 0.02 = 9

 

 

L2 Cache가 있는 경우, L1 Cache 실패가 L2 Cache에서 처리될 수도 있고 메인 메모리에서 처리될 수도 있다. 

 

L2 Cache 접근에 따른 miss penalty는 다음과 같다.

 

5ns X 4GHz = 20 Clock Cycle

 

만약 Cache 실패가 L2 Cache에서 처리된다면 위 값이 전체 miss penalty가 된다. 

 

하지만 메인 메모리까지 가서 실패를 처리하게 된다면 전체 miss penalty는 L2 Cache 접근과 메인 메모리 접근 시간의 합인 420 Cycle이 된다.

 

따라서 2단계 Cache에서 전체 CPI는 두 캐시에서 발생하는 지연 사이클과 기본 CPI의 합이 된다.

 

1 + 20 X 0.02 + 400 X 0.05 = 3.4

 

따라서 L2 Cache를 갖는 프로세서는 2.6배만큼 빨라진다.

 

 

설계 고려사항

 

L1 Cache

  • Clock cycle의 단축이나 파이프라인 단계의 축소가 가능하도록 hit time 최소화에 중점을 둔다.

단일 Cache와 비교할 때 multi level cache의 L1 cache는 대게 더 작다

또한 L1 Cache는 크기를 작게 하고 miss penalty를 줄이기 위해 Block size가 작다.

 

 

L2 Cache

  • 긴 메모리 접근시간으로 인한 손실을 줄이도록 miss rate에 중점을 둔다.

L2 Cache는 단일 Cache와 비교할 때 접근시간이 덜 중요하기 때문에 크기가 훨씬 더 크다. (속도가 줄어도 되기 때문에 저렴한 Cache를 많이 사용할 수 있어서)

 

따라서 단일 Cache에 적절한 Block size보다 더 큰 Block을 L2 Cache에 사용하여 miss rate를 줄일 수 있다.

또한 L2 Cache는 miss rate를 줄이는 데 집중해야 하므로 L1 Cache보다 더 높은 Associativity를 많이 사용한다. 

 

 

 

 

 

 

 

 

참고

 

https://ttl-blog.tistory.com/1096

https://hi-guten-tag.tistory.com/290

https://jja2han.tistory.com/226?category=583664