ultra_dev
cpu의 성능 향상 기법 본문
1. 빠른 CPU를 위한 설계 기법
컴퓨터 부품들은 ‘클럭 신호’에 맞춰서 일사불란하게 움직이고, cpu는 명령어 사이클이라는 정해진 흐름에 맞춰 명령어들을 실행한다.
클럭 속도 : 헤르츠(Hz) 단위로 측정
헤르츠(Hz) : 1초에 클럭이 반복되는 횟수
클럭이 ‘똑-딱-’하고 1초에 한 번 반복되면 1Hz
클럭이 1초에 100번 반복되면 100Hz
ex) max 4.9Ghz, base 2.5Ghz : 1초에 클럭이 기본적으로 25억번, 순간적으로 최대 49억번 반복된다.
그렇다고 필요 이상으로 클럭을 높이면 발열이 심각해진다.
클럭 속도를 늘리는 방법 이외에 다른 방법 들은?
- 코어 수를 늘리는 방법(”듀얼코어” “멀티코어”)
- 스레드 수를 늘리는 방법(”멀티스레드”)
코어란(Core)란?
- 현대적인 관점에서 “CPU”라는 용어를 재해석 해야한다.
- 전통적으로 명령어를 실행하는 부품은 원칙적으로 하나만 존재(싱글 코어 느낌)
- But 오늘날 cpu에는 명령어를 실행하는 부품이 여러 개 존재(멀티 코어 느낌)
- cpu 안에서 명령어를 실행하는 부품을 코어라는 용어로 사용
스레드와 멀티 스레드
- 스레드 : 실행 흐름의 단위
- 스레드는 하드웨어적 스레드와 소프트웨어적 스레드가 있다.
- 하드웨어적 스레드 : 하나의 코어가 동시에 처리하는 명령어 단위
- 만약 pc가 8코어 16스레드라면, 이 pc의 cpu 안에는 명령어를 실행할 수 있는 부품이 8개있고 각각의 코어 부품당 동시 실행 가능한 명령어는 2개이기 때문에 총 16개의 명령어를 동시에 처리할 수 있구나
: 하나의 명령어를 실행하기 위해 꼭 필요한 레지스터들을 묶은 걸 ‘레지스터 세트’라고 한다면
코어 안에 2개의 레지스터 세트가 있으면 하나의 코어로 2개의 명령어를 동시에 처리할 수 있는 것!!
: 하드웨어 스레드는 논리 프로세서라고도 불린다.
왜냐하면 메모리 입장에서는 메모리에 떠있는 여러 프로그램을 실행 시키는
cpu가 몇코어 몇스레드 인 줄 모른다.
메모리는 그냥 여러개의 명령어를 동시에 가져가니까 작업흐름이 몇개 있구나 정도만 알 수 있음
따라서 하드웨어 스레드는 논리적인 cpu 개수 느낌으로 논리 프로세서라고도 부른다!!
소프트웨어적 스레드
- 만약 워드프로세서 만든다 치면 여러 기능들이 동시에 실행돼야하니까 스레드를 3개 만들어서 각각 실행되도록 하는 것
- 사용자로부터 입력받은 내용을 화면에 보여 주는 기능
- 사용자가 입력한 내용이 맞춤법에 맞는지 검사하는 기능
- 사용자가 입력한 내용을 수시로 저장하는 기능
⇒ 1코어 1스레드 cpu도 여러 개의 소프트웨어 스레드를 만들 수 있다.
⇒ 하드웨어적 스레드와 소프트웨어적 스레드는 다르니까
하드웨어적 스레드가 1개여도 소프트웨어적 스레드 여러개 가능. why?
cpu가 번갈아가며 빠르게 실행하기 때문에(컨텍스트 스위칭?) 마치 동시에 실행하는 것처럼 보이게 가능함
2. 명령어 병렬 처리 기법
cpu가 어떻게 시간을 알뜰살뜰이 쓰면서 명령어 빠르게 처리할 수 있는지
명령어 파이프 라인
: 명령어가 처리 되는 과정을 비슷한 시간 간격으로 나누면
- 명령어 인출 : 명령어를 메모리로부터 갖고옴
- 명령어 해석
- 명령어 실행
- 결과 저장 : 필요하다면 결과값을 메모리같은데다 저장
: 같은 단계가 겹치지만 않으면 cpu는 각 단계를 동시에 실행할 수 있다.
: 명령어를 동시에 병렬처리 하는 걸 명령어 파이프라인이라고 함
: 명령어 파이프라인이 없다면 하나의 명령어를 끝까지 다 처리해야 다음 명령어 처리 하고 이런 식으로 됐겠지
파이프라인 위험 : 명령어 파이프라인이 성능 향상에 실패하는 경우(파이프라인이 제대로 동작하지 않는 경우..병렬동작 제대로 동작 안하는 경우..)
- 데이터 위험
: 명령어 간의 의존성 때문에 병렬 처리 못하는 경우
: 이전 명령어를 끝까지 실행해야만 실행 가능한 경우
ex) 명령어 1 : R1에 R2+R3의 값을 저장해라. 명령어 2: R4에 R1+R5의 값을 저장해라
- 제어 위험
: 프로그램 카운터의 갑작스러운 변화(점프, 콜 등의 명령어 등..)
: - 구조적 위험
: 서로 다른 명령어가 같은 CPU 부품(ALU, 레지스터)를 쓰려고 할 때
슈퍼 스칼라
- cpu 내부에 여러 개의 명령어 파이프라인을 포함한 구조
- 오늘날의 멀티스레드 프로세서
- 이론적으로는 파이프라인 개수에 비례해서 처리 속도 증가
- BUT 파이프라인의 위험도 증가로 인해 비례해서 처리 속도가 증가하지는 않는다.
비순차적 명령어 처리
- 합법적인 새치기
- 파이프라인의 중단을 방지하기 위해 명령어를 순차적으로 처리하지 않는 명령어 병렬 처리 기법
- M(100) ← 1
- M(101) ← 2
- M(102) ← M(100) + M(101)
- M(103) ← M(102) + M(101)
- M(104) ← M(100)
이렇게 순차적으로 100번지부터 처리 하면 102가 100,101 기다려야하니 병렬적 처리를 못하게 됨
102처리를 뒤로 미뤄서 병렬적 처리가 가능하게 하는 것
이때 막 바꾸는 건 아님
예를 들어서
1,3 순서는 바꿀 수 없다.(3 수행을 위해 M(100)이 필요)
1,4순서도 바꿀 수 없다(1을 토대로 3 수행, 3을 토대로 4가 수행되니까)
이런 식으로 바꿀 수 없는 경우 많음
여기선 4,5 순서를 바꿀 수 있겠지
즉 전체 프로그램 실행 흐름에는 영향이 없어야 함
명령어 집합 구조, CISC와 RISC
명령어의 세세한 생김새, 연산, 주소 지정 방식 등은 cpu마다 다르다
명령어 집합 (구조) : cpu가 이해할 수 있는 명령어들의 모음
ex) 인텔 cpu 컴퓨터에서 만든 실행 파일을 그대로 아이폰에 옮겨 특별한 설정 없이 바로 실행할 수는 없음
일반적으로 인텔의 cpu는 “x86(x86-64)” 명령어 집합을, 애플의 cpu는 일반적으로 “ARM” 명령어 집합을 따름
x86에서 만든 exe파일을 arm에서 별도 설정 없이 실행 x?
같은 소스코드여도 다른 저급 언어로 변환됨 (명령어 집합이 다르기 때문..)
→ 즉 명령어 집합(구조)는 cpu의 언어인 셈이다.
따라서 명령어가 달라지면 그에 대한 나비효과로
명령어 해석 방식, 레지스터의 종류와 개수, 파이프라이닝의 용이성 등이 달라진다.
명령어 집합 구조 ISA는 cpu의 언어이자 하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속!
명령어 집합의 두 축 : CISC & RISC (시스크 리스크)
CISC(Complex Instruction Set Computer)
- 복잡한 명령어 집합을 활용하는 컴퓨터(CPU)
- x86, x86-64는 CISC 기반 명령어 집합 구조
- 복잡하고 다양한 명령어 활용
- 명령어의 형태와 크기가 다양한 가변 길이 명령어 사용
- 따라서 다양하고 강력한 명령어가 많아서
상대적으로 적은 수의 명령어로도 프로그램 실행 가능
단점
: 명령어 파이프 라이닝이 불리하다
→ 명령어가 워낙 복잡하고 다양한 기능 제공하기 때문에
명령어의 크기와 실행되기까지의 시간이 일정하지 않는다.
그리고 복잡한 명령어 때문에 명령어 하나를 실행하는 데에 여러 클럭 주기가 필요하다
→ 예전 메모리 최대한 아끼며 개발했던 시절에는 인기가 높았으나 지금은…글쎄….
: 대다수 복잡한 명령어는 사용 빈도가 낮음.. 어차피 자주 쓰는 명령어만 계속 쓰게 되니까
RISC(Reduced Instruction Set Computer)
- 명령어 종류가 적고, 짧고 규격화된 명령어 사용
- 단순하고 적은 수의 고정 길이 명령어
→ 위 2가지 이유로 명령어 파이프 라이닝에 유리
- CISC가 다양한 주소지정 방식 지원하는 반면에
RISC는 메모리 접근 방식을 최소화(접근하는 건 load, 저장은 store로 제한) 하고 대신에 레지스터를 십분 활용한다
→ 따라서 RISC는 CISC보다 범용레지스터의 종류가 더 많다
- 다만 명령어 종류가 CISC보다 적기에 더 많은 명령어로 프로그램을 실행하게 된다.
⇒ 현시대에서는 CISC도 문제점 인식하고 명령어 잘게 쪼개서 마이크로 명령어라고해서
명령어 실행을 1클럭 내외로 잘게 쪼개서 수행하기 때문에 내부적으론 RISC처럼 동작하긴 함
'혼자 공부하는 컴퓨터구조+운영체제' 카테고리의 다른 글
보조기억장치 (0) | 2023.09.11 |
---|---|
메모리와 캐시 메모리 (0) | 2023.09.10 |
CPU의 작동 원리 (1) | 2023.09.05 |
명령어 (0) | 2023.08.28 |
데이터, 0과 1 (0) | 2023.08.26 |