목차
- 클럭
- 코어 & 멀티 코어
- 스레드 & 멀티 스레드
- 명령어 병렬 처리 기법
- 명령어 집합
CPU의 속도를 빠르게 만들어보자
- 컴퓨터 부품들은 '클럭 신호' 에 맞춰 일사불란하게 움직인다.
- CPU는 '명령어 사이클' 이라는 정해진 흐름에 맞춰 명령어들을 실행한다.
클럭 속도
- 클럭속도: 헤르츠(Hz) 단위로 측정
- 헤르츠(Hz): 1초에 클럭이 반복되는 횟수
- 클럭이 1초에 한 번 반복되면 1Hz
- 클럭이 1초에 100번 반복되면 100Hz
Q. 그럼 클럭 신호가 빠르게 반복되면 CPU를 비롯한 컴퓨터 부품들은 그만큼 빠른 박자에 맞춰 움직일까요?
A. 꼭 그런건 아니지만 일반적으로는 그렇다.
Q. 그럼 클럭 신호를 마냥 높이면 CPU가 무지막지하게 빨리지나요?
A. 꼭 그렇진 않다! 필요 이상으로 클럭을 높이면 발열이 심각해짐
코어와 멀티 코어
클럭 속도를 늘리는 방법 이외에는 다른 방법이 없을 까요?
- 코어 수를 늘리는 방법("듀얼 코어, "멀티 코어", ...)
- 스레드 수를 늘리는 방법("멀티 스레드", ..)
코어(Core)란?
- 현대적인 관점에서 "CPU" 라는 용어를 재해석 해야함
- "명령어를 실행하는 부품" ?
- 정통적으로 "명령어를 실행하는 부품" 은 원칙적으로 하나만 존재
- 하지만 오늘날 CPU에는 "명령어를 실행하는 부품" 이 여러개 존재
- '명령어를 실행하는 부품' 을 코어라는 용어로 사용
멀티코어 프로세서란 여러 개의 코어를 가지고 있는 CPU를 말한다.
Q. 코어를 두 개, 세 개, 100개를 늘리면 연산 속도도 그에 비례하여 빨라지나요?
A. 코어 수에 비례하여 증가하지는 않는다.
스레드와 멀티 스레드
스레드란 '실행 흐름의 단위'
스레드의 종류
- 하드웨어적 스레드
- 소프트웨어적 스레드
하드웨어 스레드: 논리 프로세서 라고도 부른다.
- 하나의 코어가 동시에 처리하는 명령어 단위
- 예) 1코어 1스레드 CPU
- 멀티 스레드 프로세서, 멀티 스레드 CPU
- 예) 2코어 4스레드 CPU
멀티스레드 프로세서를 실제로 설계하는 일은 매우 복잡하지만, 가장 큰 핵심은 레지스터
소프트웨어 스레드: 하나의 프로그램에서 독립적으로 실행되는 단위
멀티스레드: 하나의 프로그램에서 두개 이상의 영역이 실행되는 것
1코어 1스레드 CPU(하드웨어적 스레드)도 여러 소프트웨어적 스레드를 만들 수 있다.
명령어 병렬 처리 기법
멀티 코어 멀티 스레드 CPU를 빠르게 처리할 수록 설계하는 것도 중요하지만
메모리에 있는 명령어들을 어떻게 처리하는가도 중요하다.
명령어 파이프 라인
하나의 명령어가 처리되는 과정을 비슷한 시간 간격으로 나눈다면?
- 명령어 인출(Instruction Fetch)
- 명령어 해석(Instruction Decode)
- 명령어 실행(Execute Instruction)
- 결과 저장(Write Back)
위 같은 단계가 겹치지 않는다면 각각의 CPU는 '각 단계를 동시에 실행할 수 있다'
명령어 파이프라이닝은 동시에 여러 개의 명령어를 겹쳐 실행하는 기법이다.
명령어 파이프라인을 사용하지 않았다면?
파이프라인 위험: 명령어 파이프라인이 성능 향상에 실패하는 경우
- 데이터 위험
- 제어 위험
- 구조적 위험
1. 데이터 위험: 명령어 간의 의존성에 의해 야기
- 모든 명령어를 동시에 처리할 수는 없다.
- 이전 명령어를 끝까지 실행해야만 비로소 실행할 수 있는 경우
예시
- 명령어 1: R1 <= R2 + R3 // R2 레지스터 값과 R3 레지스터 값을 더한 값을 R1 레지스터에 저장
- 명령어 2: R4 <= R1 + R5 // R1 레스스터 값과 R5 레지스터 값을 더한 값을 R4 레지스터에 저장
- 명령어 1이 해석하고 있는 와중 명령어 2를 인출할 수 없다.
2. 제어위험: 프로그램 카운터의 갑작스러운 변화
대응 방안으로 분기 예측(branch prediction) 이라는 방법도 있다.
3. 구조 위험: 서로 다른 명령어가 같은 CPU 부품(ALU, 레지스터)를 쓰려고 할 때
슈퍼스칼라
- 여러 개의 명령어 파이프라인을 두는 기법(오늘날의 멀티스레드 프로세서)
- 이론적으로는 파이프라인 개수에 비례하여 처리 속도 증가
- 하지만 파이프라인 위험도의 증가로 인해 파이프라인 개수에 비례하여 처리 속도가 증가하지 않음
비순차적 명령어 처리
- 비순차적 명령어 처리 기법은 파이프라인의 중단을 방지하기 위해
- 명령어를 순차적으로 처리하지 않는 명령어 병렬 처리 기법
- 예시) 합법적인 새치기
- 지금까지 설명한 방식들은 모두 순차적으로 명령어를 처리하는 방식
의존성이 없는 명령어의 순서를 마지막으로 바꿔본다면?
- 파이프라이닝의 중단을 방지할 수 있다.
- 당연히 아무 명령어가 순서를 바꿀 수는 없다.
- 순서를 바꿔도 전체 흐름에 영향이 없는 선에서 가능
그렇다면 명령어가 어떻게 생겨야 명령어 파이프라이닝에 유리할까요?
명령어 집합
"CPU는 명령어를 실행한다"
Q. 근데 정말 이 세상의 모든 CPU가 똑같이 생긴 명령어를 실행할까?
A. 명령어의 세세한 생김새, 연산, 주소 지정 방식 등은 CPU 마다 다르다.
예시
인텔 CPU 컴퓨터에서 만든 실행 파일을 그대로 아이폰에 옮겨 특별한 설정 없이
바로 실행한다면 당연히 실행이 되지 않을 것이다.
- 인텔의 CPU는 일반적으로 "X86(X86-64)" 명령어 집합을
- 애플의 CPU는 일반적으로 "ARM" 명령어 집합을 따른다.
명령어 집합 (구조): CPU가 이해할 수 있는 명령어들의 모음
- CPU 의 언어인 셈
- 명령어가 달라지면 그에 대한 나비효과로 많은 것들이 달라진다.
- 명령어 해석 방식, 레지스터의 종류와 개수, 파이프라이닝의 용이성 등등
ISA
CPU의 언어이자 하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속
명령어 집합의 두 축
CISC(Complex Instruction Set Computer)
- 복잡한 명령어 집합을 활용하는 컴퓨터(CPU)
- x86, x86-64는 CISC 기반 명령어 집합 구조
- 복잡하고 다양한 명령어 활용
- 명령어의 형태와 크기가 다양한 가변 길이 명령어를 활용
- 다양하고 강력한 명령어를 활용
- 상대적으로 적은 수의 명령어로도 프로그램을 실행할 수 있다.
메모리를 최대한 아끼며 개발해야 했던 시절에 인기가 높았으나
명령어 파이프라이닝이 불리하다는 치명적인 단점
명령어가 워낙 복잡하고 다양한 기능을 제공하는 탓에
명령어의 크기와 실행되기까지의 시간이 일정하지 않음
복잡한 명령어 때문에
명령어 하나를 실행하는 데에 여러 클럭 주기 필요
게다가, 대다수의 복잡한 명령어는 사용 빈도가 낮다.(자주 쓰는 명령어만 쓰게 됨)
RISC (Reduced Instruction Set Computer)
명령어의 종류가 적고, 짧고 규격화된 명령어 사용
단순하고 적은 수의 고정 길이 명령어 집합을 활용
짧고 규격화된 명령어를 활용하기 때문에 파이프라이닝에 유리함
메모리 접근 최소화(load, store), 레지스터 십분 활용
다만 명령어 종류 자체가 CISC보다 적기에 더 많은 명령어로 프로그램을 동작시킨다.
정리
참고
CISC가 실제로 실행될 때는 CPU 내부적으로 잘게 쪼개서 실행하는 경우가 많다.
내부적으로는 RISC 처럼 사용하고 있다.
해당 포스팅에 나온 글과 이미지들은 강민철 저자님의 혼자 공부하는 컴퓨터 구조 + 운영체제의 책과 강의를 참고하여 만들어졌습니다.
책에서 보다 깊게 나오는 내용이 있으므로 한번 구매하고 보셔도 좋을 것 같습니다.
'CS' 카테고리의 다른 글
[CS] 보조 기억 장치 (0) | 2024.05.23 |
---|---|
[CS] 메모리, 캐시 메모리 (0) | 2024.05.23 |
[CS] CPU의 작동 원리 (0) | 2024.05.22 |
[CS] 명령어 (0) | 2024.05.22 |
[CS] 정보 단위, 인코딩 (1) | 2024.05.22 |