CPU의 구조와 기능
- CPU는 기억장치에 저장되어 있는 프로그램 코드인 명령어들을 실행하며 '프로그램 수행'이라는 컴퓨터의 기본 기능을 수행
- 명령어 인출: 기억장치로부터 명령어를 읽어옴
- 명령어 해독: 수행해야 할 동작을 결정하기 위하여 명령어를 해독
- 데이터 인출: 명령어 실행을 위하여 데이터가 필요한 경우에는 기억장치 or I/O 장치로부터 그 데이터를 읽어옴
- 데이터 처리: 데이터에 대한 산술 or 논리 연산을 수행
- 데이터 저장: 수행한 결과를 저장
- 위 동작들 중 1, 2번 동작은 모든 명령어들에 대하여 공통적으로 수행되지만, 3-5번 동작은 명령어에 따라 필요한 경우에만 수행
1. CPU의 기본 구조
- CPU의 구성 요소
- 산술논리연산잔치(ALU): 각종 산술 연산들과 논리 연산들을 수행하는 회로들로 이루어진 하드웨어 모듈
- 레지스터 세트: CPU 내부에 위치한 기억장치로서, 액세스 속도가 컴퓨터의 기억장치들 중에서 가장 빠름. 그러나 내부 회로가 복잡하여 비교적 큰 공간을 차지하기 때문에, 많은 수의 레지스터들을 CPU의 내부에 포함시키기는 어려워 특수 목적용 레지스터들과 적은 수의 일반 목적용 레지스터들만 포함
- 제어 유닛: 프로그램 코드를 해석하고, 그것을 실행하기 위한 제어 신호들을 순차적으로 발생하는 하드웨어 모듈
- 명령어 실행에 필요한 각종 정보들의 전송 통로와 방향을 지정해주고, CPU 내부 요소들과 시스템 구성 요소들의 동작 시간도 결정
- CPU가 제공하는 명령어들의 수가 많아질 수록 제어 유닛의 내부 회로는 더 복잡해짐
- 복잡도를 줄이기 위해 제어 유닛의 동작을 SW로 처리해주는 방법이 마이크로프로그래밍
- 그러나 이 방법을 이용하면 명령어 실행 시간이 길어짐
- 따라서 최근에는 명령어의 수를 가능한 줄이고 명령어 형식을 단순화함으로써, HW만으로 명령어를 실행할 수 있도록 하는 RISC(Reduced Instruction Set Computer) 설계 개념도 많이 사용되고 있음
- CPU 내부 버스
- ALU와 레지스터들 간의 데이터 이동을 위한 데이터 선들과 주소 선들, 그리고 제어 유닛으로부터 발생되는 제어 신호들을 전송하는 선들로 구성
- 외부의 시스템 버스와 직접 연결되지 않으며, 반드시 버퍼 레지스터나 인터페이스 회로를 통하여 시스템 버스와 접속
2. 명령어 실행
- CPU가 한 개의 명령어를 실행하는 데 필요한 전체 과정이 명령어 사이클
- 명령어 사이클은 CPU가 기억장치로부터 명령어를 읽어 오는 명령어 인출 단계와 (인출 사이클)
- 인출된 명령어를 실행하는 명령어 실행 단계로 이루어짐 (실행 사이클)
- 명령어 사이클은 CPU가 프로그램 실행을 시작한 순간부터 전원을 끄거나 회복 불가능한 오류가 발생하여 중단될 때 까지 반복 수행
- 명령어 실행을 위해 기본적으로 필요한 CPU 내부 레지스터
- 프로그램 카운터(PC): 다음에 인출될 명령어의 주소를 가지고 있는 레지스터
- 누산기(AC): 데이터를 일시적으로 저장하는 레지스터. CPU가 한 번에 처리할 수 있는 데이터의 비트 수와 크기가 같음
- 명령어 레지스터(IR): 가장 최근에 인출된 명령어가 저장되어 있는 레지스터
- 기억장치 주소 레지스터(MAR): 프로그램 카운터에 저장된 명령어 주소가 시스템 주소 버스로 출력되기 전에 일시적으로 저장되는 주소 레지스터
- 기억장치 버퍼 레지스터(MBR): 기억장치에 저장될 데이터 혹은 이미 읽어온 데이터가 일시적으로 저장되는 버퍼 레지스터
2-1. 인출 사이클
- CPU는 각 명령어 사이클의 시작 단계에서 PC가 가리키는 기억장치의 위치로부터 명령어를 인출
- 그런 다음 CPU는 PC의 내용을 1씩 증가시킴으로써 명령어들을 기억장치에 저장되어 있는 순서대로 읽어올 수 있도록 해줌
- 인출 사이클에서 수행되는 동작의 마이크로 연산(CPU 클록의 각 주기 동안 수행되는 기본적 동작)
- t0: MAR <- PC // 현재 PC 내용을 CPU 내부 버스를 통하여 MAR로 보냄
- t1: MBR <- M[MAR], PC <- PC + 1 // 그 주소가 지정하는 기억장치 위치로부터 읽혀진 명령어가 데이터 버스를 통하여 MBR로 적재 + PC 증가
- t2: IR <- MBR // MBR에 저장되어 있는 명령어 코드가 명령어 레지스터인 IR로 이동
- cf. t0, t1, t2는 CPU 클록의 각 주기를 가리킴
- 명령어 인출에는 세 개의 CPU 클록 주기만큼의 시간이 걸림
- CPU의 클록 주파수가 1GHz라면 클록 주기가 1ns이므로, 인출 사이클은 3ns
2-2. 실행 사이클
- 인출된 명령어를 CPU가 해독하고, 그 결과에 따라 필요한 연산 수행
- CPU 수행 연산
- 데이터 이동: CPU와 기억장치 간 혹은 CPU와 I/O 장치 간 데이터 이동
- ex) LOAD addr
- t0: MAR <- IR(addr)
- t1: MBR <- M[MAR]
- t2: AC <- MBR
- 데이터 처리: 데이터에 대하여 산술 or 논리 연산 수행
- ex) ADD addr
- t0: MAR <- IR(addr)
- t1: MBR <- M[MAR]
- t2: AC <- AC + MBR
- 데이터 저장: 연산결과 데이터 혹은 입력장치로부터 읽어들인 데이터 기억장치에 저장
- ex) STA addr
- t0: MAR <- IR(addr)
- t1: MBR <- AC
- t2: M[MAR] <- MBR
- 프로그램 제어: 프로그램의 실행 순서 결정
- ex) JUMP addr
- t0: PC <- IR(addr)
2-3. 인터럽트 사이클
- CPU로 하여금 현재 진행 중인 프로그램 처리를 중단하고 다른 프로그램을 처리하도록 요구하는 메커니즘으로서, CPU와 외부장치들 간의 상호작용을 위하여 필요한 기능
- 인터럽트 서비스 루틴(ISR): 인터럽트 요구를 처리해주기 위해 수행하는 프로그램 루틴
- 인터럽트 사이클: 인터럽트 요구가 들어왔는지 검사하고, 그 처리에 필요한 동작들을 수행하는 과정
- 인터럽트 요구 신호 검사
- t0: MBR <- PC // 현재 PC 내용을 스택에 저장(인터럽트 처리 완료 후, 복귀 위함)
- t1: MAR <- SP, PC <- ISR의 시작 주소 // PC에 해당 ISP의 시작 주소를 적재
- t2: M[MAR] <- MBR, SP <- SP - 1 // 원래 PC의 내용을 스택에 저장 후, SP 감소
- 프로그램에 따라 **인터럽트 가능 상태(EI)**와 **인터럽트 불가능 상태(DI)**가 있음
- 인터럽트 사이클로 인해 AC에 저장된 값이 바뀔 수 있기 때문에, 인터럽트 서비스 루틴의 시작 단계에서 레지스터들의 내용을 스택에 저장하였다가, 루틴의 마지막 단계에서 복원시켜주는 절차가 필요함
- 다중 인터럽트의 처리 방법
-
- CPU가 ISR을 처리하고 있는 도중에는 새로운 인터럽트 요구가 들어오더라도 인터럽트 사이클을 수행하지 않도록 하는 것
- 이전 루틴을 처리하는 동안 CPU는 DI 상태. 루틴 처리하는 동안 발생한 인터럽트 요구는 대기 상태로 남아 있다가, CPU가 EI 상태로 바뀐 후에 인식됨
-
- 인터럽트 요구들 간에 우선순위를 정하고, 우선순위에 따라 수행 여부 판단
- 스택에는 원래의 주프로그램으로 복귀하기 위한 주소뿐 아니라, 첫 번째 ISR으로 복귀하는데 사용될 주소도 저장되어야 함
2-4. 간접 사이클
- 실행 사이클에서 사용될 데이터의 실제 주소를 기억장치로부터 읽어오는 과정
- t0: MAR <- IR(addr)
- t1: MBR <- M[MAR]
- t2: IR(addr) <- MBR
- 간접 사이클은 항상 수행되는 것이 아니며, 명령어 내의 특정 비트(ex: I 비트)가 1로 세트된 경우에만 수행
3. 명령어 파이프라이닝
- 명령어를 실행하는데 사용되는 하드웨어를 독립적인 단계로 분할하고, 그들로 하여금 동시에 서로 다른 명령어들을 처리하도록 함으로써 CPU의 성능을 높여주는 기술
- 분할되는 단계의 수가 많아질수록 처리 속도가 높아짐
3-1. 2단계 명령어 파이프라인
- 명령어를 실행하는 하드웨어를 인출 단계와 실행 단계라는 두 개의 파이프라인 단계로 분리 구성
-
명령어 선인출: 다음에 실핼될 명령어를 미리 인출하는 동작
- 많은 수의 명령어들을 실행시키는 경우에 얻을 수 있는 최대 속도 향상은 파이프라인 단계의 수와 같은 2배에 접근하게 됨
- 그러나, 실제로는 실행 단계가 인출 단계보다 더 긴 수행 시간을 보이기 때문에 2배만큼 빨리지지는 못함
3-2. 4단계 명령어 파이프라인
- 파이프라인 단계들의 처리 시간이 동일하지 않음으로 인하여 발생하는 효율 저하를 방지하는 방법
- 파이프라인을 명령어 인출(IF) - 명령어 해독(ID) - 오퍼랜드 인출(OF) - 실행(EX)의 4단계로 구성
- 파이프라이닝을 이용하여 얻을 수 있는 속도 향상의 관계식
- T = k + (N - 1)
- 파이프라인 단계의 수 k, 실행할 명령어들의 수 N
- 첫 번째 명령어를 실행하는 데 k 주기가 걸리고, 나머지 (N-1)개의 명령어들은 각각 한 주기씩만 소요
- 파이프라이닝을 사용하지 않을 경우, k x N 주기를 소모
- k-단계 파이프라이닝의 문제
-
- 모든 명령어가 k 단계를 거치지는 않음
- 어떤 명령어는 실행 과정에서 오퍼랜드의 인출이 필요 없을 수도
-
- 파이프라인 클록은 처리 시간이 가장 오래 걸리는 단계를 기준으로 정해짐 -> 쓸데없는 대기 시간 있을 수 있음
-
- 기억장치 충돌의 문제가 있을 수 있음
- IF 단계와 OF 단계는 모두 기억장치를 액세스하는데 이 때 기억장치 충돌의 문제 발생
-
- 조건 분기 명령어가 실행된다면, 미리 인출되어 파이프라인에서 처리하고 있던 명령어들이 무효화될 수 있음
-
슈퍼파이프라이닝: 2번 문제의 해결을 위해 명령어 파이프라인의 단계들을 더욱 잘게 분할하여 처리 속도를 높여주는 기술
- 최근에는 대부분의 프로세스들이 10 단계 이상의 단계들로 분할된 명령어 파이프라인 구조를 사용
- 3번 문제의 보완을 위해 IF 단계와 OF 단계가 직접 액세스하는 CPU 내부 캐시를 명령어 캐시와 데이터 캐시로 분리시키는 방법이 사용됨
- 조건 문기로 인한 성능 저하를 최소화시키기 위한 해결책
- 분기 예측: 분기가 일어날 것인지를 예측하고, 그에 따라 어느 경로의 명령어를 인출할 지를 결정하는 확률적 방법. 최근 분기 결과들을 저장하여 두는 분기 역사 표를 참조하여 예측하는 방법이 가장 널리 사용
- 분기 목적지 선인출: 조건 분기가 인식되면, 분기 명령어의 다음 명령어뿐 아니라, 조건이 만족될 경우에 분기하게 될 목적지의 명령어도 함께 인출하는 방법. 이 방법의 사용을 위해서는 분기 목적지 명령어를 별도로 저장해둘 수 있는 기억 장소가 추가되어야 함
- 루프 버퍼: 파이프라인의 명령어 인출 단계에 포함되어 있는 작은 고속 기억장치로 가장 최근에 인출된 일정 개수의 명령어들이 순서대로 저장됨
- 지연 분기: 분기 명령어의 위치를 적절히 조정하여 원래보다 나중에 실행되도록 재배치함으로써, 성능 저하를 최소화하는 방법
- 조건 분기 명령어에서 사용하는 조건들은 CPU 내부의 상태 레지스터에 저장
- 상태 레지스터: 연산처리 결과 및 시스템 상태를 가리키는 비트들을 저장하는 레지스터
3-3. 슈퍼스칼라
- CPU 내에 여러 개의 명령어 파이프라인들을 두어, 동시에 그 수만큼의 명령어들을 실행할 수 있도록 한 구조
- 슈퍼스칼라 프로세서에서 유의할 점으로는 동시에 처리할 명령어들이 서로 간에 영향을 받지 않고 독립적으로 실행될 수 있어야 한다는 것
- 두 명령어 사이에 데이터 의존성이 존재하지 않아야 함!
- 명령어들 간 데이터 의존성이 존재하면 파이프라인들의 일부 단계들이 idle 상태에 들어가 속도 향상을 저해
- m-way 슈퍼스칼라 프로세서가 N개의 명령어들을 실행하는 데 걸리는 전체 시간
- T(m) = k + N-m/m
- 처음 m개의 명령어들을 실행하는 k 주기 소요 + 매 주기마다 m개씩의 명령어들이 동시에 실행 완료
3-4. 듀얼 코어 및 멀티 코어
- 멀티 코어 프로세서: CPU 코어 여러 개를 하나의 칩에 넣은 것
- 멀티 코어에서는 각 CPU 코어가 슈퍼스칼라의 명령어 파이프라인에 비하여 독립성이 더 높음
- 별도의 하드웨어 모듈로, 시스템 버스 인터페이스와 내부 캐시만 공유
- 따라서 각 CPU 코어는 프로그램 실행을 독립적으로 수행하며, 필요한 경우에만 공유 캐시를 통해 정보 교환
- 독립적인 처리가 가능한 단위로 분할된 태스크 프로그램들이 CPU 코어들에 의해 동시에 처리됨
- 이와 같은 동시처리 기술을 멀티 태스킹 혹은 멀티 스레딩이라 부름
- CPU 코어가 많을수록 그 수만큼의 태스크 프로그램들을 동시에 처리할 수 있게 됨