일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 핀토스 프로젝트 1
- 셋업
- 자 이제 시작이야
- 파란 장미
- alarm clock
- 핀토스 프로젝트 3
- 마일섬
- 글리치
- 끝
- 아직도 실험 중
- multi-oom
- 핀토스 프로젝트 2
- PINTOS
- 일지 시작한 지 얼마나 됐다고
- 가테
- 제발흰박
- 내일부터
- 핀토스 프로젝트 4
- 바빠지나?
- 핀토스 프로젝트
- 글루민
- 노가다
- Project 1
- 황금 장미
- botw
- Today
- Total
거북이의 쉼터
기말 대비용 정리 노트 (Lecture 4) 본문
오늘은 caching에 대한 심화 내용을 다룰 것이다. 뭔가 정리를 하다보니 cache에 대한 작은 소주제 여러개를 다루는 느낌이라 주제별로 분리해서 작성하였다.
아키텍처와 마이크로 아키텍처의 구분 (마이크로 아키텍처로서의 Cache)
architecture와 microarchitecture란 무엇일까? 수업 때도 차이를 설명 하셨지만 정말 완벽한 정리가 있는 블로그가 있어서 인용을 하자면
- Architecture (a.k.a. Instruction Set Architecture) - 하드웨어와 소프트웨어 인터페이스. 즉, 컴퓨터 하드웨어가 어떻게 소프트웨어와 상호작용 하는가.
- Microarchitecture - 아키텍처의 실행(구현)이 실제로 어떻게 되는가. 어떻게 컴퓨터가 동작하는가.
으로 정리할 수 있다. 아키텍처가 해당 칩을 사용할 프로그래머가 한눈에 확인하고 이용할 수 있도록 전체적인 구조를 나타내는 매뉴얼 개념이라면, 마이크로 아키텍처는 그러한 아키텍처가 구체적으로 어떻게 구현이 되어있는지를 나타내는 implementation detail이라고 할 수 있다. Intel과 AMD에서 기능적인 차이를 느끼지는 못하지만, 그 세부적인 구현(Cache data 보유 방식에서 inclusive Intel, exclusive AMD)에서 차이가 있다.
Software가 볼 수 있는 machine의 status에 해당하는 부분은 아키텍처에 해당하며, 마이크로 아키텍처에 해당하는 것은 드러나지 않는다. Instruction Set을 통해 레지스터와 DRAM을 컨트롤 할 수 있기 때문에 이들은 아키텍처이며, cache의 경우 일반적인 소프트웨어는 그 내부에 뭐가 들어있는지 확인하거나 임의로 변경할 수 없기 때문에 마이크로 아키텍처에 해당한다. 실제로 cache는 아키텍처인 DRAM의 속도 향상을 위한 implementation detail에 해당하는 부분이라고도 볼 수 있다. 물론 OS가 특정 cache line을 없애는 명령인 flush 등을 가지고 있기도 하나, 아키텍처는 SW가 instruction을 통해 해당 부품에 대한 전권을 가질 수 있다는 것이 차이가 있다. 명확한 구분을 위해서는 ISA에 기술된 내용이면 아키텍처, 묘사되지 않은 내부적인 내용이면 마이크로 아키텍처라고 생각하는 것이 좋다. 칩 디자이너가 임의로 아키텍처에 해당하는 부분을 바꿔버릴 경우 호환성의 문제가 생길 수 있기 때문에 대부분 성능 개선을 위해서는 마이크로 아키텍처 관련 부분을 바꾼다.
앞서 배운 OOO 등으로 인해 순차적으로 명령이 실행되지 않은 경우, 실행되지 말아야 할 명령어가 미리 실행되어 machine의 상태가 바뀐 경우를 생각해보자. 이 때, machine은 그 status에 해당하는 것과 그렇지 않은 것을 분류한다. 여기서 앞선 분류에 의해 아키텍처에 해당하는 것은 명령이 실행되기 이전의 원래 상태로 복구가 되지만, 마이크로 아키텍처에 해당하는 것은 그대로 유지된다. 이러한 마이크로 아키텍처의 특성 때문에 마이크로 아키텍처에 흔적을 남길 수 있는 행위는 모두 invalid 행동의 실행 결과를 남기는 방식으로 활용되어 attack hole이 될 수 있다.
Prefetching
찾는 내용이 cache에 없을 경우에는 손해가 커진다. 이를 미리 대처하기 위해 load/store 명령이 내려오지 않더라도 미리 필요할만한 데이터를 예측해서 cache로 가져온다. 아래와 같은 코드를 예시로 들어보자.
for (i = 0; i < N; i++) {
sum += a[i] * b[i];
}
보이는 코드 외에 어떠한 조치도 이루어지지 않는다고 할 때, 컴퓨터는 필요한 값을 메모리에서 가져와 cache에 두고 처리하려고 할 것이다. 문제는 계속해서 cold miss가 날 것이기 때문에 배열의 모든 값에 대해 메모리에서 cache로 load하는 것을 기다리게 될 것이라는 점이다. 메모리의 경우 한 번의 연산마다 100 cycle 정도를 기다려야 하기 때문에 아무 조치가 없다면 끔찍하게 비효율적일 것이다.
이를 대비해서 만약 유저가 위와 같이 prefetch하기 위한 코드를 넣었다고 하면, 초반 8번의 연산 동안은 어쩔 수 없이 느린 연산이 이루어지겠지만, 그 이후부터는 cache에 미리 값을 올려 놓았기 때문에 빠르게 값을 가져와서 연산할 수 있다.
HW 방식으로 prefetching이 이루어지게 할 수 있다. SW 방식으로 prefetching이 이루어지는 경우, 마이크로 아키텍처에 굉장히 민감하기 때문에 같은 코드라도 다른 기기에서는 최적의 성능을 내지 않을 수 있다. 따라서 유저가 본인의 코드와 각각의 마이크로 아키텍처에 대해 잘 알고 있지 않은 경우 fine tuning이 어렵다. HW prefetching은 이에 비해 전형적인 access patern에 대한 prefetching을 HW 단에서 처리할 수 있게 함으로서 개발자가 마이크로 아키텍처에 대한 이해가 없더라도 어느 정도의 성능을 낼 수 있도록 한다. 이는 일종의 Focus on Common Case라고도 볼 수 있다.
공격 패턴에 따라 다를 수 있지만 prefetching은 주로 HW 공격에 방해가 된다. 이는 prefetch가 공격으로 cache에 남긴 흔적을 overwrite하거나 다른 정보를 cache에 넣어 공격이 성공했는지의 여부를 확인하기 어렵게 만들기 때문이다. 이 때문에 최악의 경우 공격이 성공했는지도 판단하기 어려울 수 있다고 한다.
Local Storage (Software - managed cache)
cache가 있음에도 이걸 쓰는 이유는 unpredictable한 상황을 최대한 피하고 싶을 때를 생각할 수 있다. 만약 특정한 값이 계속해서 쓰일 것을 안다면 굳이 cache에 이를 올려 evict될 위험성을 감수하고 싶지 않을 것이다. 따라서 특정한 값의 활용 패턴 및 성질을 잘 알고 있다면 cache가 evict할 위험성을 배제하기 위해 local storage를 쓸 수 있다.
일반적인 cache가 마이크로 아키텍처인 것과 대조적으로 LS는 아키텍처적 요소이다. LS를 control하는 instruction이 명확하며, software가 명확한 의도를 가지고 데이터를 원하는 위치에 놓거나 제외할 수 있기 때문이다. 때문에 기능적으로는 cache와 비슷하더라도 HW 보안 측면에서는 다른 면모를 지니게 되는 것이다.
'코딩 삽질 > HW 요약 정리' 카테고리의 다른 글
기말 대비용 정리 노트 (Lecture 3) (0) | 2022.09.26 |
---|---|
기말 대비용 정리 노트 (Lecture 2) (0) | 2022.09.25 |
기말 대비용 정리 노트 (Lecture 1) (0) | 2022.09.23 |