04-1. ALU와 제어장치
ALU, 플래그, 제어장치, 제어신호
CPU의 구성 요소 중 ALU와 제어장치가 어떤 정보를 내보내고 받아들이는지를 중심으로 두 장치의 역할 학습
ALU
계산을 하는 부품인데 계산을 하기 위해서는 피연산자와 수행할 연산이 필요하다
📍 ALU가 받아들이는 정보
- 피연산자 : 레지스터 통해 받아들인다
- 제어신호 : 제어장치로부터 받아들인다(제어신호가 수행할 연산을 알려준다)
📍 ALU가 내보내는 정보
- 특정 숫자나 문자, 메모리 주소
- 플래그
연산할 때마다 메모리에 접근하면 속도가 그만큼 느려지기 때문에 ALU의 결과값은 레지스터에 우선 저장한다.
플래그(flag)
연산 결과에 대한 추가적인 상태 정보. 일종의 참고 정보이다
플래그들은 플래그 레지스터에 저장된다.
e.g. 이진수만 봐서는 양수인지 음수인지 판단이 어려워서 구분하기 위해 플래그를 사용한다.
연산 결과가 연산 결과를 담을 레지스터보다 클 때 '결과값이 너무 크다'(overflow) 는 추가 정보를 보낸다.
플래그 종류 | 의미 | 사용 예시 |
부호 플래그 | 연산 결과의 부호 | 1 : 음수 0 : 양수 |
제로 플래그 | 연산 결과가 0인지 여부 | 1 : 결과 0 0 : 결과 ~0 |
캐리 플래그 | 연산 결과 올림수나 빌림수 발생 여부 | 1 : 발생 0 : 발생하지 않음 |
오버플로우 플래그 | 오버플로우 발생 여부 | 1 : 발생 0 : 발생하지 않음 |
인터럽트 플래그 | 인터럽트 가능 여부 | 1 : 가능 0 : 불가능 |
슈퍼바이저 플래그 | 커널 모드인지 사용자 모드로 실행 중인지 | 1 : 커널 모드 0 : 사용자 모드 |
플래그 레지스터 : 제로 플래그가 1이므로 연산 결과가 0이다.
부호 플래그 0 |
제로 플래그 1 |
캐리 플래그 0 |
오버플로우 플래그 0 |
인터럽트 플래그 0 |
슈퍼바이저 플래그 0 |
이 밖에도 ALU 내부에는 계산을 위한 회로들이 존재한다.
- 가산기(+), 보수기(-), 시프터(시프트 연산), 오버플로우 검출기(오버플로우 대비)
제어장치
전기 신호를 내보내고, 명령어를 해석하는 부품
제어 신호 : 컴퓨터 부품들을 관리하고 작동시키기 위한 일종의 전기 신호
📍 제어장치가 받아들이는 정보
1. 클럭 신호(clock)
컴퓨터의 모든 부품을 일사불란하게 움직일 수 있게 하는 시간 단위
클럭의 주기에 맞춰 데이터가 이동되거나, 연산이 수행되거나, 명령어를 읽는다. 클럭이라는 박자에 맞춰 작동할 뿐 한 클럭마다 작동하는 것은 아니다.
하나의 명령어가 여러 클럭에 걸쳐서 처리될 수도 있다.
2. 해석해야 할 명령어
해석해야 할 명령어는 명령어 레지스터라는 특별한 레지스터에 저장된다.
제어장치는 명령어 레지스터가 주는 해석할 명령어를 받아들이고 ➡️ 해석한 뒤 ➡️ 제어 신호를 발생시켜 ➡️ 컴퓨터 부품들에게 수행할 내용을 알려준다.
3. 플래그 레지스터 속 플래그 값
플래그를 참고하여 제어 신호를 발생시킨다.
4. 시스템 버스 중에서 제어 버스로 전달된 제어 신호
제어 신호는 CPU 뿐만 아니라 입출력장치를 비롯한 CPU 외부 장치도 발생시킬 수 있다. 제어 장치만 만들어낼 수 있는 것 아님!
제어 버스를 통해 외부로부터 전달된 제어 신호를 받아들인다.
📍 제어장치가 내보내는 정보
1. CPU 외부에 전달하는 제어 신호
= 제어 버스로 제어 신호를 내보낸다
- 메모리에 전달하는 제어 신호 : 메모리에 저장된 값을 읽거나 새로운 값을 쓰고 싶을 때
- 입출력장치(보조기억장치)에 전달하는 제어 신호 : 입출력장치의 값을 읽거나 새로운 값을 쓰고 싶을 때
2. CPU 내부에 전달하는 제어 신호
- ALU에 전달하는 제어 신호 : 수행할 연산을 지시하기 위해
- 레지스터에 전달하는 제어 신호 : 레지스터 간에 데이터를 이동시키거나 레지스터에 저장된 명령어를 해석하기 위해
📌 확인 문제
1.
부호 플래그 = 1 이므로 음수이다.
101의 2의 보수 : 010+1 = 011
011 = 십진수 2^1 + 2^0 = 3 이므로 -3이다.
2.
- 제어장치는 제어 버스로 제어 신호를 내보내고, 제어 신호를 통해 ALU에 연산을 지시하고, 클럭 신호를 받아들인다.
- 산술 연산과 논리 연산을 담당하는 부품은 ALU이다.
3.
1 - 플래그 레지스터
2 - 명령어 레지스터
3 - 제어 버스
4.
하드 디스크는 CPU의 구성 요소가 아니다.
04-2. 레지스터
프로그램 카운터, 명령어 레지스터, 메모리 주소/버퍼 레지스터, 범용/플래그 레지스터, 스택 포인터, 베이스 레지스터
레지스터의 종류와 역할을 학습 후 각 레지스터를 통해 명령어 처리 과정 이해
프로그램속 명령어와 데이터는 실행 전후로 반드시 레지스터에 저장되므로, 레지스터에 저장된 값을 잘 관찰하면 프로그램의 실행 흐름을 파악할 수 있다. 즉, 프로그램 실행 시 CPU 내에서 어떤 일을 처리하는지, 어떤 명령어가 어떻게 수행되는지 알 수 있다.
프로그램 카운터(PC ; program counter)
메모리에서 읽어 들일 명령어의 주소 저장
프로그램 카운터를 명령어 포인터(IP, Instruction pointer)라고 부르는 cpu도 있다.
명령어 레지스터(IR ; Instruction Register)
방금 메모리에서 읽어 들인 명령어를 저장
제어장치에서는 명령어 레지스터 속 명령어를 받아들이고 해석 후 제어 신호를 내보낸다.
메모리 주소 레지스터(MAR ; Memory Address Register)
메모리의 주소를 저장하는 레지스터
CPU가 읽어 들이고자 하는 주소 값을 주소 버스로 보낼 때 메모리 주소 레지스터를 거친다.
메모리 버퍼 레지스터(MBR ; Memory Buffer Register)
메모리와 주고받을 값(데이터 혹은 명령어)을 저장
메모리에 쓰고 싶은 값, 전달받은 값은 메모리 버퍼 레지스터를 거친다.
- cpu가 주소 버스로 내보낼 값이 메모리 주소 레지스터를 거친다
- 데이터 버스로 주고받을 값은 메모리 버퍼 레지스터를 거친다
메모리 데이터 레지스터(MDR, Memory Data Register)라고 부르는 경우도 있다.
범용 레지스터(general purpose register)
다양하고 일반적인 상황에서 자유롭게 사용
메모리 주소나 값 모두 저장할 수 있다. 일반적으로 여러 개의 범용 레지스터가 있고, 대다수 cpu는 모두 갖고 있다.
플래그 레지스터
플래그(연산결과 혹은 cpu상태에 대한 부가 정보)를 저장
메모리에 저장된 프로그램을 실행하는 과정
✔️ 명령어가 각각 하나의 메모리 번지를 차지하고 있다고 가정
cpu로 실행할 프로그램이 메모리의 1000~1500번지에 저장되어 있고, 1000번지에는 1101가 저장되어 있다.
1. PC에 1000이 저장
PC는 메모리에서 읽어 들일 명령어의 주소를 저장하므로, 1000이 저장된다.
2. 1000번지를 읽기 위해 MRA에 1000 저장 후 주소 버스로 내보낸다.
MRA는 cpu가 읽을려고 하는 주소 값을 주소 버스로 보낼 때 거친다. 1000을 읽으려고 하니 MRA에 저장 후 주소 버스로 보낸다.
3. 제어 신호(메모리 읽기)는 제어 버스 통해 MAR 값은 주소 버스를 통해 메모리로 보내진다.
cpu 외부(메모리)로 보내는 제어 신호이므로 제어 버스 통해 전달한다.
4. 메모리 1000번지에 저장된 값이 데이터 버스 통해 MBR로 전달된다.
메모리에 쓸거나 전달받은 값은 MBR로 간다.
5. PC는 증가되어 (1001) 다음 명령어 읽을 준비를 한다
명령어 처리되는 것이 아니라 MBR로 값이 전달되면 PC가 먼저 다음 명령어의 주소로 업데이트한다.
💡 PC가 꾸준히 증가하면서 다음 명령어 읽을 준비 하므로 cpu가 차례로 프로그램 실행할 수 있다.
6. MBR에 저장된 값은 명령어 레지스터로 이동한다.
7. 제어장치는 명령어 레지스터의 명령어를 해석 후 제어 신호를 발생시킨다.
📌 순차적인 흐름이 끊기는 경우?
- 명령어 중 JUMP, CONDITIONAL JUMP, CALL, RET 등을 이용해 특정 메모리 주소로 실행 흐름을 이동하는 경우 프로그램은 차례로 실행되지 않는다. PC에는 변경된 주소가 저장된다.
1200번지 실행 도중 2500번지로 점프하라는 명령어를 만나게 된다면?
JUMP 2500
1201 이 아닌 2500을 PC에 저장한다.
- 인터럽트가 발생
특정 레지스터를 이용한 주소 지정 방식
프로그램 카운터, 스택 포인터, 베이스 레지스터는 주소 지정에 사용할 수 있는 특별한 레지스터이다.
1) 스택 주소 지정 방식
스택과 스택 포인터를 이용한 주소 지정 방식
📍스택 포인터(stack pointer) : 스택의 꼭대기를 가리키는 레지스터
즉, 스택의 어디까지 데이터가 채워졌는지 알 수 있다.
- 스택에서 데이터를 꺼내면 스택 포인터가 한칸 아래로 내려간다. (4번지 -> 5번지)
- 스택에 데이터를 추가한다면 스택 포인터가 한칸 위로 올라간다. (4번지 -> 3번지)
스택이라기 보다는 메모리 안에 스택처럼 활용할 수 있는 영역인 스택 영역이 있는데 이 영역은 다른 주소 공간과는 다르게 스택처럼 사용하기로 암묵적으로 약속됐다.
2) 변위 주소 방식(displacement addressing mode)
오퍼랜드 필드의 값(변위)과 특정 레지스터의 값을 더해 유효 주소를 얻어내는 방식
💡 유효 주소 : 연산 코드에 사용할 데이터가 저장된 위치, 즉 연산의 대상이 되는 데이터가 저장된 위치
변위 주소 지정 방식을 사용하는 명령어
연산 코드 | 레지스터 | 오퍼랜드 |
해당 레지스터 값 + 오퍼랜드의 주소 값 = 유효주소
오퍼랜드 필드의 주소와 어떤 레지스터를 더하는지에 따라 상대 주소 지정 방식, 베이스 레지스터 지정 방식 등이 있다.
2-1) 상대 주소 지정 방식(relative addressing mode)
오퍼랜드 + 프로그램 카운터 = 유효 주소
- 프로그램 카운터 : 8
- 오퍼랜드 : -3
➡️ 세 번째 이전 번지(세 칸 이전 번지)인 5번지의 명령어를 실행한다.
➡️ 오퍼랜드가 3 이면 세 번째 이후 번지인 11번지로 접근한다.
2-2) 베이스 레지스터 주소 지정 방식(base-register addressing mode)
오퍼랜드 + 베이스 레지스터 = 유효 주소
📍베이스 레지스터 : 기준주소
📍오퍼랜드 : 기준 주소로부터 떨어진 거리
- 베이스 레지스터 : 200
- 오퍼랜드 : 40
➡️ 기준 주소 200번지부터 40만큼 떨어진 240번지로 접근
📌 확인 문제
2.
- 플래그 레지스터 : 연산 결과 혹은 CPU 상태에 대한 부가 정보를 저장하는 레지스터
- 프로그램 카운터 : 메모리에서 가져올 명령어의 주소를 저장하는 레지스터
- 범용 레지스터 : 데이터와 주소를 모두 저장할 수 있는 레지스터
- 명령어 레지스터 : 해석할 명령어를 저장하는 레지스터
04-3. 명령어 사이클과 인터럽트
명령어사이클, 인터럽트, 예외, 하드웨어 인터럽트, 인터럽트 서비스 루틴
CPU가 하나의 명령어를 처리하는 흐름인 명령어 사이클과 그 흐름을 방해하는 인터럽트에 대해 학습
명령어 사이클
하나의 명령어를 처리하는 정형화된 흐름
프로그램 속 각각의 명령어들이 반복되며 실행되는 주기
1단계 : 인출 사이클(fetch cycle)
메모리에 있는 명령어를 cpu로 가져오는 단계
✔️ 위의 메모리에 저장된 프로그램을 실행하는 과정
2단계 : 실행 사이클(execution cycle)
cpu로 가져온 명령어를 실행하는 단계
제어장치가 명령어 레지스터에 담긴 값 해석 후 제어 신호를 발생
간접 사이클(indirect cycle)
✔️ 간접 주소 지정 방식은 오퍼랜드 필드에 유효 주소의 주소를 명시하므로, 명령어 인출해 cpu로 가져와도 바로실행 사이클로 가지 못하고 한번 더 메모리 접근이 필요하다. ➡️ 추가로 메모리 접근이 필요한 경우 간접 사이클
인터럽트 사이클
인터럽트 처리하는 사이클
인터럽트
cpu의 작업을 방해하는 신호
➡️ cpu가 꼭 주목해야 할 때
➡️ cpu가 얼른 처리해야 할 다른 작업이 생겼을 때
인터럽트의 종류를 구분하는 통일된 기준은 없다. 아래의 내용은 인텔 공식 문서 참조
동기 인터럽트(synchronous interrupts) = 예외(exception)
cpu에 의해 발생
cpu가 명령어들을 수행하다 예상치 못한 상황에 마주쳤을 때 발생(e.g. 프로그램 상 오류)
비동기 인터럽트(asynchronous interrupts) = 하드웨어 인터럽트
주로 입출력장치에 의해 발생
세탁기완료 알림 등 알림 역할 수행
[사용처]
- cpu가 프린트 등의 입출력장치에 입출력 작업 부탁 ➡️ 작업 끝낸 입출력장치가 cpu에 완료 알림(인터럽트) 보냄
- 키보드 마우스와 같은 입출력장치가 어떠한 입력 수용 ➡️ 처리 위해 cpu에 입력 알림(인터럽트) 보냄
✔️ 만약 하드웨어 인터럽트가 없다면?
입출력장치는 느려서 cpu가 입출력 장치의 결과를 바로 받아볼 수 가 없어 주기적으로 프린터의 완료 여부를 확인해야 한다.
cpu 사이클 낭비!
[순서]
- 입출력장치가 cpu에 인터럽트 요청 신호를 보냄
- cpu가 실행 사이클이 끝나고 명령어 인출 전 항상 인터럽트 여부 확인
- cpu는 인터럽트 요청을 확인하고 인터럽트 플래그를 통해 현재 인터럽트를 수용가능 여부 확인
- 인터럽트 수용 가능하면 cpu는 지금까지의 작업을 백업
- cpu는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행
- 인터럽트 서비스 루틴 실행이 끝나면 백업 둔 작업을 복구해 실행 재개
✔️ 하드웨어 인터럽트는 인터럽트 플래그로 막을 수 있는 인터럽트와 막을 수 없는 인터럽트가 존재(정전, 하드웨어 고장)
📍 인터럽트 서비스 루틴(ISR; Interrupt Service Routine) = 인터럽트 핸들러(interrupt handler)
인터럽트를 처리하는 프로그램
➡️ cpu가 인터럽트 처리 = 인터럽트 서비스 루틴을 실행 후 본래 수행하던 작업으로 돌아온다.
📍 인터럽트 벡터(interrupt vector)
인터럽트 서비스 루틴의 시작 주소를 포함하는 인터럽트 서비스 루틴의 식별 정보
서비스 루틴의 시작 주소를 알 수 있어서 cpu가 인터럽트 벡터 통해 인터럽트 서비스 루틴을 처음부터 실행할 수 있다.
인터럽트 서비스 루틴도 명령어와 데이터로 이루어져 있는데, 그래서 인터럽트 서비스 루틴도 레지스터를 사용하며 실행된다.
📍 백업
현재 프로그램을 재개하기 위해 필요한 모든 내용을 스택에 백업 후 pc를 인터럽트 서비스 루틴의 시작 주소로 갱신 후 루틴 실행
인터럽트 처리 후 스택에 저장한 값을 불러와 작업 재개
05-1. 빠른 CPU를 위한 설계 기법
클럭, 코어, 멀티코어, 스레드, 멀티스레드
클럭과 코어, 스레드 학습 후 빠른 CPU를 만드는 설게기법인 멀티코어와 멀티스레드 이해
1) 클럭
클럭 신호가 빠르면 cpu 포함 컴퓨터 부품들이 빠른 박자에 맞춰 움직인다
➡️ cpu는 명령어 사이클을 더 빠르게 반복하고, 다른 부품들도 그에 맞게 더 빠르게 작동한다.
➡️ 일반적으로 클럭 속도가 높은 cpu는 성능이 좋다
➡️ cpu 속도 단위로 간주된다.
클럭 속도
1초에 클럭이 반복되는 횟수(Hz)
1초에 한번 : 1Hz
실제 cpu 클럭 속도는 기본 2.5GHz, 최대 속도 4.9GHz로 1초에 클럭이 기본적으로 25억번, 순간적으로 45억번 반복
✔️ 클럭은 시계처럼 일정 속도가 유지되는 것이 아니라 고성능 요할땐 빠르게, 평범할땐 낮춰 유연하게 대응한다.
✔️ 오버클럭킹(overclocking) : 최대 클럭 속도를 강제로 끌어올리는 기법
cpu에 무리가 가는 작업(그래픽 많이 요구되는 게임이나 영상 편집 등)을 장시간 하면 발열 문제가 생긴다. 클럭 속도를 무턱대고 높이면 발열 문제가 심각해지므로, 클럭 속도가 높다고 해서 cpu가 빨라지는 것은 아니다.
2) 코어와 멀티코어
코어(core)
명령어를 실행하는 부품(cpu)
- 8코어 : 명령어를 실행하는 부품 8개
멀티코어(multi-core) CPU (멀티코어 프로세서)
코어를 여러 개 포함하고 있는 CPU
멀티코어의 처리 속도는 단일코어보다 빠르다.
✔️ 성능 : 클럭 속도가 2.4GHz인 단일 코어 < 클럭 속도가 1.9GHz인 멀티코어
✔️ 프로세서 명칭 : 싱글코어 // 듀얼코어, 트리플코어, 쿼드코어, 헥사코어, 옥타코어, 데카코어, 도데카코어
cpu의 연산 속도는 항상 코어 수에 비례하여 증가하지 않는다.
처리하고자 하는 작업량보다 코어 수가 지나치게 많아도 성능에 영향을 미치지 않는다.
📌 코어마다 처리할 명령어들을 얼마나 적절하게 분배하는 것이 포인트!
3) 스레드와 멀티스레드
스레드(thread)
하드웨어적 스레드(cpu) : 하나의 코어가 동시에 처리하는 명령어 단위
소프트웨어적 스레드(프로그래밍) : 하나의 프로그램에서 독립적으로 실행되는 단위
하드웨어적 스레드(cpu에서 사용)
하나의 코어가 동시에 처리하는 명령어 단위
✔️ 2코어 4스레드 cpu : 명령어 실행 부품 2개 포함 + 한 번에 네 개의 명령어 처리(1코어당 2개의 하드웨어 스레드 처리)
✔️ 멀티스레드(multithread) 프로세서 (멀티스레드 CPU) : 하나의 코어로 여러 명령을 동시에 처리하는 cpu
✔️ 하이퍼스레딩(hyper-threading) : 인텔의 멀티스레드 기술 이름
소프트웨어 스레드
하나의 프로그램에서 독립적으로 실행되는 단위
➡️ 프로그래밍 언어나 운영체제 학습 시 접하는 스레드
Q) 워드 개발 시 입력받은 내용 화면에 보여주는 기능, 입력한 내용이 맞춤법에 맞는지 검사, 내용 수시로 저장 기능 동시에 수행되려면?
A) 해당 기능을 작동시키는 코드를 각각의 스레드로 만들기
💡 1코어 1스레드 cpu도 소프트웨어 스레드를 수십 개 실행이 가능하다.
멀티스레드 프로세서
핵심은 레지스터!!
pc, stack pointer, MAR, MBR 등 하나의 명령어 처리 위해 꼭 필요한 레지스터를 여러 개 가져야 한다.
레지스터 세트가 2개인 cpu는 두 개의 명령어를 처리하기 위한 정보들을 기억하는 것이 가능하다.
ALU와 제어장치가 두 개의 레지스터 세트에 저장된 명령어 해석 후 실행 시 1코어에서 2명령어가 동시에 실행된다.
📌 하드웨어 스레드 = 논리 프로세서(logical processor)
메모리 속 프로그램의 입장 : 하드웨어 스레드는 한 번에 하나의 명령어를 처리하는 cpu
2코어 4스레드 cpu는 한 번에 4개의 명령어를 처리하는데, 프로그램 입장에서는 1회 1명령어 처리하는 cpu 4개로 보인다.
즉 작업 흐름이 4개가 있으므로 코어가 네개인가.. ?
📌 확인 문제
4. 코어
코어는 cpu내에서 명령어 처리하는 부품이고, cpu는 코어를 여러 개 가질 수 있다 = 멀티코어 cpu
05-2. 명령어 병렬 처리 기법
명령어 파이프라이닝, 슈퍼스칼라, 비순차적 명령어 처리 기법
명령어를 빠르고 효율적으로 처리하기 위해 CPU를 한시도 쉬지 않고 작동시키는 명령어 병렬 처리 기법 알아보기
빠른 CPU 위해 높은 클럭 속도, 멀티코어, 멀티스레드 지원하는 CPU 만드는 것도 중요하지만, CPU가 쉬는 시간 없이 작동하게 만드는 것이 중요해 명령어 동시에 처리하는 명령어 처리 기법(ILP; Instruction-Level Parallelism)도 필요하다.
명령어 파이프라인
하나의 명령어가 처리되는 과정을 클럭 단위로 나누면
- 명령어 인출(Instruction Fetch)
- 명령어 해석(Instruction Decode)
- 명령어 실행(Execute Instruction)
- 결과 저장(Write Back)
cf) 전공서에 따라 명령어 인출 ➡️ 명령어 실행 / 명령어 인출 ➡️ 명령어 해석 ➡️ 명령어 실행 ➡️ 메모리 접근 ➡️ 결과 저장 으로 나누기도..
📍 같은 단계가 겹치지만 않으면 CPU는 각 단계를 동시에 실행할 수 있다. 명령어들을 명령어 파이프라인(instruction pipeline)에 넣고 동시에 처리하는 기법이 명령어 파이프라이닝(instruction pipelining)이다.
파이프라이닝 위험(pipeline hazard)
특정 상황에서 성능 향상에 실패하는 상황
데이터 위험(data hazard)
명령어 간 데이터 의존성에 의해 발생
명령어 1: R1 <= R2 + R3
명령어 2: R4 <= R1 + R5
명령어 1을 수행해서 R1을 구해야 명령어 2를 제대로 수행할 수 있다. 즉 명령어 2는 명령어 1 데이터에 의존적이다.
데이터 의존적인 두 명령어를 무작정 동시에 실행하려고 하면 파이프라인이 제대로 작동하지 않는다.
제어 위험(control hazard)
분기 등으로 인한 PC의 갑작스러운 변화에 의해 발생
✔️ 프로그램 카운터(PC) : 기본적으로 현재 실행 중인 명령어의 다음 주소로 갱신
❓ 10번지, 11번지, 12번지를 동시에 처리하고 있었는데 10번지 명령어 처리중에 60번지로 분기해야 한다면 11번지, 12번지 명령어들은 쓸모없어진다.
❗️ 분기 예측(branch prediction) 기술을 통해 어디로 분기할 지 미리 예측해 해당 주소를 인출한다.
구조적 위험(structual hazard)
명령어 병렬 처리 중 서로 다른 명령어가 동시에 같은 CPU 부품을 사용해야할 때 발생
자원 위험(resource) 라고도 부른다.
슈퍼스칼라(superscalar)
CPU 내부에 여러 개의 명령어 파이프라인을 포함한 구조
✔️ 슈퍼스칼라 프로세서(슈퍼스칼라 cpu) : 슈퍼스칼라 구조로 명령어 처리가 가능한 cpu
매 클럭 주기마다 동시에 여러 명령어 인출이 가능. 즉 같은 단계를 동시에 처리할 수 있다.
멀티스레드 프로세서는 한 번에 여러 명령어를 인출하고 해석하고 실행할 수 있기 때문에 슈퍼스칼라 구조 사용이 가능하다.
✔️ 슈퍼스칼라 프로세서는 이론적으로 파이프라인 개수에 비례하여 프로그램 처리 속도가 빨라지는데, 파이프라인 위험 등의 예상치 못한 문제가 있어 실제로는 반드시 개수에 비례해 빨라지지 않다.
여러 개의 파이프라인을 이용하면 하나 이용 시보다 파이프라이닝 위험을 피하기 더욱 어렵다.
비순차적 명령어 처리(OoOE; Out-of-order execution)
오늘날 cpu 성능 향상에 크게 기여했고, 대다수의 cpu가 차용하는 기법이므로 중요하다!
명령어들을 순차적으로 실행하지 않는 기법, 즉 합법적인 새치기!
- 명령어 파이프라이닝 / 슈퍼스칼라 : 여러 명령어의 순차적인 처리를 상정
- 비순차적 명령어 처리 : 순차적으로 처리하지 않음
❓ 파이프라이닝 위험 등 예상치 못한 문제들이 발생해 명령어가 곧바로 처리되지 않을 수 있다. 이 상황에서 모든 명령어를 순차적으로 처리하게 된다면 명령어 파이프라인이 멈춘다.
# 메모리 N번지에 M을 저장하라 ; M(N) <- M
M(100) <- 1
M(101) <- 2
M(102) <- M(100) + M(101)
M(150) <- 1
M(151) <- 2
3번 실행 위해너는 1,2 명령어 실행이 끝날 때까지 기다려야 하므므로 3, 4, 5 명령어들은 2번이 끝날 때까지 대기한다.
💡 4, 5 명령어는 데이터 의존성이 없어 순서를 바꿔 처리해도 수행 결과에 영향을 주지 않는다. 데이터 의존성이 있는 3번을 맨 끝으로 보내서 4, 5 명령어가 기다리지 않고 1, 2와 병렬 처리될 수 있도록 위치를 바꿔 파이프라인이 멈추는 것을 방지할 수 있다!
📍 아무 명령이나 바꾸면 안되니 고려해야 할 부분
- 데이터 의존성이 있는지?
- 순서를 바꿔 실행할 수 있는 명령어에는 어떤 것이 있는지?
05-3. CISC와 RISC
ISA, CISC, RISC
CPU의 언어인 ISA를 이해하고, 현대 CPU의 주요 설계 방식인 CISC, RISC 정의와 차이점 학습
명령어 집합(instruction set), 명령어 집합 구조(ISA; Instruction Set Architecture)
cpu가 이해할 수 있는 명령어들의 모음
✔️ 명령어의 기본 구조와 작동 원리는 비슷하지만, 명령어의 생김새, 할 수 있는 연산, 주소 지정 방식은 cpu마다 차이가 있다.
즉, cpu마다 ISA가 다를 수 있다는 의미.
✔️ cpu가 어떤 명령어를 이해하는지에 따라 컴퓨터 구조 및 설계 방식이 달라지므로 명령어 집합 '구조' 이다.
e.g.
- 인텔 노트북 속 cpu : x86(32비트용), x86-64 ISA(64비트용)
- 애플의 아이폰 속 cpu : ARM ISA
📍 인텔의 노트북과 애플의 아이폰은 서로의 명령어를 이해할 수 없다. 실행 파일은 명령어로 이루어져 있고 서로의 컴퓨터가 이해할 수 있는 명령어가 다르기 때문! 명령어가 달라지니 어셈블리어도 달라진다.
동일한 소스 코드를 작성하고 ISA가 다른 컴퓨터에서 어셈블리어로 컴파일하면 얻는 결과가 달라진다.
✔️ 사용한 컴파일러에 따라서도 어셈블리어가 달라질 수도 있다.
ISA가 다를 때 나타는 효과
- 명령어의 생김새
- 제어장치가 명령어를 해석하는 방식
- 사용되는 레지스터의 종류와 개수
- 메모리 관리
- cpu 하드웨어 설계
ISA는 CPU의 언어임과 동시에 CPU를 비롯한 하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속이다.
ISA 중 명령어 병렬 처리 기법들을 적용하기 용이한 ISA가 있는가 반면 그렇지 못한 ISA도 있다.
📍 명령어 병렬 처리 기법들을 도입하기 유리한 ISA
- CISC
- RISC
CISC(Complex Instruction Set Computer)
복잡한 명령어 집합을 활용하는 컴퓨터(CPU)
e.g. x86, x86-64
특징
✔️ 가변 길이 명령어 활용
다양하고 강력한 기능의 명령어 집합을 활용하므로 명령어의 크기와 형태가 다양해야 한다.
➡️ 상대적으로 적은 수의 명령어로도 프로그램 실행이 가능하다 = 컴파일된 프로그램의 크기가 작다(실행 파일의 크기가 작다)
➡️ 메모리를 최대한 아끼며 개발이 가능하다.
e.g. ARM 명령어 여러 개로 수행할 수 있는 일을 몇 개만으로 수행이 가능하다.
✔️ 특별한 상황에서만 사용되는 독특한 주소 지정 방식들이 존재
단점
✔️ 명령어가 복잡해 다양한 기능을 제공하기 쉽지만 그로인해 명령어 규격화가 어려워 파이프라이닝이 어렵다.
- 명령어의 크기와 실행되기까지의 시간이 일정하지 않다.
- 복잡한 명령어로 인해 명령어 하나 실행되는 데 여러 클럭 주기가 필요하다.
❗️ 명령어 파이프라인 기법을 위해서는 각 단계에서 소요되는 시간이 (가급적 1클럭으로) 동일해야 한다. 현대 CPU에서는 명령어 파이프라인이 높은 성능을 내기 위한 핵심 기술이므로 매우 중요하다.
✔️ 대다수의 복잡한 명령어의 사용 빈도가 높지 않고 실제로는 자주 사용되는 명령어가 주로 쓰인다.
➡️ CPU 성장에 한계가 있다.
RISC(Reduced Instruction Set Computer)
사용되는 명령어의 종류가 적다.
짧고 규격화된 명령어, 되도록 1클럭 내외로 실행되는 명령어 지향
CPU성능 향상을 위해 중요한 것
- 빠른 명령어 처리를 위해 파이프라인이 이용이 필수적 ➡️ 명령어 길이와 수행 시간이 짧고 규격화되어 있어야 한다.
- 자주 쓰이는 명령어 위주로 사용 ➡️ 복잡한 기능 지원 명령어 추가보다는 자주 쓰이는 기본적인 명령어를 작고 빠르게 만들어야 한다.
특징
✔️ 고정 길이 명령어 사용
➡️ 명령어가 규격화되어 있고, 1클럭 내외로 실행되므로 명령어 파이프라이닝에 최적화
✔️ 메모리 접근 단순화하고 최소화
- 메모리에 직접 접근하는 명령어 load, store 2개로 제한
- 주소 지정 방식의 종류가 적은 경우가 많다. ➡️ load-store 구조라고 부르기도 함
✔️ 레지스터 적극적으로 활용
➡️ 레지스터 이용 연산이 많고, 일반적인 경우보다 범용 레지스터의 개수가 더 많다
✔️ 사용 가능 명령어 개수가 CISC보다 적어 많은 명령으로 프로그램을 작동시킨다.
'CS > 혼자 공부하는 컴퓨터 구조 + 운영체제' 카테고리의 다른 글
[혼공학습단 13기] 6주차 : 가상 메모리 | 파일 시스템 (0) | 2025.02.20 |
---|---|
[혼공학습단 13기] 5주차 : 프로세스 동기화 | 교착 상태 (0) | 2025.02.13 |
[혼공학습단 13기] 4주차 : 운영체제 시작하기 | 프로세스와 스레드 | CPU 스케쥴링 (0) | 2025.02.07 |
[혼공학습단 13기] 3주차 : 메모리와 캐시 메모리 | 보조기억장치 | 입출력장치 (0) | 2025.01.20 |
[혼공학습단 13기] 1주차 : 컴퓨터 구조 시작하기 | 데이터 | 명령어 (0) | 2025.01.16 |