빠른 CPU를 위한 설계 기법
클럭
앞에서 컴퓨터 부품들은 클럭 신호에 맞춰 움지깅고 CPU는 명령어 사이클이라는 흐름에 맞춰 명령어를 실행한다는 것을 알아보았다. 클럭이 높아지면 컴퓨터 부품들은 그만큼 빠르게 움직이고 명령어 사이클을 더 빠르게 반복해 다른 부품들도 더욱 빠르게 작동할 것으로 예상된다.
실제로 클럭 소도가 높은 CPU는 일반적으로 성능이 좋아 클럭 속도는 CPU 속도 단위로 간주된다. 클럭 속도는 헤르츠(Hz)단위로 측정한다.
그렇다고 무작정 클럭 속도를 높인다고 무조건 CPU가 빨라지지 않는다. 무작정 높이면 빨라지지만 발열 문제가 더 커지는 등 클럭 속도만으로는 한계가 있다.
* 클럭은 기본 클럭 속도 최대 클럭 속도로 나누어져있는데 일정한 클럭 속도를 유지하기 보다는 고성능을 요하는 순간에 순간적으로 클럭 속도를 높이거나 그렇지 않을 때는 낮추기도한다. 최대 클럭 속도를 강제로 올릴 수 있는데 이를 오버클럭킹이라 한다.
코어와 멀티 코어
클럭 속도를 높이는 방법 외에 CPU의 코어와 스레드 수를 늘리는 방법이 있다. 앞서 CPU를 명령어를 실행하는 부품이라 소개했다. 오늘날에 보면 CPU 내부에 명령어를 실행하는 부품을 얼마든지 만들 수 있게 되었다. 명령어를 실행하는 부품은 오늘날 코어라 불리게 되고 CPU 내부에는 다수의 코어가있는 멀티코어 CPU 또는 멀티코어 프로세스라 부른다.
잠깐 다른 얘기를 하자면 이 부분을 공부하니 예전에 인터넷에서 본 글 중에서 이를 포켓몬이나 스타크래프트에 비유하는 글이 떠올랐다ㅋㅋㅋ 포켓몬으로는 근육몬과 괴력몬을 예로 했고 스타로 보면 코어는 멀티 갯수고 스레드가 일꾼의 유닛 수로 비유 하는 것을 어릴 때 봤었다(당시에는 뭔지 잘 이해 못 했던거같다ㅋㅋㅋ)
CPU의 연산 속도가 코어 수에 비례하여 증가하지는 않는다. 코어가 두 개, 세 개 있다고 더 빨라지지 않는 것이다. 저자는 이를 조별 과제에 비유했는데 딱 들어맞는 것 같다ㅋㅋ 코어마다 연산이 적절히 분배되지 않는다면 코어 수에 비례하여 연산 속도가 증가하지 않는다. 처리하고자 하는 작업량보다 코어 수가 지나치게 많아도 성능에 크게 영향이 없다. 중요한 것은 얼마나 적절하게 분배하냐이다.
스레드와 멀티스레드
스레드의 사전적 의미는 실행 흐름의 단위이다. 하지만 알아야할게 CPU에서 사용되는 스레드와 프로그래밍에서 사용되는 스레드는 용례가 다르다는 것을 알아야한다.
CPU에서 사용되는 하드웨어적 스레드가 있고 프로그램에 사용되는 소프트웨어적 스레드가 있다.
- 하드웨어적 스레드
스레드를 하드웨어적으로 정의하면 하나의 코어가 동시에 처리하는 명령어 단위를 의미한다. 지금까지 CPU는 1코어 1스레드로 가정하고 공부했다. 여러 스레드를 지원하는 CPU는 하나의 코어로 여러개의 명령어를 동시에 실행할 수 있다. 이를 멀티스레드 프로세서 또는 멀티스레드 CPU라한다. (인텔에서는 하이퍼스레딩이라는 용어를 사용한다.)
예를 들면 8코어 16스레드는 명령어를 실행하는 부품이 여덟 개 있고 열여섯 개의 명령어를 처리할 수 있다는 것이다. 코어 하나당 두개의 하드웨어 스레드를 처리한다는 뜻이다.
8코어 8스레드 = 근육몬 8마리, 8코어 16스레드 = 괴력몬 8마리(팔이 2배로 늘어 작업량 2배로 증가)
- 소프트웨어적 스레드
소프트웨어적으로 정의된 스레드는 하나의 프로그램에서 독립적으로 실행되는 단위이다. 프로그래밍 언어나 운영체제에서 다루는 스레드가 보통 여기에 해당된다.
하나의 프로그램은 실행되는 과정에서 한 부분만 실행될 수도 있지만, 프로그램의 여러 부분이 동시에 실행될 수도 있다. 아래의 기능이 동시에 수행되길 원하는 프로그램을 개발한다 해보자.
- 사용자로부터 입력 받은 내용을 화면에 보여주는 기능
- 사용자가 입력한 내용이 맞춤법에 맞는지 검사하는 기능
- 사용자가 입력한 내용을 수시로 저장하는 기능
위 코드를 각각의 스레드로 만들면 동시에 실행 가능하다.
* 1코어 1스레드 CPU도 소프트웨어적 스레드를 수십 개 실행할 수 있다.
- 멀티스레드 프로세서
멀티스레드 프로세서의 가장 큰 핵심은 레지스터이다. 하나의 명령어를 처리하기 위해 꼭 필요한 레지스터를 여러개 가지는 것이다. 이런 레지스터들을 레지스터 세트라하겠다. 레지스터 세트가 한 개인 CPU는 한 개의 명령어를 처리하기 위한 정보들을 기억할 뿐이지만, 세트가 두 개인 CPU는 두 개의 명령어를 처리하기 위한 정보들을 기억한다. 하나의 코어에서 두 개의 명령어가 동시에 실행되는 것이다.
하지만 이를 메모리 속 프로그램 입장에서 봤을 때 각각의 하드웨어 스레드는 하나의 명령어를 처리하는 CPU와 같다. 예로 2코어 4스레드는 프로그램 입장에서 CPU 네 개가 있는 것 처럼 보인다. 그렇기에 하드웨어 스레드를 논리 프로세서라 부르기도 한다.
명령어 병렬 처리 기법
위와 같은 방법도 중요하지만 CPU가 놀지 않으며 작동하게 하는 것도 중요하다. 이러한 방법인 명령어 병렬 처리 기법을 알아보자. 대표적인 명령어 병렬 처리 기법에는 명령어 파이프 라이닝, 슈퍼스칼라, 비순차적 명령어 처리가 있다.
명령어 파이프라인
이를 이해하려면 하나의 명령어가 처리되는 과정을 비슷한 시간 간격으로 나누어 봐야 한다.
- 명령어 인출
- 명령어 해석
- 명령어 실행
- 결과 저장
여기서 중요한 점은 단계가 겹치지 않는다면 CPU는 각 단계를 동시에 실행할 수 있다는 것이다. 예를 들어 인출하는 동안 실행이나 해석 저장을 동시에 진행 할 수 있는 것이다.
마치 공장 생산 라인과 같이 명령어들을 명령어 파이프라인에 넣고 동시에 처리하는 기법을 명령어 파이프라이닝이라고 한다.
파이프라이닝이 높은 성능을 가져오기도 하지만 실패하는 경우도 있는데 이러한 상황을 파이프라인 위험이라 한다. 여기에는 크게 데이터 위험, 제어 위험, 구조적 위험이 있다.
- 데이터 위험
데이터 위험은 명령어 간 데이터 의존성에 의해 발생한다. 모든 명령어를 동시에 처리할 수는 없는데 어떤 명령어는 이전 명령어를 끝까지 실행해야만 실행할 수 있는 경우가 있다. 이처럼 데이터 의존적인 두 명령어를 동시에 실행하려하면 제대로 작동하지 않는 것을 데이터 위험이라 한다.
- 제어 위험
제어 위험은 주로 분기등으로 인한 프로그램 카운터의 갑작스러운 변화에 의해 발생한다. 기본적으로 프로그램 카운터는 현재 실행 중인 명령어의 다음 주소로 갱신되는데 실행 흐름이 바뀌어 명령어가 실행되면서 프로그램 카운터 값에 갑작스러운 변화가 생기면 명령어 파이프라인에 미리 가지고 와서 처리 중이었던 명령어들이 쓸모 없어진다. 이를 제어 위험이라 한다. 참고로 이를 위해 분기 예측이라는 기술이 있는데 프로그램이 어디로 분기할지 미리 예측한 후 그 주소를 인출하는 기술이다.
- 구조적 위험
구조적 위험은 명령어들을 겹쳐 실행하는 과정에서 서로 다른 명령어가 동시에 ALU, 레지스터 등의 부품을 사용하려 할 때 발생한다. 구조적 위험은 자원 위험이라 부르기도 한다.
슈퍼스칼라
오늘날 대부분의 CPU에는 여러개의 파이프 라인을 사용한다. 이처럼 여러 개의 명령어 파이프라인을 포함한 구조를 슈퍼스칼라라고 한다.
이런한 구조로 명령어 처리 가능한 CPU를 슈퍼스칼라 프로세서 또는 슈퍼스칼라 CPU라 한다. 멀티 스레드 프로세서는 한 번에 여러 명령어를 인출하고, 해석하고, 실행할 수 있기에 슈퍼스칼라 구조를 사용 가능하다.
이론적으로 파이프라인 개수에 비례하여 처리 속도가 빨라지는데 파이프라인 위험 등의 문제가 있어 실제로는 반드시 개수에 비례하여 빨라지지 않는다. 특히 여러 개의 파이프라인을 사용하기에 파이프라인 위험을 피하기 더욱 까다로워 고도로 설계되어야 한다.
비순차적 명령어 처리
비순차적 명령어 처리(줄여서 OoOE)는 오늘날 CPU 성능 향상에 크게 기여한 기법이자 대부분의 CPU가 차용하는 기법이다. 이름에서 알 수 있듯 명령어들을 순차적으로 실행하지 않는 기법인데 명령어들이 어떤 명령어와 데이터 의존성을 가지고있는지, 순서를 바꿔 실행할 수 있는 명령어에는 어떤 것들이 있는지 판단 후 순서를 바꾸어 실행하게 된다.
CISC와 RISC
명령어 집합
CPU가 이해할 수 있는 명령어들의 모음을 명령어 집합 또는 명령어 집합 구조(ISA: Instruction Set Architecture)라고 한다. CPU마다 ISA가 다를 수 있는데 ISA가 다르면 어셈블리어도 달라진다.
즉, ISA는 일종의 CPU의 언어인 셈이다.
ISA가 다르면 그에 따라 많은 것이 달라진다. 제어장치가 명령어를 해석하는 방식, 사용되는 레지스터의 종류와 개수, 메모리 관리 방법 등이 달라진다. 그리고 이는 CPU 하드웨어 설계에 큰 영향을 미친다.
CISC
CISC는 Complex Instruction Set Computer의 약자다. 해석하면 복잡한 명령어 집합을 활용하는 컴퓨터를 의미한다. CISC는 다양하고 강력한 기능의 명령어 집합을 활용하기 때문에 명령어의 형태와 크기가 다양한 가변 길이 명령어를 활용한다. 그리고 이런한 말은 상대적으로 적은 수의 명령어로 프로그램을 실행할 수 있다는 것을 의미한다.
메모리 공간을 절약할 수 있다는 장점에 이전 시기에는 인기가 높았으나 CISC에는 큰 단점이 있다. 워낙 복잡하고 다양한 기능을 제공하기에 명령어의 크기와 실행되기까지의 시간이 일정하지 않다. 그리고 복잡한 명령어 때문에 명령어 하나를 실행하는 데에 여러 클럭 주기를 필요로 한다.
명령어 파이프라인 기법을 위한 이상적인 명령어는 각 단계에 소요되는 시간이 가급적 1클럭으로 동일해야 한다. 하지만 CISC는 그렇지 않기에 효울적으로 처리할 수 없다. 한마디로 규격화 되지 않은 명령어가 파이프라이닝을 어렵게 만드는 것이다.
RISC
RISC는 Reduced Instruction Set Computer의 약자다. 이름처럼 RISC는 CISC에 비해 명령어의 종류가 적다. 그리고 CISC와 달리 짧고 규격화된 되도록 1클럭 내외로 실행되는 명령어를 지향한다. 즉, RISC는 고정 길이 명령어를 활용한다. 명령어가 규격화되어 있고, 하나의 명령어가 1클럭 내외로 실행되기 때문에 RISC 명령어 집합은 명령어 파이프라이닝에 최적화되어 있다.
RISC는 메모리 접근을 load, store 두 개로 제한할 만큼 메모리 접근을 단순화하고 최소화를 추가한다. 그렇기에 CISC보다 주소 지정 방식의 종류가 적은 경우가 많다.
RISC는 메모리 접근을 단순화, 최소화하는 대신 레지스터를 적극적으로 활용한다. 그렇기에 CISC보다 레지스터를 이용하는 연산이 많고, 일반적인 경우보다 범용 레지스터 개수도 더 많다. 다만 사용 가능한 명령어 개수가 CISC보다 적기에 RISC는 CISC보다 많은 명령으로 프로그램을 작동한다.
|
CISC
|
RISC
|
|
복잡하고 다양한 명령어
|
단순하고 적은 명령어
|
|
가변 길이 명령어
|
고정 길이 명령어
|
|
다양한 주소 지정 방식
|
적은 주소 지정 방식
|
|
프로그램을 이루는 명령어의 수가 적음
|
프로그램을 이루는 명령어의 수가 많음
|
|
여러 클럭에 걸쳐 명령어 수행
|
1클럭 내외로 명령어 수행
|
|
파이프라이닝하기 어려움
|
파이프라이닝하기 쉬움
|
'CS 공부 > 컴퓨터 구조, 운영체제' 카테고리의 다른 글
| 컴퓨터 구조(7) - 보조기억장치 (0) | 2026.02.06 |
|---|---|
| 컴퓨터 구조(6) - 메모리와 캐시 메모리 (0) | 2026.02.06 |
| 컴퓨터 구조(4) - CPU의 작동원리 (0) | 2026.01.29 |
| 컴퓨터 구조(3) - 명령어 (0) | 2026.01.27 |
| 컴퓨터 구조(2) - 데이터 (0) | 2026.01.26 |