5.3번 문제들: 캐시 전체 비트 수 계산 및 성능 비교
문제 설명: 32KiB, 64KiB 캐시에 대해 태그, 유효 비트, 데이터 비트 총합을 계산하고, 블록 크기 변화에 따른 효과를 살펴본다.
• 1 KiB = 1024바이트
• 32 KiB = 32 * 1024 = 32768 바이트
• 64 KiB = 64 * 1024 = 65536 바이트
• 워드(Word) = 4바이트
5.3.1 (32KiB 캐시, 2-word 블록)
조건:
• 총 데이터 용량: 32KiB = 32768바이트
• 블록 크기: 2워드/블록, 1워드=4바이트 ⇒ 블록 크기 = 2 *4바이트 =8바이트
• 블록 수 = 총 용량 / 블록 크기 = 32768바이트 /8바이트 =4096블록
어드레스 비트 분해(32비트 주소):
• 오프셋(Offset) 비트 수: 블록 크기 8바이트 ⇒ log2(8)=3비트
• 인덱스(Index) 비트 수: 블록 수=4096 ⇒ log2(4096)=12비트
• 태그(Tag) 비트 수: 32 - (12+3)=17비트
각 블록마다:
• 태그: 17비트
• 유효 비트(Valid bit): 1비트
• 데이터: 8바이트(=64비트)
총 태그+유효 비트: (17+1)4096=184096=73728비트
총 데이터 비트: 32KiB =32768바이트=32768*8=262144비트
전체 비트 수 = 태그+유효+데이터 =73728+262144=335872비트
5.3.2 (64KiB 캐시, 16-word 블록)
조건:
• 총 용량: 64KiB =65536바이트
• 블록 크기: 16워드, 워드=4바이트 ⇒ 블록=16*4=64바이트
• 블록 수=65536바이트/64바이트=1024블록
주소 비트 분해:
• 오프셋: 64바이트/블록 ⇒ log2(64)=6비트
• 인덱스: 블록 수=1024 ⇒ log2(1024)=10비트
• 태그: 32-(10+6)=16비트
각 블록마다:
• 태그=16비트+유효=1비트=17비트/블록
• 총 태그+유효 비트:17*1024=17408비트
• 데이터 비트: 64KiB =65536바이트=65536*8=524288비트
전체 비트:524288+17408=541696비트
이 캐시는 이전 (5.3.1)의 32KiB 캐시보다 데이터 용량은 2배, 전체 비트 수도 증가했지만 블록 크기가 커서 태그 개수 감소효과가 있음. 그럼에도 더 큰 캐시임에도 오히려 태그 오버헤드는 덜 늘어남.
5.3.3
왜 64KiB 캐시가 더 큰데도 더 느릴 수 있는가?
• 블록 크기가 커지면 미스 발생 시 더 많은 데이터를 한 번에 가져와야 하므로 미스 패널티 증가
• 프로그램이 큰 블록 내부 데이터 모두 사용하지 않으면 낭비 발생(불필요한 데이터 전송)
• 또한 큰 블록은 더 적은 수의 블록을 의미하므로 어떤 워킹셋 패턴에는 오히려 충돌 미스가 증가할 수 있음.
즉, 더 큰 캐시라도 블록 크기 증가로 인해 오히려 성능이 떨어질 수 있다.
5.3.4
32KiB 2-way set associative 캐시와 32KiB direct mapped 캐시를 비교할 때, 2-way가 더 좋은 성능을 내는 요청 패턴 예:
• Direct mapped 캐시에선 같은 인덱스에 해당하는 다른 주소를 번갈아 접근하면 충돌이 발생해 매번 미스.
• 같은 상황에서 2-way 세트 연관은 같은 인덱스 라인 두 개 중 하나에 두 블록을 모두 저장 가능하므로 미스가 줄어듦.
예: 0x0000, 0x1000, 0x0000, 0x1000을 반복 접근 시 direct mapped는 계속 교체 발생, 2-way는 히트율 상승.
5.4번 문제: XOR 인덱싱 함수 사용 가능 여부
문제: 전통적 인덱싱은 단순히 주소 비트를 잘라서 인덱스로 사용. 여기서는 Block address[63:54] XOR Block address[53:44]와 같은 복잡한 인덱싱을 제안. 가능한가?
• 원칙적으로 하드웨어로 XOR 연산을 추가해 인덱스를 생성하는 것은 가능하다.
• 그러나 direct-mapped 캐시는 단순히 주소의 특정 비트 부분을 인덱스로 사용하여 빠르게 액세스하는 장점이 있다. XOR 같은 연산을 도입하면 하드웨어 복잡성 증가.
• 성능상 이득이 없다면 이렇게 하지 않는다.
즉, 가능은 하지만 일반적이지 않고 구현 복잡도가 증가한다. 실용적으로 거의 쓰지 않는다.
5.5번 문제들: 32비트 주소에서 주어진 필드(Tag, Index, Offset)로부터 블록 크기, 블록 수, 비트 비율 계산 및 접근 패턴 분석
문제 조건:
Tag: bits [63:10], Index: [9:5], Offset: [4:0] 라고 제시되었으나 이것은 교재 예시 형식으로, 실제 32비트 주소에서 태그가 63:10까지 나갈 수는 없다. 여기서는 문제에서 “the following bits of the address are used”라고 했으니, 상위 비트는 모두 태그로 간주하고, 인덱스와 오프셋 비트 수만 맞추면 됨.
가정: 32비트 주소 중
• Offset: 5비트([4:0])
• Index: 5비트([9:5])
• Tag: 나머지(22비트: [31:10])
5.5.1
오프셋이 5비트면 블록 크기 = 2^5=32바이트/블록. 1워드=4바이트 ⇒ 블록당 워드 수=32바이트/4바이트=8워드.
답: 8워드/블록
5.5.2
인덱스=5비트 ⇒ 블록 수(=라인 수)=2^5=32블록.
답: 32블록
5.5.3
데이터 전체 크기와 태그/유효 비트 비율 계산:
• 블록당 32바이트 데이터, 총 32블록 ⇒ 총 데이터=32*32=1024바이트=8192비트
• 태그=22비트, 유효비트=1비트/블록 ⇒ 23비트/블록 *32블록=736비트 오버헤드
• 전체=8192+736=8928비트
데이터 대비 전체 비율=8928/8192≈1.09 ⇒ 약 9% 추가 오버헤드.
답: 약 1.09:1 비율
5.5.4
여러 주소 접근(00,04,10,84,E8,A0,400,1E,8C,C1C,B4,884)에 대해:
1. 각 주소를 2진으로 변환
2. 오프셋(5비트), 인덱스(5비트), 태그(22비트) 분리
3. 캐시 초기엔 비어있으므로 첫 블록 접근은 미스 → 해당 블록 라인을 채운다.
4. 같은 블록 내 주소 접근 시 히트 발생
5. 다른 인덱스 또는 다른 태그로 접근 시 미스 발생
이 문제는 구체적인 수치가 매우 길어지므로 원리만 요약:
• 첫 번 주소(0x00): 미스 후 캐시에 로드
• 이어서 같은 블록 범위 내 주소들(예: 0x04, 0x10)이 오면 히트
• 새로운 블록에 속하는 주소(0x84, 0xE8 등) 접근 시 미스
• 같은 블록 재접근 시 히트
이 과정을 모든 주소에 대해 반복하면 각 접근의 히트/미스 판정과 대체된 바이트(교체된 바이트)를 나열할 수 있다.
5.5.5
히트율(hit ratio)는 5.5.4에서 계산한 총 히트 횟수/총 접근 횟수.
실제 계산은 각 접근 마다 히트/미스를 판정한 뒤, 히트 수를 세면 됨.
5.5.6
최종적으로 캐시에 남아 있는 각 블록의 <인덱스, 태그, 데이터> 상태를 나열. 데이터는 해당 블록에 적재된 메모리 범위를 표시. 접근 종료 후의 캐시 상태를 기록한다.
5.6번 문제들: L1/L2 캐시의 쓰기 정책(Write policy) 및 버퍼, 멀티 레벨 익스클루시브 캐시 전략
5.6.1
L1과 L2 사이, 또 L2와 메인 메모리 사이에 쓰기 버퍼(write buffer), 미스 핸들링용 버퍼, 프리페치 버퍼 등을 둘 수 있다. 문제의 요지는 L1 write-through, L2 write-back 등의 조합에서 레이턴시를 줄이기 위해 버퍼가 필요하다는 것. 가능한 버퍼:
• L1->L2 사이의 write buffer(작성 버퍼)
• L2->Memory 사이의 miss buffer나 prefetch buffer
5.6.2
L1 write-miss 처리 절차(더티 블록 교체 가정):
• L1에 블록이 없음: write-allocate이면 먼저 L2에서 블록을 가져와 L1에 적재.
• 이 때 L1에서 블록 교체가 필요하고, 교체되는 블록이 더티라면 L2로 해당 블록을 다시 써야(write-back) 함.
• L2에서도 만약 교체 발생 시 더티 블록을 메모리에 다시 써야 할 수도 있음.
• 즉 L1 miss → L2 접근, 필요 시 L1 더티 블록 write-back, L2 miss 시 메모리 접근… 이런 식으로 단계적으로 처리.
5.6.3 (Multilevel exclusive 캐시)
익스클루시브 캐시는 같은 블록이 L1과 L2에 동시에 존재하지 않는다.
• L1 read-miss: L2에 해당 블록이 있다면 L2에서 L1으로 블록을 이동(L1에 로드하면서 L2에서 제거). 메모리까지 갈 수도 있음.
• L1 write-miss:
• Write-allocate 시: L2에서 블록 가져와 L1에 적재 후 수정
• Non-write-allocate 시: L1에 적재하지 않고 L2(또는 메모리)에 직접 쓰기(write-through)
이때 항상 한 레벨에만 블록이 존재하므로 L1에서 블록을 가져오면 L2에선 제거, L2에 있던 것을 다시 L1으로 올리는 식으로 운영한다.
5.7번 문제: CPU 성능, 캐시 미스율, 대역폭 계산
주어진 상황:
• 프로그램 실행 시, 1000명령어당 data reads =250번, data writes=100번 발생.
• Instruction miss rate=0.30%, Data miss rate=2%, block size=64바이트
• CPU의 CPI(기본 CPI)=2라고 가정(즉, 캐시 미스 없으면 한 명령어당 2 사이클 정도 걸림).
5.7.1 (Write-through, Write-allocate 캐시에서 대역폭 계산)
• Read bandwidth(읽기 대역폭)과 Write bandwidth(쓰기 대역폭)을 구해야 한다.
• miss가 날 때마다 64바이트 블록을 메모리에서 가져온다.
• 1000명령어당 instruction fetch miss: 명령어 접근량: 1000명령어 당 보통 1000 instruction fetch라 가정. 미스율 0.30%면 1000번 중 3번 miss 발생. miss 1회 당 64바이트 읽음 → instruction miss로 인한 읽기 = 3 *64바이트=192바이트
• data read miss: data read는 1000명령어 당 250회, 그 중 miss율 2% →2500.02=5회 miss, 각 miss 때 64바이트 읽음 → 564=320바이트
• data write miss: data write=100, miss율 동일 2%라고 하면 write-allocate이므로 miss 시에도 block read 필요 (64바이트) →2회 miss 발생(1000.02=2), 264=128바이트 읽음
또한 write-through 이므로 모든 write는 메모리에도 쓰여야 한다. write hit일 때도 최소한 store를 메모리에 전달한다. 100회 쓰기 중 miss는 2회(이미 위에서 block 읽고 쓰는 과정), 나머지 98회는 write hit인데 write-through면 매번 적어도 4바이트(한 워드) 정도를 메모리에 써야 한다고 가정(문제 상세조건이 필요하지만 일반적으로 write-through는 매 쓰기마다 메모리에 1워드 정도 씀). 98회*4바이트=392바이트 write.
정리:
• Read 총량: instruction miss로 192바이트 + data read miss로 320바이트 + data write miss로 128바이트 → 총 640바이트 정도 읽기
• Write 총량: write-through는 모든 write를 메모리에 → 총 100회 writes *4바이트=400바이트 (추가적으로 block write-back은 없으나 write-allocate 시 miss 때 읽기는 했지만 바로 쓰기 반영은 write-through로 매번…)
(정확한 수치는 문제의 조건해석에 따라 다를 수 있으나 개념적으로 read miss 때 block 전송으로 읽기 대역폭, write-through로 매번 write로 쓰기 대역폭 발생.)
핵심: read bandwidth는 모든 miss 시 블록 크기만큼 읽어오는 바이트 수/1000명령어, write bandwidth는 write-through 때문에 대부분의 write가 메모리에 반영되는 것으로 계산.
5.7.2 (Write-back, Write-allocate, 30% dirty blocks)
• 여기서는 replaced data block의 30%가 더티(수정됨)라서 miss 시 새로운 블록을 가져오기 전에 더티 블록을 메모리에 64바이트 써야 함.
• read bandwidth: instruction/data miss 발생 시 64바이트 블록 읽기 동일.
• write bandwidth: 30% 확률로 블록을 쓸 때(교체 시) 64바이트를 메모리에 write-back.
• 따라서 miss 발생 비율에 따라 0.3*(미스 횟수)*64바이트만큼 write 발생.
정확한 수치는 문제 조건에서 명확히 주어진 계산식을 따른다. 핵심은 write-back은 miss 시에만 블록을 메모리에 다시 쓰며, 그 중 30% 정도 발생한다는 점이다.
5.8번 문제: 스트리밍 워크로드의 miss rate
상황:
• 워크로드가 순차적으로 0,1,2,3,… 이렇게 커다란 주소 공간(512KiB)을 스트리밍(한 번만 읽고 다시 안 쓰는)
• 64KiB direct-mapped 캐시, 블록 크기=32바이트 일 때 miss rate?
순차 접근이라 매번 새로운 블록 접근 시 한 번 miss 후 그 블록 내 나머지 주소는 히트.
하지만 스트리밍은 크기가 워킹셋보다 훨씬 커서 한 번 사용한 블록은 다시 안 씀. 결국 거의 매 블록당 첫 단어 접근 시 miss. 즉 miss rate는 (블록 내 워드 수 중 첫 워드 접근 시 miss 1번/블록 내 모든 워드 접근) 형태가 된다.
5.8.1
512KiB 데이터를 순차 접근, 블록당 32바이트면 총 512KiB/32바이트 = 16384블록. 모든 블록을 처음 접근할 때 miss 발생 → miss 16384번
접근 횟수(단어 주소 스트림 길이)는 매우 클 것이고 대부분 첫 접근당 miss. miss rate는 거의 100%에 가깝다(블록당 첫 접근이 miss이므로 1-block당 1번 miss, 이후 다시 같은 블록에 접근 없으면 miss율 ~100%).
이런 워크로드는 공간 지역성은 있으나(연속적), 재사용이 거의 없어 시간 지역성이 없다. 결국 캐시 크기를 늘려도 재사용이 없으면 miss rate 줄이기 힘들다.
5.8.2
블록 크기 16바이트, 64바이트, 128바이트로 바꾸면?
• 큰 블록일수록 한 번 miss 시 더 많은 데이터 가져오나, 어차피 한 번만 사용하고 지나가므로 추가로 가져온 데이터는 헛수고(사용 안 함).
• 블록 크기 커져도 miss 횟수는 총 접근한 블록 수와 비슷. 결국 miss rate 크게 안 줄어듦.
5.8.3 (Prefetching)
스트림 버퍼로 미리 다음 블록을 가져온다면, 현재 블록 사용 중에 다음 블록 미리 갖고 있으면 miss 없이 히트로 처리 가능. 이 경우 스트리밍에 딱 맞아, miss rate를 매우 낮출 수 있다. 이상적으로는 첫 블록 miss 이후 나머지는 프리페치로 히트 → miss rate 거의 1/블록 전체 개수 정도로 매우 낮아진다.
5.9번 문제: miss rate와 miss latency의 트레이드오프
block size 변화에 따라 miss rate가 바뀌고, miss latency(미스 처리 시간)도 바뀐다.
표:
• 8바이트: 4% miss
• 16바이트:3%
• 32바이트:2%
• 64바이트:1.5%
-128바이트:1%
miss latency가 B 사이클(블록 크기에 비례)라고 하면, block이 커질수록 miss latency 증가하지만 miss rate 감소.
5.9.1 (miss latency=20×B)
블록 크기 커질수록 miss latency 커진다. 여기서 최소화해야 할 것은 total miss penalty = miss rate * miss latency.
예:
• 8바이트: miss rate=4%, miss latency=20×8=160사이클 →평균 미스코스트=0.04160=6.4사이클
-16바이트: miss rate=3%, latency=20×16=320사이클 →0.03320=9.6사이클
-32바이트:2%, latency=20×32=640 사이클 →0.02640=12.8사이클
-64바이트:1.5%, latency=20×64=1280 사이클 →0.0151280=19.2사이클
-128바이트:1%, latency=20×128=2560 사이클 →0.01*2560=25.6사이클
가장 낮은 것은 8바이트일 때 6.4사이클.
답: 8바이트 블록이 최적.
5.9.2 (miss latency=24+B)
이제 latency는 24+(블록 크기)라고 가정.
-8바이트: latency=24+8=32사이클, miss rate=4% →평균=0.0432=1.28사이클
-16바이트: latency=24+16=40사이클, miss rate=3% →0.0340=1.2사이클
-32바이트:24+32=56사이클, miss rate=2% →0.0256=1.12사이클
-64바이트:24+64=88사이클, miss=1.5% →0.01588=1.32사이클
-128바이트:24+128=152사이클, miss=1% →0.01*152=1.52사이클
여기서 최소는 1.12사이클(32바이트)
답: 32바이트 블록 최적.
5.9.3 (constant miss latency)
miss latency가 block size에 상관없이 일정하다면, miss rate가 낮을수록 좋으므로 가장 큰 블록(128바이트)이 miss rate 1%로 최소. 이 경우 블록 크기를 크게 해서 miss rate를 낮추는 것이 최적.
5.10번 문제: L1 캐시 크기 변화로 인한 성능 변동
P1: L1=2KiB, 8% miss rate, L1 hit time=0.66ns
P2: L1=4KiB, 6% miss rate, L1 hit time=0.90ns
메모리 access=70ns, instruction 36%가 data, 나머지 instruction fetch.
5.10.1
L1 hit time이 사이클 타임 결정 → P1=0.66ns/사이클, P2=0.90ns/사이클
즉, P1 클럭은 더 빠름(주기가 짧음), P2는 더 큼=더 느린 클럭.
5.10.2
Average Memory Access Time(AMAT)= hit time + miss rate×miss penalty
P1: hit=0.66ns, miss=0.08×70ns=5.6ns추가 →AMAT~0.66+5.6=6.26ns
P2: hit=0.90ns, miss=0.06×70=4.2ns →AMAT=5.1ns
5.10.3
CPI=1.0(기본)+Memory stall
Memory stall 비율은 AMAT와 접근 횟수 고려
대략적으로 P2가 더 낮은 AMAT이므로 전체 CPI 낮아 P2가 더 빠름.
이후 L2 캐시 추가 시(5.10.4~5.10.7)는 L2 hit time, miss rate 고려해서 AMAT 다시 계산. L2 miss 시 메모리 접근. 목표: L2로 miss penalty 줄이고 CPI 감소. L2 miss rate를 조절해 P1을 P2보다 빠르게 만들 수 있다.
• 5.10.4: L2 추가하면 L1 miss→L2 접근해서 더 짧은 시간에 해결 가능. AMAT 계산 시 L1 miss penalty 대신 L2 hit time+L2 miss penalty로 바뀌며, L2가 크고 miss rate 낮으면 전체 AMAT 개선.
• 5.10.5~5.10.7: L2 miss rate를 어느 정도까지 줄이면 P1이 P2보다 빨라지나? 즉 L2가 충분히 좋으면 작은 L1+L2 조합이 큰 L1 단독보다 나아진다.
5.11번 문제: 다양한 캐시 디자인(직접사상 vs 세트 연관 vs 완전 연관), 블록 크기 변화, 대체 정책(LRU, MRU, Optimal) 시뮬레이션
여기서는 주소열(0x03,0xb4,0x2b,…)에 대해:
• 5.11.1: 3-way set associative cache 그림 그리기(48워드용), 각 라인에 몇 비트 태그, 데이터가 들어가는지. 블록당 2워드이므로 offset 비트=1, 전체 블록 수 계산해서 인덱스 비트 정하고 나머지는 태그.
• 5.11.2: 주어진 참조 주소마다 태그, 인덱스, 오프셋 나누고 해당 세트 내 LRU를 고려해 hit/miss 판단.
• 5.11.3: 완전 연관 8워드 캐시: 인덱스 없음(모두 한 세트), 태그만으로 식별, 매번 LRU로 교체.
• 5.11.4: 동일 접근 패턴을 완전 연관 캐시에 적용, 히트/미스 및 교체 추적.
• 5.11.5, 5.11.6: 2-word 블록 완전 연관 8워드 캐시, 각 참조 시 offset, tag만 확인, LRU로 교체, 히트/미스 기록.
• 5.11.7 (MRU): LRU 대신 MRU(가장 최근 사용) 교체 정책으로 다시 추적.
• 5.11.8 (Optimal): 최적 대체 정책(앞으로 가장 늦게 필요할 블록 교체)으로 다시 계산하면 miss 더 줄어듦.
핵심: 이 문제들은 실제로 주소를 2진수로 변환해 태그/인덱스/오프셋을 나누고, 각 접근마다 캐시 상태(어떤 태그가 어느 라인에 있나, 어떤 것이 LRU인지)를 갱신해야 한다. 여기서는 원리만 설명:
• Set associative나 fully associative일 때 인덱스가 줄어들거나 사라지고, 한 세트에 여러 블록이 들어가므로 miss가 줄어들 수 있다(충돌 줄음).
• LRU, MRU, Optimal 등의 대체 정책에 따라 miss 횟수가 달라진다. Optimal이 이론적으로 가장 miss가 적다.
5.12번: 멀티 레벨 캐시(Multilevel Caching)
• 기본 개념: L1 캐시 미스 발생 시 L2 캐시 접근, L2에서도 미스 나면 메인 메모리 접근. L2 캐시는 L1보다 크고 느리지만, L1 미스를 줄여 전체 성능 향상에 도움.
• 5.12.1: L1만 있을 때 CPI, L2를 직병렬(Direct-mapped)으로 추가했을 때의 CPI, 8-way 세트 연관 L2를 추가했을 때의 CPI를 계산.
방법:
1. 기본 CPI를 주고 (예: 1.5), L1 미스율, L2 미스율, 메모리 액세스 시간 등을 이용해 AMAT를 구한다.
2. AMAT(평균 메모리 접근 시간)으로부터 추가 사이클을 CPI에 반영.
3. 미스율이 절반으로 준다거나 메모리 접근 시간이 2배가 된다면 CPI가 어떻게 변하는지 비교.
핵심: L2 추가로 L1 미스를 빨리 해결해 CPI를 낮출 수 있고, 메인 메모리 접근 부담을 덜 수 있다.
• 5.12.2: L3 캐시 추가가 더 나은가?
L3는 L2보다 더 큰 캐시로, 더 낮은 레벨 미스를 줄인다. 하지만 액세스 시간이 더 길어질 수 있다. 장점: 미스율 추가 감소. 단점: 더욱 긴 접근 시간. 결과적으로 시스템 성능 향상 여부는 워크로드(프로그램 특성)에 따라 달라짐.
• 5.12.3: 과거 프로세서 사례(Pentium이나 Alpha) 언급. L2 캐시가 칩 외부에 있을 때 대역폭과 레이턴시 문제. 추가 캐시 용량으로 미스율 낮추는 대신 레이턴시 증가. 최적의 캐시 크기와 레벨 수는 균형 문제.
5.13번: MTBF(Mean Time Between Failures), Availability
• MTBF: 평균 고장간격(한 장치가 평균적으로 고장 없이 동작하는 시간)
• MTTR: 평균 수리시간
• Availability(가용성) = MTBF/(MTBF+MTTR)
문제에서 3년 MTBF, 1일 MTTR 등이 주어질 경우 시간을 같은 단위로 맞춘 뒤 계산. 예를 들어:
3년 ≈ 3*365일=1095일, MTTR=1일
Availability = 1095/(1095+1)=약 1095/1096≈99.9%
MTTR→0이면 가용성은 거의 100%에 수렴. MTTR 매우 커지면 장비 복구 힘들어 가용성 크게 떨어짐.
5.14번: SEC/DED (Single Error Correct / Double Error Detect) ECC 코드
• 5.14.1: 128비트 단어를 보호하기 위한 최소 패리티 비트 수 계산. SEC/DED 코드는 해밍 코드 변형으로, k비트 데이터 보호 위해 r비트 패리티 필요. 2^r ≥ k + r +1 조건 사용. 128비트일 때 r을 증가시키며 조건 만족하는 최소 r 찾음. 대략 128비트 보호 위해 약 8비트 정도의 패리티 필요(문제에서 자세히 계산 가능).
• 5.14.2: 64비트 당 8비트 패리티(예: 기존 코드 대비 새로운 코드) 성능/비용 비교. 패리티 비트 수(오버헤드) 대비 교정 성능(몇 개 에러까지 교정?) 비교. 적은 패리티로 동일 수준 교정 가능하면 효율적.
• 5.14.3~5.14.5: 8비트 데이터 보호에 4 parity bits 사용 시, 특정 값(0x375) 읽었을 때 오류 감지/수정 여부. 해밍 코드 테이블에 따라 에러 비트 위치 식별하고 수정 가능. 핵심: 해밍 코드로 단일 비트 에러는 교정, 이중 비트 에러는 검출 가능.
5.15번: 페이지 사이즈 최적화(Page size for B-tree index)
• 디스크 액세스 비용과 페이지 크기 선택. 페이지가 크면 한 번 읽을 때 더 많은 데이터 가져올 수 있으나 불필요한 데이터 전송 증가, 작은 페이지면 I/O 오버헤드 증가.
• 문제에서 표로 제공된 유틸리티(몇 개의 디스크 액세스 절약?), 인덱스 페이지 액세스 비용(ms), Utility/Cost 비율 제공.
• 5.15.15.15.3: 엔트리 크기나 페이지 반쯤 차있을 때, 디스크 대역폭 변할 때 최적 페이지 크기 재산정.
핵심: 주어진 조건에서 다양한 페이지 크기(2KB32KB 등)에 대해 Utility/Cost 비교 후 가장 높은 Utility/Cost 비율 갖는 페이지 크기 선택.
5.16번: 가상 메모리, TLB, 페이지 테이블 업데이트
• TLB(Translation Lookaside Buffer): 가상주소→물리주소 매핑 캐시. TLB miss 시 페이지 테이블 접근. 페이지도 메모리 없으면 디스크에서 로드(Page fault).
• 5.16.1: 주어진 가상 주소 스트림(예: 0x123d,0x08b3…)에 대해:
1. 페이지 번호와 오프셋 분리(4KiB 페이지면 하위 12비트 오프셋).
2. TLB에 해당 페이지 태그 있는지 확인 → 히트/미스 판정
3. 미스면 페이지 테이블 확인, 또 페이지가 메모리에 없는 경우 디스크에서 로드(page fault)
4. TLB 업데이트(LRU 방식)
이 과정을 각 주소에 대해 반복, 히트/미스, page fault 여부와 TLB 최종 상태 제시.
• 5.16.2~5.16.5: 페이지 크기 16KiB로 바꿔보거나, 2-way 세트 연관 TLB, direct-mapped TLB등 바꿨을 때 hit/miss 변화 파악. 페이지 크기 커지면 TLB 엔트리 수 감소하지만 miss penalty 증가 가능. Set associative TLB는 miss 줄일 수 있으나 접근 시간 증가.
• 5.16.5: 왜 TLB가 성능에 중요한가? TLB 없이 매번 페이지 테이블 접근하면 매우 느려짐. TLB는 가상→물리 변환을 빠르게 해 CPU 성능 유지.
5.17번: 페이지 테이블 크기 계산
• 파라미터: 32비트 주소, 8KiB 페이지, 4바이트 PTE(Page Table Entry)
• 5.17.1: 단일 레벨 페이지 테이블 크기 = (가상 주소 공간 / 페이지 크기) PTE크기
32비트 주소공간 =4GiB(≈42^30바이트)
페이지=8KiB=8192바이트
4GiB/8KiB=약 524288개 페이지 당 PTE 필요
PTE 하나 4바이트 → 총 524288*4바이트=약 2MiB 페이지 테이블 크기
5개의 프로세스라면 5배.
• 5.17.2: 2레벨 페이지 테이블 사용 시, 1레벨당 엔트리 수, 2레벨당 엔트리 수 계산해 실제 사용하는 PTE만 할당. 페이지 테이블 크기 감소. 최솟값: 필요한 엔트리만큼만 2레벨 페이지 테이블 할당, 최대값: 전체 가상 공간 커버하는 풀 트리 구성 시.
• 5.17.3: 페이지 크기 변화, 캐시 크기 변화에 따른 데이터 사이즈 결정. 가상 인덱스, 물리 태그 캐시 구현 시 데이터 부분 증가 필요성.
5.18번: 다단계 페이지 테이블 및 성능 최적화
• 5.18.1: 단일 레벨 페이지 테이블에서 PTE 수 = (가상공간/페이지크기).
• 5.18.2: 다단계 페이지 테이블로 메모리 절약. 활성화된 페이지만 PTE 할당. 레벨 수 = 주소 비트 분해해 상위 비트를 분배. 세그먼트 테이블+페이지 테이블 사용 시 세그먼트 테이블 크기, 페이지 테이블 크기 계산.
• 5.18.3, 5.18.4: 세그먼트 제한 시 테이블 깊이. 4바이트 PTE가 4KiB 페이지에 얼마나 많이 들어가는지, 필요한 레벨 수, 세그먼트 테이블 크기 등 계산.
5.18.5 (Inverted page table): 해시 기반 테이블에서 PTE 수 = 물리 메모리 페이지 수, 해시 충돌 시 추가 참조 필요. 보통 평균 1회 참조, 최악의 경우 여러 번 참조 필요. 장점: 크기 일정, 단점: 해시 충돌 시 탐색 비용 증가.
5.19번 문제 (TLB 상태표 분석)
표에 4-엔트리 TLB 상태가 주어지고, 각 엔트리에 Valid 비트, VA Page(가상 페이지), Modified 비트, Protection, PA Page(물리 페이지)가 있다.
• 5.19.1: 어떤 상황에서 엔트리 3의 Valid 비트를 0으로 만드는가?
TLB 엔트리의 Valid 비트는 그 엔트리에 해당하는 매핑이 더 이상 유효하지 않을 때 0으로 리셋된다. 예를 들어, 해당 페이지가 unmapped되거나, 프로세스 컨텍스트 스위치 시 flush, 해당 페이지 테이블 엔트리가 수정되었을 때 등의 상황.
즉, 페이지가 무효화되거나 해당 매핑이 사라지는 경우.
• 5.19.2: VA 페이지 30(가상 페이지 번호 30)에 접근 시 무슨 일이 일어나는가? 소프트웨어 관리 TLB vs 하드웨어 관리 TLB 비교.
하드웨어 관리 TLB의 경우 미스 시 하드웨어가 페이지 테이블 참조, 빠르게 TLB를 업데이트. 소프트웨어 관리 TLB는 miss 발생 시 OS 트랩, OS가 페이지 테이블 확인 후 TLB 업데이트. VA page 30이 TLB에 없으면 miss, 소프트웨어 관리라면 트랩 → OS처리 → TLB 업데이트 과정 필요.
소프트웨어 관리 TLB는 유연하지만 miss penalty가 클 수 있음. 특정 상황(특히 OS가 최적화할 때) 소프트웨어 관리가 빠를 수도 있지만 일반적으로 하드웨어 관리가 평균적으로 더 빠르다.
• 5.19.3: VA 페이지 200에 접근 시?
동일한 원리. TLB에 VA page 200 매핑 없으면 miss. miss 시 페이지 테이블 확인, 물리 페이지 찾기, TLB 업데이트. Protection 비트나 Modified 비트는 페이지 접근 권한과 쓰기 여부에 따라 설정.
5.20번 문제 (Replacement policy 영향)
2-way set associative 캐시, 각 세트 당 4워드 블록 중 2개 존재(2-way), 주소 시퀀스: 0,2,4,8,10,12,14,16,0,… 등
• 5.20.1 (LRU): LRU(Least Recently Used) 사용 시 어떤 접근이 히트인가?
주소를 순서대로 변환해 인덱스, 태그를 구한 뒤 캐시 라인에 들어가 있는지 확인. LRU는 가장 오래 사용하지 않은 블록을 치환. 반복적인 패턴(예: 0,2,4,8…)에서 일정 주기 후 다시 같은 블록이 온다면 히트 발생. 문제에서 0→2→4→8… 이런 식으로 일정한 패턴이라면, 실제 인덱스 계산 후 히트를 판단해야 한다. 여기서는 단순히 개념적으로: LRU 정책일 때 자주 재사용되는 어드레스는 히트 확률↑.
• 5.20.2 (MRU): MRU(Most Recently Used) 교체 정책은 마지막에 사용한 블록을 우선 추방. 이런 정책은 순차적 스트림에 불리할 수 있다. 예를 들어 0 사용 후 2,4,8… 계속 새로운 블록을 불러오면, 자주 재사용되는 블록을 계속 잘못 추방해 miss 증가 가능.
• 5.20.3 (Random): 무작위로 교체하면 평균적으로 LRU보다 성능이 떨어짐. 몇 번의 miss가 늘어나는지? 랜덤으로 동전 던지듯 선택 시 재사용 패턴을 전혀 활용하지 못해 miss가 증가.
• 5.20.4~5.20.5 (Optimal): 최적 정책은 앞으로 가장 늦게 사용될 블록을 교체. 실제 시스템에서 미래를 알 수 없으나, 최적 정책 가정 시 miss 최소화. 여기서는 실제 접근 시퀀스를 알고 있으므로, 가장 나중에 사용될 블록을 추방하면 miss 최소. Optimal 정책이 어떻게 miss를 줄이는지 설명 가능.
핵심: 교체 정책에 따라 동일한 접근 패턴에서 miss율 달라진다. LRU가 보통 좋은 성능, Random은 중간, MRU는 특정 패턴에 비효율적, Optimal은 이론적 최솟값.
5.21번 문제 (가상머신 성능, 트랩 오버헤드)
가상 머신(VMM) 환경에서 I/O 액세스, 트랩 오버헤드, CPI 계산 문제.
• 기본 CPI=1.5, priv. op. per 10,000 instr = 120, trap to guest OS=15 cycles, trap to VMM=175 cycles, I/O per 10,000 instr=30, I/O latency=1100 cycles 등 주어짐.
• 5.21.1: I/O가 없다고 가정하면 CPI 계산.
CPI = 기본CPI + (privileged op * trap penalty/명령어).
priv op 120/10,000명령어 → 0.012 priv op/명령어
각 priv op trap 15 cycles 추가 → 0.012*15=0.18 사이클 추가
총 CPI=1.5+0.18=1.68
VMM 오버헤드가 2배로 늘면 trap to VMM=350 cycles 가정 시, 만약 priv op 처리 시 guest OS→VMM 트랩 발생 시 추가적 계산 필요.
I/O 없으므로 I/O 부분 제외. 만약 VMM 오버헤드 절반이라면 trap penalty 절반 줄어 CPI 낮출 수 있다. 10% degradation 이하로 제한하려면 trap빈도와 penalty를 재계산해 최대 허용 cycle 도출.
• 5.21.2: I/O가 존재한다면 I/O miss penalty(1100 cycles) 고려. 비가상화 vs 가상화 환경 CPI 비교. 비가상화에서는 단순히 I/O latency만 반영, 가상화에서는 추가 trap to VMM 비용도 반영. I/O 빈도를 절반으로 줄이면 CPI 얼마나 개선되는지 계산 가능.
• 5.21.3: 가상화 장점/단점 정성적 비교. 언제 가상화 선호하는지 (서버 consolidation), 언제 기피하는지(극한 성능 요구).
5.23번 문제 (이기종 ISA 가상화)
QEMU같은 에뮬레이터 예를 들어, 다른 ISA를 에뮬레이션할 때 발생하는 어려움. 완전한 속도 달성 어려움, 원래 ISA보다 느려질 수 있음. 최적화 기법 필요. 이 문제는 정성적 설명.
5.24번 문제 (Write buffer 추가한 캐시 컨트롤러 FSM 설계)
• Write-back 캐시에서 더티 블록 교체 시 메모리 쓰기 때문에 시간 걸림. Write buffer 도입하면 프로세서는 블록 읽는 동안 더티 블록을 버퍼에 저장하고 비동기적으로 메모리에 쓰기.
• 5.24.1: 블록을 메모리에 쓰는 중 miss 발생 시 어떻게? write buffer 비우지 않고 miss 블록을 우선 가져올 수도 있음. 어떤 상황에서 stall하는지 설명.
• 5.24.3: Write buffer 지원하는 FSM 설계: 상태 다이어그램 그리기, miss 발생 시 dirty block write를 buffer에 enqueue, main memory write 끝나면 buffer 비움. 상태 전이와 신호, 제어 로직을 서술.
5.25번 (Cache coherence)
두 프로세서가 같은 캐시 블록 X의 다른 단어에 read/write. 캐시 일관성 프로토콜 없으면 한 프로세서 업데이트가 다른 쪽에 반영 안됨. 나쁜 값 관측 가능.
• 5.25.1~5.25.3: 일관성 보장 위해 MESI 또는 Snooping 프로토콜 사용. 가능한 시나리오 나열. Best case: 한 번의 invalidate, write-back 최소화. Worst case: 서로 번갈아 업데이트 → 매번 invalidation, miss 발생.
기본적으로 coherence는 read/write 순서에 따라 다양한 miss 패턴 생김.
5.26번 문제 (CMP - 멀티코어 Private vs Shared L2 캐시)
벤치마크 A,B에 대해 Private L2 vs Shared L2 miss율, hit latency 차이 비교.
• Private L2: 각 코어 전용 L2. Miss율 높을 수 있으나 hit latency 짧음(5 cycles).
• Shared L2: miss율 낮추나 latency 길어짐(20 cycles).
• 메모리 접근 180 cycles.
• 5.26.1: 어떤 벤치마크에 어떤 캐시가 좋은가? miss rate vs latency trade-off. 예: A는 10% vs 4%, B는 2% vs 1%. A의 경우 miss율 차이가 크므로 shared가 좋을 수 있음. B는 miss율 차이 적으나 latency 차이가 클 경우 private가 나을 수도 있다.
• 5.26.2: 코어 수 늘어나 off-chip 대역폭 병목 증가. Shared 캐시는 miss율 낮춰 off-chip 접근 줄일 수 있으나 latency 커짐. off-chip 대역폭이 두 배 필요하면 어떤 구조가 유리한지 분석.
• 5.26.3: single-threaded(코어 하나), multithreaded(동일 프로그램 여러 스레드), multiprogramming(서로 다른 프로그램) 상황에서 private vs shared L2 장단점. Shared는 전체 miss율 낮출 수 있지만 한 프로그램에 대한 보장 줄어듦, private는 독립성 but miss 많음.
• 5.26.4~5.26.6: Non-blocking L2, off-chip 대역폭 증가 필요성, concurrency 개선 등. 미래 코어 수 증가 시 off-chip BW가 얼마나 증가해야 동일 성능 유지? Miss를 효율적으로 처리하기 위해 비차단 캐시나 더 큰 대역폭 필요.
5.27번 문제 (로그 처리 최적화)
구조체 entry {srcIP, URL, refTime, status, browser[64]}
가장 많이 쓰는 필드는 캐시에 잘 들어맞는 곳에 배치. 64바이트 캐시 블록 가정 시, 자주 접근하는 필드를 한 블록 안에 몰아서 공간 지역성 향상. URL이나 browser같이 큰 필드는 덜 자주 쓰이면 뒤로 배치.
• 5.27.1: log entry에서 가장 자주 읽는 필드 식별, 그 필드를 블록 경계 맞춰서 배치하면 miss 감소.
• 5.27.2: 데이터 구조 재배치로 더 나은 spatial/temporal locality 달성.
• 5.27.3: 다른 로깅 함수와 결합 시에도 캐시 효율 개선 가능. hot field와 cold field 분리.
5.28번 문제 (SPEC CPU2000 캐시 성능 자료 활용)
• 5.28.1~5.28.3: MESA/GCC vs MCF/SWIM 같은 벤치마크 조합에서 64KiB, 1MiB L2 캐시, 세트 연관도 변화에 따른 miss type(Cold, Capacity, Conflict) 분석. 더 큰 캐시에선 capacity miss 줄고, 연관도 증가 시 conflict miss 줄어듦.
• 최적 세트 연관도 선택: L1은 direct-mapped, L2는 4-way 등 제안.
• 5.28.3: 세트 연관도 증가하면 라인 당 태그 저장 많아져서 태그 스토리지 늘어남. miss rate 낮출 수 있지만 비용↑.
5.29번 문제 (2단계 가상화: Shadow page table, Nested page table)
VA→PA→MA(Nested) 변환 시 TLB miss 처리에 더 많은 메모리 접근 필요.
• 5.29.1: Shadow page table vs Nested page table 시 같은 작업(프로세스 생성, TLB miss, page fault, context switch)에서 발생하는 동작 비교. Nested PT는 두 번의 페이지 테이블 워크 필요.
• 5.29.2: x86 4-level page table vs nested page table 접근 횟수 비교. TLB miss 시 native는 4번 테이블 접근(최대), Nested는 4번 * 2 =8번 등 더 많음.
• 5.29.3: TLB miss rate, miss latency, page fault rate, page fault handler latency 중 nested PT에서 중요한 것은 miss latency 및 reference count. Nested로 인한 2배 탐색 비용이 성능 영향.
• 5.29.4: NPT(Nested Page Table) 오버헤드로 CPI 변화 계산. 예: Base CPI=1, TLB miss per 1000 instr=0.2, NPT TLB miss latency=200 cycles, shadowing overhead=30,000 cycles/page fault 등.
각 이벤트 확률×penalty 더해 CPI 추산.
• 5.29.5~5.29.6: Page table shadowing 감소 기법, 예: Huge pages 사용, TLB reach 확대, 소프트웨어 최적화로 shadow overhead 감소. NPT 오버헤드 줄이기 위해 캐시된 변환 사용, 대형 페이지로 테이블 단계 줄이기.
정리:
• CPI 계산: CPI = Base CPI + (Event Frequency * Event Penalty)
• Page table 크기: (Virtual Memory Size / Page Size) * PTE Size
• ECC parity bits: 2^r ≥ data_bits + r + 1 조건으로 r 구하기.
• Replacement policy: 실제 접근 시퀀스 나열 후 hit/miss 판단.
• I/O 오버헤드: I/O 빈도 × I/O penalty를 CPI에 추가.
'Book > COMPUTER ORGANIZATION AND DESIGN RISC-V' 카테고리의 다른 글
CH5. Self-Study (0) | 2024.12.02 |
---|---|
5.11 Parallelism and Memory Hierarchy:Redundant Arrays of Inexpensive Disks (0) | 2024.12.02 |
5.10 Parallelism an Memory Hierarchy:Cache Coherence (0) | 2024.12.02 |
5.9 Using a Finite-State Machine to Control a Simple cache (0) | 2024.12.02 |
5.8 A common Framework for Memory Hierarchy (0) | 2024.12.02 |