floatFirstTOC: right
🖥️ 시작하며🔍 컴퓨터 시스템 구성 요소📌 하드웨어 (Hardware)📌시스템 소프트웨어 (System Software)📌 응용 소프트웨어 (Application Software)⚙️ 프로그램 코드 레벨🔍 부동소수점🔍 파이프라인📌 해저드1️⃣ 구조적 해저드2️⃣ 데이터 해저드💡 Forwarding (전방 전달)💡 Load-Use Data Hazard3️⃣ 제어 해저드🔍 캐시(Cache)란?💡 메모리 구조🔍 캐시 메모리 ‘자주 사용하는 데이터’ 특성📌 시간적 지역성📌 공간적 지역성🔍 캐시의 구조📌 워드 (Word)📌 블록 (Block)📌 캐시 (Cache)🔍 캐시의 작동 방식📌 인덱싱📌 태그 매칭과 Vaild📌 Offset의 사용처💡 여전한 의문점 : 이 이미지는 무엇인가?
🖥️ 시작하며
컴퓨터 아키텍처에 대한 리뷰를 진행합니다.
🔍 컴퓨터 시스템 구성 요소
📌 하드웨어 (Hardware)
하드웨어는 컴퓨터 시스템을 구성하는 물리적인 장치
- 프로세서 (Processor): 중앙 처리 장치(CPU)는 컴퓨터의 두뇌 역할을 하며, 명령어를 해석하고 실행합니다.
- 메모리 (Memory): 메모리는 데이터를 일시적으로 저장하는 공간임. RAM(휘발성 메모리)은 시스템이 실행 중인 프로그램과 데이터를 저장하고, ROM(비휘발성 메모리)은 시스템 부팅에 필요한 펌웨어를 저장합니다.
- I/O 컨트롤러 (Input/Output Controller): I/O 컨트롤러는 입력 장치(키보드, 마우스)와 출력 장치(모니터, 프린터)를 관리하여, 이들 장치와 프로세서 간의 데이터 전송을 제어합니다.
📌시스템 소프트웨어 (System Software)
시스템 소프트웨어는 하드웨어와 사용자 간의 인터페이스를 제공
- 컴파일러 (Compiler): 컴파일러는 고급 언어로 작성된 소스 코드를 기계어로 번역하여 컴퓨터가 실행할 수 있도록 합니다.
- 운영 체제 (Operating System): 운영 체제는 컴퓨터 시스템의 기본적인 서비스 코드를 제공하며, 주요 기능은 다음과 같습니다:
- 입출력 처리 (Handling Input/Output): 키보드, 마우스 등의 입력 장치와 모니터, 프린터 등의 출력 장치 간의 데이터 흐름을 관리합니다.
- 메모리 및 저장소 관리 (Managing Memory and Storage): 프로그램이 사용할 메모리를 할당하고, 데이터가 저장되는 위치를 관리합니다.
- 작업 스케줄링 및 자원 공유 (Scheduling Tasks & Sharing Resources): 여러 프로그램이 동시에 실행될 때 CPU 시간을 분배하고, 시스템 자원을 효율적으로 공유합니다.
📌 응용 소프트웨어 (Application Software)
사용자가 특정 작업을 수행하기 위해 고급 언어로 작성된 프로그램
⚙️ 프로그램 코드 레벨
🔍 부동소수점
🔍 파이프라인
데이터를 처리하거나 작업을 수행하기 위해 여러 단계를 연결한 일련의 프로세스
📌 해저드
다음 사이클에서 다음으로 실행될 명령의 실행 불가능을 의미
1️⃣ 구조적 해저드
파이프라인의 자원이 동시에 여러 명령어에 의해 사용되어야 할 때 발생, 보통 메모리가 부족할 시 발생
2️⃣ 데이터 해저드
레지스터 상에서 현재 사용중인 데이터가 이전 명령어에 종속될 때 발생
💡 Forwarding (전방 전달)
→ 값을 레지스터에 저장할 필요가 없을 때, 값을 직접 전달하면 됩니다.
💡 Load-Use Data Hazard
메모리에서 직접 데이터를 가져와야 할 때, 즉
lw
와 같은 명령어를 사용할 때 발생합니다. 이런 경우에는 컴파일러 차원에서 코드를 재배치함으로써 해결합니다.3️⃣ 제어 해저드
분기 명령이 존재할 때, 즉 다음 명령어를 실행할지 결정하는 것이 이전 명령어의 결과에 따라 달라질 때 발생
→ 지연 분기 예측으로 해결합니다. 요즈음은 동적 분기 예측도 활용합니다.
🔍 캐시(Cache)란?
프로세스는 트랜지스터의 등장 이후 굉장히 빠른 속도로 발전한 반면, 메모리의 발전 속도는 프로세서에 비해 굉장히 더디게 발전했다. 이런 속도 간격을 메꾸기 위해
캐시(Cache)
가 나오게 되었다.캐시는 CPU 안에 들어가는 매우 빠른 메모리다. 자주 사용하는 데이터들은 미리 캐시에 넣어둔 후, 프로세서가 메인 메모리 대신 캐시에서 데이터를 가져오도록 해 처리 속도를 높이는 것이 목적이다.
💡 메모리 구조
그림에서 보는 바와 같이, 속도는 위로 올라갈수록 빨라지고 용량은 위로 올라갈수록 적어진다. 그리고 가장 중요하게 알아 둬야 할 것은 인접한 두 계층 사이에서만 데이터 전송이 일어난다는 것이다.
그럼 이러한 질문이 나올 수 있다.
왜 레지스터랑 캐시 메모리를 많이 만들지 않나요?
여러 이유가 있지만, 우선 가장 큰 이유는 비용이다. 또한 레지스터나 캐시 메모리는 작기 때문에 빠르다는 특성을 가지고 있다. 작아야 전기 신호가 빠르게 이동하고, 데이터에 더 빠르게 접근할 수 있기 때문이다.
🔍 캐시 메모리 ‘자주 사용하는 데이터’ 특성
자주 사용하는 데이터
의 기준은 지역성을 따릅니다.📌 시간적 지역성
한번 참조된 항목은 곧바로 다시 참조되는 경향을 말합니다.
가장 간단한 예는 반복문입니다.
for (int i = 0; i < 10; i++) { arr[i] = i; }
여기서 변수
i
는 곧바로 계속 참조되는 경향이 있다.📌 공간적 지역성
참조된 어떤 항목 근처의 다른 항목들이 곧바로 다시 참조되는 경향을 뜻합니다.
이것도 반복문을 보면 쉽게 알 수 있습니다.
for (int i = 0; i < 10; i++) { arr[i] = i; }
arr
의 요소는 붙어있으므로 근처 요소들이 곧바로 다시 참조됩니다.🔍 캐시의 구조
먼저 캐시를 알기 위해서는
워드
와 블록
을 알아야 합니다.또한 대전제로, 메모리는
1byte
단위로 취급된다는 것도 알아야 합니다. bit 단위가 아닙니다!📌 워드 (Word)
메모리에서 데이터를 액세스하는 기본 단위이다. 보통
32bit
운영체제에서는 32bit
, 즉 4B
가 데이터 엑세스 기본 단위입니다.📌 블록 (Block)
데이터의 기본 저장 단위입니다. 각 블록은 특정 크기(예 :
32B
)의 데이터를 저장하며, 여러 개의 워드를 포함합니다.즉 블록이
32B
의 데이터를 저장하면 32bit 운영체제에서 워드의 크기는 4B
이니 4개의 워드가 포함됩니다.📌 캐시 (Cache)
여러 개의 블록들의 집합입니다. 즉 캐시의 크기는 블록이 몇 개 있는지에 따라 결정됩니다.
예를 들어, 각 블록이
32B
를 저장할 수 있고 총 1024개의 블록
이 있다면, 캐시의 전체 크기는 32B
× 1024 블록
= 32,768B (32KB)
가 됩니다.그림으로 나타내면 다음과 같습니다.
🔍 캐시의 작동 방식
이제 캐시가 어떻게 작동하는지 알아야 합니다.
CPU에서 요청한 데이터가 캐시에 존재할 때
캐시 히트 (Hit)
라고 한다. 캐시에 존재하지 않으면 미스 (Miss)
났다고 하며, 하위 메모리에서 다시 값을 가져와야 합니다.그렇다면 CPU에서 어떤 메모리에 존재하는 데이터를 가져오기 위해 주소가 주어졌을 때, 어떻게 이 데이터가 캐시에 존재하는지, 즉
Hit
날 것인지 알 수 있을까요?여러 방법이 있지만, 일단 여기서는
Direct Mapping Cache
에 대해 설명하려고 합니다.📌 인덱싱
캐시는 당연하게도 메모리보다는 작으므로
32bit
전체를 가지고 바로 캐시로 접근할 수는 없습니다. 그러므로 Indexing
작업을 통해 접근합니다.위에서 가정했던 바와 같이 캐시 블록의 수가 1024개, 블록 사이즈가 32바이트라고 가정합시다.
→ 이므로 캐시 블록의 개수를 나타나는 데
10bit
가 필요합니다.→ 받은 전체 주소에서 하위
5bit
를 Offset
으로 지정하고, 이후 10bit
를 Index
로 사용해 캐시 블록에 접근합니다.그러나 이렇게만 사용한다면 캐시에 데이터가 존재한다면 이 데이터가 요청한 데이터가 맞는지 알기 힘들다. 중복되는 데이터가 굉장히 많기 때문입니다.
그렇기에 이런 충돌을 줄이기 위해
Tag
와 Vaild
를 사용합니다.📌 태그 매칭과 Vaild
- 주소의
Index
를 찾아 캐시로 들어갑니다.
Vaild
값이 0이라면 데이터가 없던 것, 1이라면 데이터가 있던 것이다. 0이라면 하위 메모리 계층에서 데이터를 갖고 와야 합니다.
Tag
를 비교해 일치하면 원하든 데이터인 것이므로Hit
처리하고Data
를 반환합니다.
📌 Offset의 사용처
오프셋
은 데이터의 정확한 위치를 찾기 위해 사용합니다.캐시에는 여러 블록이 있고, 물론 주소가 하나의 블록을 가리키지만 블록에도 여러 워드가 존재합니다.
만약 블록이
32B
라 가정합시다. 이므로 블록 내부 데이터를 가리킬 때 5bit
가 필요합니다.즉, 더 빠르게 데이터에 접근하기 위한 값이라 할 수 있습니다.
워드를 다시 생각해봅시다. 블록이
32B
라면 워드는 4B
이기 때문에 블록에 8개의 워드가 들어갑니다.→ 이므로 워드의 위치를 나타내는 데에
3bit
가 필요합니다.총 정리하면 아래와 같습니다.
- 상위 3비트 (비트 2, 3, 4): 이 비트들은 블록 내에서 워드의 위치를 선택하는 데 사용됩니다. 이 비트들은 0부터 7까지의 값을 가지며, 블록 내에서 각 워드의 시작 바이트를 지정합니다.
- 하위 2비트 (비트 0, 1): 이 비트들은 워드 내에서 바이트의 위치를 지정하는 데 사용됩니다. 워드가 4바이트이므로, 이 2비트는 워드 내에서 0부터 3까지의 바이트 위치를 선택하는 데 필요합니다.
💡 여전한 의문점 : 이 이미지는 무엇인가?
여기서는 태그 배열이 존재한다고 하셔서.. 어렵다 어려워. 제가 찾은 다른 참고자료들에는 이런 자료가 없어서 헷갈리긴 하지만 그래도 밑에 대충 적어보았습니다.
댓글