Chapter 05 CPU 성능 향상 기법 - goorm-6th-Als/for_study_Algorithm GitHub Wiki
- 컴퓨터 부품들은 '클럭(Clock) 신호(Hz단위)'에 맞춰 움직임.
ex) 클럭의 "똑딱똑딱" 주기에 맞춰 레지스터에서 다른 레지스터로 데이터가 이동하거나, ALU에서 연산이 수행되거나, CPU가 명령어를 읽음.
- CPU는 '명령어 사이클' 흐름에 맞춰 명령어를 실행.
- Hz : 1초에 클럭이 반복되는 횟수
ex) 클럭이 1초에 100번 반복 => 100Hz
ex) 4.9GHz => 클럭이 1초에 49억번 반복
-
클럭을 필요 이상으로 높이면 발열이 심해짐
-
클럭 속도 이외에 성능향상은 코어수를 늘리거나 스레드 수를 늘림
- 명령어를 (해석, 인출, 실행)하는 하드웨어 부품
- 코어가 하나면 싱글코어, 여러개면 멀티코어 CPU 또는 멀티코어 프로세서 라고 함.
- 연산속도는 코어수에 꼭 비례하지는 않음.
- 명령어 실행 흐름의 단위
- CPU에서 사용하는 개념 : 하드웨어적 스레드
- 프로그램에서 사용하는 개념 : 소프트웨어적 스레드
- 하나의 코어가 동시에 처리하는 명령어 단위
- 논리 프로세서라고도 부름
- 하나의 코어가 여러개의 명령어를 동시에 처리할 수 있는 CPU를 멀티 스레드 (프로세스, CPU)라고 함
ex)하나의 코어가 동시에 하나의 명령어 처리 = 1코어 1스레드 CPU
- 하나의 코어로 여러 명령어를 동시 처리
- 멀티 스레드 프로세서의 핵심 : 레지스터
- 하나의 프로그램에서 독립적으로 실행되는 단위
- 프로그램 언어나 운영체제에서의 스레드
ex) 워드 프로그램에서 사용자로부터 입력받은 내용을 화면에 보여줌 + 내용이 맞춤법에 맞는지 검사 + 수시로 저장 -> 이 기능들을 각각의 스레드로 만들면 동시에 실행 가능.
+) 1코어 1스레드 CPU(하드웨어적 스레드)도 소프트웨어적 스레드를 멀티 스레드로 만들 수 있음
- 코어 : 명령어를 실행할 수 있는 '하드웨어 부품'
- 스레드 : '명령어를 실행하는 단위'
- 멀티코어 프로세서 : 하나의 CPU에 (명령어를 실행할 수 있는)코어가 두개 이상 있는 CPU
- 멀티스레드 프로세서 : 하나의 코어에서 명령어를 동시에 여러개 실행할 수 있는 CPU
명령어 병렬 처리 기법은 CPU가 명령어를 동시에 처리하는 방법을 의미한다
명령어 병렬 처리 기법은 명령어 파이프 라이닝, 슈퍼스칼라, 비순차적 명령어 처리 등이 있다.
- 명령어 인출(Instruction Fetch): 명령어 주소를 계산하고 그 주소에 가서 명령어를 가져옴
- 명령어 해석(Instruction Decode): 어떻게 수행, 행위, 동작시킬지 결정
- 명령어 실행(Execute Instruction): 연산을 수행
- 결과 저장(Write Back): 연산 결과를 어디에 저장할 것인지에 대한 동작을 수행
전공책에 따라 처리되는 과정이 다를 수 있습니다.
각 단계가 겹치지만 않으면 CPU는 각 단계를 통시에 실행 할 수 있다
이러한 모습이 공장 생산 라인과 같이 명령어들을 명령어 파이프라인에 넣고 동시에 처리하는 기법을 명령어 파이프라이닝 이라고 한다.
파이프라이닝에서 성능 향상에 실패하는 경우를 파이프라인 위험이라고 한다.
파이프라인 위험에는 데이터 위험, 제어 위험, 구조적 위험 세 가지가 있다.
-
데이터 위험은 명령어 강 데이터 의존성에 의해 발생한다.
-
제어 위험은 주로 분기 등으로 인해 프로그램 카운터의 갑작스러운 변화에 의해 발생한다.
-
구조적 위험은 명령어들의 서로 같은 메모리에 접근하때 발생한다. 자원 위험이라고도 불린다.
CPU 내부에 여러 개의 명령어 파이프라인을 포함한 구조를 슈퍼스칼라라고 한다.
파이프라인이 늘어났다고 해서 CPU의 처리 속도가 빨라지지는 않는다.
파이프라인이 증가하는 만큼 위험도 증가하기 때문이다.
파이프 라인의 한 단계를 세분화 하여 한 클록 당 여러 명령어를 수 할수 있습니다.
비순차적 명령어 처리는 명령어의 순서가 순처적으로 이루어지지 않는 처리 방법을 뜻합니다.
m(1) <- 100
m(2) <- 300
m(3) <- m(1)+m(2)
m(4) <- 100
m(5) <- 200
m(1) <- 100
m(2) <- 300
m(4) <- 100
m(5) <- 200
m(3) <- m(1)+m(2)
위와 같이 명령어가 이동을 하면 m1과 m2의 명령어가 다 처리하는 동안 기다리지 않고, 다른 명령어를 실행시킬 수 있다.
CPU는 어떤 명령어가 데이터 의존성을 가지는 지 판단을 할수 있을 경우, 사용이 가능한 처리 방식이다.
- Ardor IT's Devlog](https://ardor-dev.tistory.com/29#google_vignette)`
펼쳐보기
- 명령어 집합 이란 CPU가 이해할 수 있는 명령어들의 모음이다.
CPU 회사 마다 연산, 주소 지정 방식이 조금씩 차이가 있다.
-
CPU가 이해할 수 있는 명령어들의 모음을 명령어 집합(instruction set) 또는 명령어 집합 구조(ISA = Instruction Set Architecture)라고 한다.
-
인텔 CPU에서 만든 파일은 애플의 CPU에서 사용할 수 없다.
이해할 수 있는 명령어가 다르기 때문에 서로를 이해할 수 없기 때문이다.
동일한 소스 코드를 작성하고 ISA가 다른 컴퓨터에서 어셈블리어로 컴파일하면 아래와 같은 결과를 얻을 수 있다
- 복잡한 명령어 집합을 활용하는 컴퓨터(CPU)이다
- x86, x86-64는 CISC 기반 명령어 집합 구조 이다
- CISC는 다양하고 강력한 기능의 명령어 집합을 활용하기 때문에 명령어의 형태와 크기가 다양한 가변 길이 명령어를 활용한다
다양하고 강력한 명령어를 활용한다는 말은 상대적으로 적은 수의 명령어로도 프로그램을 실행할 수 있어서 메모리를 최대한 아끼며 개발해야 했던 시절에 인기가 높았다.
하지만 단점으로는 활용하는 명령어가 워낙 복잡하고 다양한 기능을 제공 하기 때문에 명령어의 크기와 실행되기까지의 시간이 일정하지 않다, 또한 복잡한 명령어 때문에 명어 하나를 실행하는 데에 여러 클럭 주기를 필요로 한다.
또한 복잡한 명령어의 사용 빈도는 사용 빈도가 낮고 20%정도의 명령어가 전체 명령어의 80%정도를 차지한다.
때문에 CISC 기반 CPU는 성장에 한계가 있다.
CISC에서 사람들은 이렇게 느꼈습니다
- 빠른 처리를 위해 명령어 파이프라인을 십분 활용해야 한다.
- 원할한 파이프라이닝을 위해 명령어 길이와 수행 시간이 짧고 규격화되어 있어야 한다.
- 어차피 자주 쓰이는 명령어만 사용되기에 자주 쓰이는 기본적인 명령어를 작고 빠르게 만드는 것이 중요하다
- 이러한 원칙에 등잘한 것이 RISC이다.
CISC 보다 명령어 종류가 적고 명령어가 짧고 규격화 되어 있으며, 되도록 1클럭 내외로 실행되는 명령어를 지양한다. 즉 RISC는 고정 길이 명령어를 활용한다.
- RISC는 메모리에 직접 접근하는 명령어를 load, store 두 개로 제한할 만큼 메모리 접근을 단순화하고 최소화를 추구한다.
때문에 RISC를 load-store 구조라고 부르기도 한다
- RISC는 메모리 접글을 단순화, 최소화하는 대신 레지스터를 적극 활용한다. 그렇게에 CISC보다 레지스터를 이용하는 연산이 많고, 일반적인 경우보다 범용 레지스터 개수도 더 만다. 다만 사용 가능한 명령어 개수가 CISC보다 적기 때문에 RISC는 CISC보다 많은 명령으로 프로그램을 작동시킨다.
추가로 레지스터를 주로 사용하는 연산 방식은 메모리 접근을 줄여 성능을 향상시킬 수 있다. 하지만, 이는 프로그램이 더 많은 명령어를 필요로 할 수 있으며, 때로는 프로그램의 크기가 커질 수 있다.
- ISA는 CPU언어이자 하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속
- CISC는 복잡하고 다양한 종류의 가변 길이 명령어 집합을 활용
- RISC는 단순하고 적은 종류의 고정 길이 명령어 집합을 활용