관리 메뉴

클라이언트/ 서버/ 엔지니어 "게임 개발자"를 향한 매일의 공부일지

CPU 성능 향상 기법 3 - CISC와 RISC 본문

알고리즘 및 자료 관리/컴퓨터 구조 & 운영체제

CPU 성능 향상 기법 3 - CISC와 RISC

huenuri 2024. 10. 15. 19:49

조금 전에 아침부터 오후까지 인사교에서 공부했던 단원의 확인 문제 내용을 스캔해서 학습일지에 붙여 넣었다. 이제 저녁식사가 되길 기다리는 동안 5장의 마지막 단원을 학습하려고 한다.

CPU의 언어인 ISA란 무엇인지 이해하고, 현대 CPU의 주요 설계 방식인 CISC와 RISC의 정의와 차이점에 대해 학습해 볼 것이다.

 

 

CPU의 마지막 이야기이다. 명령어 파이프라이닝과 슈퍼스칼라 기법을 실제로 CPU에 적용하려면 명령어가 파이프라이닝에 최적화되어 있어야 한다. 쉽게 말해 CPU가 파이프라이닝과 스칼라 기법을 효과적으로 사용하려면 CPU가 인출하고 해석하고 실행하는 명령어가 파이프라이닝 하기 쉽게 생겨야 한다.

 

'파이프라이닝 하기 쉬운 명령어'란 무엇일까? 명령어가 어떻게 생겨야 파이프라이닝에 유리할까? 이제 CPU의 언어인 ISA와 각기 다른 성격의 ISA를 기반으로 설계된 CISC와 RISC를 학습해 보겠다.


 

 

 

 

명령어 집합

이 세상 모든 CPU들이 똑같이 생긴 명령어를 실행할까? 세상에는 수많은 CPU 제조사들이 있고, CPU마다 규격과 기능, 생김새가 다른데 모든 CPU가 이해하고 실행하는 명령어들이 다 똑같이 생겼을까?

그렇지 않다. CPU가 이해할 수 있는 명령어들의 모음을 명령어 집합 또는 명령어 집합 구조(ISA)라고 한다. 즉, CPU마다 ISA가 다를 수 있다는 것이다.

 

 

 

 

x86과 ARM은 다른 ISA이기 때문에 인텔 CPU를 사용하는 컴퓨터와 아이폰은 서로의 명령어를 이해할 수 없다. 실행 파일은 명령어로 이루어져 있고 서로의 컴퓨터가 이해할 수 있는 명령어가 다르기 때문이다.

ISA가 다르다는 건 CPU가 이해할 수 있는 명령어가 다르다는 뜻이고, 명령어가 달라지면 어셈블리어도 달라진다.

 

 

왼쪽은 x86-64 ISA, 오른쪽은 ARM ISA이다. 똑같은 코드로 만든 프로그램임에도 CPU가 이해하고 실행할 수 있는 명령어가 달라 어셈블리어도 다른 것을 알 수 있다. 이런 점에서 ISA는 일종의 CPU의 언어인 셈이다.

 

 

 

각기 다른 언어를 사용하는 나라들을 보면 사용하는 언어만 다른 게 아니라 언어에 따라 사람들의 가치관과 생활양식도 다른 것을 볼 수 있다. 마치 높임말이 있는 나라에서는 비교적 어른을 공경하는 문화가 자리 잡혀 있고, 높임말이 없는 나라에서는 비교적 평등한 문화가 자리 잡힌 것처럼 말이다.

CPU도 마찬가지다.

 

 

 

명령어 파이프라인, 슈퍼스칼라, 비순차적 명령어 처리를 사용하기에 유리한 명령어 집합이 있고, 그렇지 못한 명령어 집합도 있다. 그렇다면 명령어 병렬 처리 기법을 도입하기 유리한 ISA는 무엇일까? 


 

 

 

CISC

 

 

메모리에 접근하는 주소 지정 방식도 다양해서 아주 특별한 상황에서만 사용되는 독특한 주소 지정 방식들도 있다.

 

 

 

앞의 어셈블리어 코드를 다시 살펴보자. x-86-64 코드 길이가 ARM보다 짧다. 이는 ARM 명령어 여러 개로 수행할 수 있는 일을 x-86-64 명령어 몇 개만으로도 수행할 수 있다는 뜻이다.

