이 글은 『이것이 컴퓨터 과학이다』를 읽으며, 책에 직접적으로 나오지 않았지만 제가 품게 된 의문에 대한 내용을 찾아보고 정리한 내용입니다.
𝐐. 메모리에 명령어와 데이터가 있는데 어디까지 명령어가 저장되고 어디부터 데이터가 저장되는가
메모리를 저장하는 아키텍처는 하버드 아키텍처와 폰 노이만 아키텍처가 있다.
하버드 아키텍처에서는 명령어 메모리와 데이터 메모리가 물리적으로 분리되어 있다. 그렇기 때문에 CPU가 명령어와 데이터를 동시에 읽을 수 있는 장점이 있다.
물리적으로 분리되어 있기 때문에 어디까지 명령어이고 어디부터 데이터인지는 의미가 없다.
폰노이만 아키텍처에서는 보통 명령어가 낮은 주소부터 저장된다. 메모리에는 텍스트 섹션과 데이터 섹션으로 나뉘는데 텍스트 섹션까지 명령어가 저장되고 데이터 섹션에 데이터가 저장된다.
𝐐. 텍스트 섹션이 다 차고 데이터 섹션에 공간이 남아있다면 명령어가 데이터 섹션에 저장될 수도 있는가
안된다. 일단 권한이 없기 때문에 실행 시 Segmentation fault 또는 Memory access violation 발생한다.
운영체제 시스템 설계에서는 메모리의 역할이 확실하게 분리되어야 한다.
명령어는 실행 권한이 있어야하고 데이터는 읽기 권한만 있으면 되기 때문에 각각을 분리해서 저장하고 권한을 부여하는 것이 더 좋다.
𝐐. 01 + 0.2 == 0.3 이 false로 나오는데 실제로는 로직에 넣을 때는 이걸 true로 넣어줘야 한다. 그럼 어떻게 할건가
a와 b를 더한 값이 c인지 확인하고 싶을 때는 c - (a+b) 가 아주 작은 값(ex 0.0000001)보다 작은지 확인하는 것으로 로직을 짤 수 있다.
𝐐. 코어가 2개 하드웨어 스레드가 4개라면 어떻게 실행되는 것인가 (이게 어떻게 가능한가)
하나의 코어가 2개의 하드웨어 스레드를 가지고 실행되는 것을 하이퍼 스레딩이라고 한다.
하나의 물리코어가 가진 실행자원
- 명령어 디코더 (Instruction Decoder)
- 산술 논리 유닛 (ALU)
- 부동소수점 유닛 (FPU)
- 로드/스토어 유닛 (Load/Store Unit)
- 레지스터 파일
- L1 캐시
- 명령어 파이프라인
일부는 공유, 일부는 복수로 존재
하이퍼 스레딩 과정
위의 공유 자원 중에 A스레드가 실행중일때 남는 공유자원이 있으면 B가 실행 될 수 있음.
𝐐. 구조적 위험(자원 위험)과 제어위험을 방지하는 방법에는 뭐가 있을까.
𝐐. 캐시 일관성 프로토콜
MSI 프로토콜
가장 기본이 되는 것은 MSI 프로토콜이다.
- Modified : 이 캐시에만 존재하며 메모리와 다름
- Shared : 여러 캐시에 복사되어 존재하며, 메모리와 같음
- Invalid : 사용 불가
한 CPU가 데이터를 변경하면 다른 CPU 캐시의 해당 블록을 Invalid로 만들고 변경한 데이터를 Modified로 만듦
𝐐. 다른 CPU가 같은 캐시에 내가 변경하려는 값을 가지고 있는지 어떻게 알까
정답은 모른다. 대신 모든 CPU가 감시하면서 알아서 응답한다. MSI는 Snooping 기반 프로토콜이다. Snooping이란 모든 CPU가 공유된 버스(bus)를 통해 다른 CPU의 캐시 접근을 감시(snoop) 하는 것을 뜻한다.
CPU A가 x 데이터를 쓰기 위해 버스에 write 신호를 보내면 다른 CPU들이 그것을 보고 자신도 x 데이터를 가지고 있는지 확인하고 자신의 x 데이터를 Invalid로 변경한다.
참고 : 스케일러블 시스템에서는 Directory-based 프로토콜을 사용한다. <-중앙에 디렉토리 라는 관리자가 CPU 다 감시하면서 적용해줌
MSI는 스누핑 기반을 사용한다.
MESI 프로토콜
MESI 프로토콜은 MSI에서 E(Exclusive)가 추가된 프로토콜이다. (가장 널리 쓰임)
Exclusive 상태는 나만가지고 있지만 메모리와 같음 상태이다. Exclusive 덕분에 메모리에 쓰기 없이 바로 수정 가능하고 Modified 상태는 반드시 쓰기 동기화를 메모리까지 해줘야 함.
MOESI 프토토콜
MOESI 프로토콜은 마찬가지로 O(Owned)가 추가된 것이다. (AMD에서 사용)
Owned 상태는 Modified처럼 값을 가지고 있으나, 다른 캐시가 읽을 수 있는 상태이다. (공유 가능)
Modified와 Shared의 중간 상태로 쓰기 후에도 다른 캐시가 읽기 가능하여 버스 트래픽 감소의 효과가 있다.
𝐐. 어떻게 Owned 상태가 버스 트래픽을 줄여주는 건가
CPU0이 x 데이터 읽기 작업을 하는데 CPU1이 x데이터를 Modified로 들고 있다면 메모리에 x 데이터 쓰기 작업을 하고 CPU0이 메모리에서 x데이터를 읽어와야한다.
읽기작업 한번에 2번의 트래픽이 발생하는 문제가 있다. Owned 상태의 데이터는 캐시-캐시 전달이 가능하다. 그렇기 때문에 CPU1에서 CPU0이 Owned 상태의 x 데이터를 가지고 오면 한번의 트래픽으로 해결할 수 있다.
캐시-캐시로 데이터를 전달하기 때문에 버스 트래픽이 줄어든다.
𝐐. 그럼 Owned 상태의 데이터는 언제 메모리에 반영되는 걸까
- 캐시에서 제거될 때
- 다른 CPU가 쓰기 요청 할 때
- 시스템에서 명시적으로 flush를 실행할 때
MESI 프로토콜
MESIF 프로토콜은 MESI에서 F(Foward)가 추가된 것이다. (Intel 에서 사용)
Foward 상태는 읽기 요청에 응답해줄 대표 캐시를 지정한다. (버스 트래픽 줄임)
𝐐. 어떻게 Foward 상태가 버스 트래픽을 줄여주는건가
스누핑 기반 프로토콜을 사용하기 때문에 버스에서 x라는 데이터에 읽기 요청을 하면 x 데이터를 Shared 상태로 가진 CPU 들이 모두 응답을한다. 이 트래픽을 줄이기 위해서 대표를 정하는 것이다. 한 CPU만 Foward 상태로 두고 나머지를 Shared 상태를 두면 읽기작업이 왔을 때 Foward 상태의 CPU에게만 응답 받으면 된다.