핵심 키워드: 클럭
, 코어
, 멀티코어
, 스레드
, 멀티스레드
컴퓨터 부품들은 클럭 신호에 맞춰 일사불란하게 움직인다.
CPU는 명령어 사이클이라는 정해진 흐름에 맞춰 명령어들을 실행한다.
클럭 속도만으로 CPU의 성능을 올리는 것에는 한계가 있습니다.
CPU 내에 명령어를 처리하는 일꾼이 여러 명 있는 것과 같습니다.
하지만, 처리할 연산이 적절히 분배되지 않는다면 코어 수에 비례하여 연산 속도가 증가하지 않습니다.
하드웨어적 스레드
하나의 코어가 동시에 처리하는 명령어 단위, 예를 들어 8코어 16스레드이면 명령어를 실행하는 부품을 여덟 개 포함하고, 한 번에 열여섯 개의 명령어를 처리할 수 있는 CPU를 의미합니다.
소프트웨어적 스레드
하나의 프로그램에서 독립적으로 실행하는 단위
멀티스레드 프로세서
가장 큰 핵심은 레지스터로 하나의 명령어를 처리하기 위해 꼭 필요한 레지스터를 여러 개 가지고 있으면 됩니다.
프로그램 입장에서 봤을 때 한 번에 하나의 명령어를 처리하는 CPU가 여러 개 있는 것처럼 보이기에 하드웨어 스레드를 논리 프로세서라고 부르기도 합니다.
코어와 스레드, 멀티 코어와 멀티 스레드의 개념 정리
멀티 코어 - CPU 내에 명령어를 처리하는 일꾼이 여러 명 있다.
큰 밭에 일꾼이 하나 있었는데, 두명이 되었다.
엄청 빨리 끝낼 수 있겠네?
멀티 스레드 - 하나의 코어가 동시에 처리하는 명령어 단위를 여러 개 수행할 수 있다.
일꾼이 모두 양손잡이가 되었다. 네??
호미를 양손에 하나씩 쥐고 좌우 밭두렁을 미친듯이 갈고 있다.
논리 프로세서 - 밭 주인의 입장에서 네명이 한 번에 밭을 갈고 있는 것 같이 보인다.
핵심 키워드: 명령어 파이프라이닝
, 슈퍼스칼라
, 비순차적 명령어 처리 기법
하나의 명령어가 처리되는 전체 과정을 클럭 단위로 나누어 보면, 크게 아래와 같은 과정으로 분해할 수 있는데, 중요한 점은 같은 단계가 겹치지만 않는다면 CPU는 각 단계를 동시에 실행할 수 있습니다.
마치 공장 생산 라인과 같이 명령어들을 명령어 파이프라인에 넣고 동시에 처리하는 기법을 명령어 파이프라이닝이라고 합니다.
하지만, 특정 상황에서 성능 향상에 실패하는 경우도 있는데, 이러한 상황을 파이프라인 위험이라고 부릅니다.
데이터 위험
data hazard는 명령어 간 ‘데이터 의존성’에 의해 발생합니다. 어떤 명령어는 이전 명령어를 끝까지 실행해야만 비로소 실행할 수 있는 경우가 있습니다.
제어 위험
control hazard는 주로 분기 등으로 인한 ‘프로그램 카운터의 갑작스러운 변화’에 의해 발생합니다.
참고 이를 해결하기 위해 사용하는 기술 중 하나가 분기 예측입니다.
구조적 위험
structural hazard는 서로 다른 명령어가 동시에 같은 CPU 부품을 사용하려고 할 때 발생합니다. 다른 말로 자원 위험이라고도 부릅니다.
오늘날의 CPU에서는 여러 개의 파이프라인을 이용하는데, 이러한 구조를 슈퍼 스칼라라고 합니다.
하지만, 파이프라인 위험 등의 예상치 못한 문제가 있어 반드시 파이프라인 개수에 비례하여 빨라지지 않습니다.
파이프라인의 중단을 방지하기 위해 명령어를 순차적으로 처리하지 않고, 의존성이 없어 순서를 바꿔도 전체 프로그램의 실행 흐름에 영향이 없는 명령어를 먼저 실행할 수 있습니다.
핵심 키워드: ISA
, CISC
, RISC
CPU가 이해할 수 있는 명령어들의 모음을 명령어 집합 또는 명령어 집합 구조 (instruction set architecture: ISA)라고 합니다.
ISA가 다르다는 것은 CPU가 이해할 수 있는 명령어가 다르다는 뜻이고, 명령어가 달라지면 어셈블리어도 달라집니다.
장점: CISC 명령어 집합은 복잡하고 다양한 기능을 제공하기 때문에 적은 수의 명령으로 프로그램을 동작시키고 메모리를 절약할 수 있습니다.
단점: 반면에, 명령어의 크기 (가변 길이 명령어)와 실행에 필요한 클럭 주기가 각양각색이라 파이프라이닝이 어렵습니다. 그리고 대다수의 복잡한 명령어는 사용 빈도가 낮습니다.
CISC의 단점을 극복하고자, 명령어의 길이와 수행 시간이 짧고 규격화된 (고정 길이 명령어) 명령어 세트를 구성하고, 자주 쓰이는 기본적인 명령어를 작고 빠르게 만들자!
이렇게 구성하다 보니 레지스터를 이용하는 연산이 많고, 범용 레지스터 개수가 더 많아졌다.