프로그램을 실행하는 명령어 수가 적다는 말은 '컴파일된 프로그램의 크기가 작다'는 것을 의미한다. 같은 소스 코드를 컴파일해도 CPU마다 생성되는 실행 파일의 크기가 다를 수 있다는 것이다.

 

 

 

 

 

 

명령어 파이프라인 기법을 위한 이상적인 명령어는 위의 그림처럼 각 단계에 소요되는 시간이 동일(가급적 1 클럭) 해야 한다. 그래야 파이프라인이 마치 공장의 생산라인처럼 착착착 결과를 낼 테니까 말이다.

하지만 CISC가 활용하는 명령어는 명령어 수행 시간이 길고 가지각색이기 때문에 파이프라인이 효율적으로 명령어를 처리할 수 없다. 한마디로 규격화되지 않은 명령어가 파이프라이닝을 어렵게 만든 셈이다.

 

명령어 파이프라인이 제대로 동작하지 않는다는 것은 현대 CPU에서 아주 치명적인 단점이다. 현대 CPU에서 명령어 파이프라인은 높은 성능을 내기 위해 절대 놓쳐서는 안 되는 핵심 기술이기 때문이다.

 

 

1974년 IBM의 연구소의 존 코크는 CISC 명령어 집합 중 불과 20% 정도의 명령어가 사용된 전체 명령어의 80%가량을 차지한다는 것을 증명하기도 했다. CISC 명령어 집합이 다양하고 복잡한 기능을 지원하지만 실제로는 자주 사용되는 명령어만 쓰였다는 것이다.

CISC 명령어 집합은 복잡하고 다양한 기능을 제공하기에 적은 수의 명령으로 프로그램을 동작시키고 메모리를 절약할 수 있지만, 명령어의 규격화가 어려워 파이프라이닝이 어렵다. 그리고 대다수의 복잡한 명령어는 그 사용 빈도가 낮다.


 

 

 

RISC

CISC의 한계가 우리들에게 준 교훈은 다음과 같다.

  1. 빠른 처리를 위해 명령어 파이프라인을 십분 활용해야 한다. 원활한 파이프라이닝을 위해 '명령어 길이와 수행 시간이 짧고 규격화'되어 있어야 한다.
  2. 자주 쓰이는 명령어만 줄곧 사용된다. 복잡한 기능을 지원하는 명령어를 추가하기보다 '자주 쓰이는 기본적인 명령어를 작고 빠르게 만드는 것'이 중요하다.

이러한 원칙 하에 등장한 것이 RISC이다.

 

CICS와 달리 짧고 규격화된 명령어, 되도록 1클럭 내외로 실행되는 명령어를 지향한다. 즉, RISC는 고정 길이 명령어를 활용한다.

 

RISC는 메모리에 직접 접근하는 명령어를 load, store 두 개로 제한할 만큼 메모리 접근을 단순화하고 최소화를 추구한다. 그렇기에 CISC보다 주소 지정 방식의 종류가 적은 경우가 많다. 이런 점에서 RISC를 load-store 구조라고 부르기도 한다.

 

그렇기에 CISC보다 레지스터를 이용하는 연산이 많고, 일반적인 경우보다 범용 레지스터 개수도 더 많다.

 

 

 

조금 전에 예시로 든 어셈블리 코드를 다시 살펴보자. ARM은 RISC 기반의 대표적인 ISA이다. x86-64보다 더 많은 명령어로 동일한 프로그램을 실행하는 것을 볼 수 있다. 즉, 같은 소스 코드를 컴파일해도 RISC는 CISC보다 많은 수의 명령어로 변환된다.

 

 


 

 

 

단원 마무리하기

 

 

1번 문제는 조금 헷갈렸는데 그래도 잘 풀었다. CISC는 다양한 명령어 주소 지정 방식을 지원한다.

 


 

 

학습을 마치고

저녁 먹기 전에 이 단원을 학습하고 싶어서 시간이 조금 늦었지만 마저 공부를 다 했다. CPU의 언어라고 할 수 있는 CISC와 RICS의 차이점을 배울 수 있는 시간이었다. 학습 시간은 1시간 정도 걸린 것 같다.

이제 저녁을 먹고 이후에 나머지 공부를 진행해보려고 한다.