[혼공컴운] 2주차 - CPU의 동작원리, CPU 성능 향상 기법

박민주·2024년 7월 7일
0

ALU와 제어장치

ALU와 제어장치가 어떤 정보를 내보내고 받아들이는지를 중심으로 두 장치의 역할을 학습해보기.

ALU

ALU가 받아들이는 정보

ALU는 레지스터릉 통해 피연산자를 받아들이고, 제어장치로 부터 수행할 연산을 알려주는 제어신호를 받아드인다. ALU는 레지스터 제어장치로 부터 받아들인 피연산자와 제어신호로 다양한 연산을 수행한다.

ALU가 내보내는 정보

ALU는 연산한 결과를 실행속도의 향상을 위해 결괏값을 레지스터에 우선 저장한다.
또한, ALU는 결괏값뿐만 아니라 연산결과에 대한 추가 정보를 내보내기 위해 플래그를 같이 내보낸다.

플래그들은 플래그 레지스터라는 레지스터에 저장된다.

제어장치

제어장치는 제어신호를 내보내고, 명령어를 해석하는 부품이다. 그리고 제어신호는 컴퓨터 부품들을 관리하고 작동시키기 위한 일종의 전기 신호이다.

제어장치가 받아들이는 정보

1. 제어장치는 클럭신호를 받아들인다.

클럭이란 컴퓨터의 모든 부품들을 일사불란하게 움직일 수 있게하는 시간 단위이다. 클럭의 주기에 맞춰 ALU에서 연산이 수행되거나, CPU가 메모리에 저장된 명령어를 읽어들인다.

컴퓨터 부품들은 클럭이라는 박자에 맞춰 작동할 뿐 한 박자마다 작동하는것이 아니다 !

2. 제어장치는 '해석해야할 명령어'를 받아들인다.

CPU가 해석해야 할 명령어는 명령어 레지스터라는 특별한 레지스터에 저장된다. 제어장치는 이 명령어 레지스터로부터 해석할 명령어를 받아 들이고 해석한 뒤, 제어신호를 발생시켜 컴퓨터 부품들에 수행해야할 내용을 알려준다.

3. 제어장치는 플래그 레지스터 속 플래그 값을 받아들인다.

제어장치는 ALU연산에 대한 추가적인 상태 정보인 플래그 값을 받아들이고 이를 참고하여 제어신호를 발생 시킵니다.

4. 제어장치는 시스템 버스, 그중에서 제어버스로 전달된 제어신호를 받아들인다

CPU뿐만 아니라 입출력장치를 비롯한 외부장치로 부터 발생된 제어신호를 제어버스를 통해 외부로부터 받아들이기도 한다.

제어장치가 내보내는 정보

CPU 외부에 전달하는 제어신호

제어장치가 CPU 외부에 제어신호를 전달한다는 말은 곧, 제어버스로 제어신호를 내보낸다는 말과 같다. 이러한 제어신호에는 크게 메모리에 전달하는 제어신호롸 입출력장치(보조기억장치 포함)에 전달하는 제어신호가 있다.

CPU 내부에 전달하는 제어신호

ALU와 레지스터에 전달하는 신호로 나눌 수 있다. ALU에는 수행할 연산을 지시하기 위해, 레지스터에는 레지스터 간에 데이터를 이동시키거나 레지스터레 저장된 명령어를 해석하기 위한 신호를 보낸다.

확인문제

답 : 부호플래그가 1이므로 결괏값은 음수이다. 101은 2의 보수로 변환한 011의 값인 3의 음수인 -3이 정답이다.

답 : 4. 연산을 담당하는 부품은 ALU이다

답 : 1 - 플래그 레지스터, 2 - 명령어 레지스터 , 3 - 제어버스

답 : 4. 보조기억장치이다. CPU 외부에 위치한다.

레지스터

레지스터의 종류와 역할을 학습하고, 각 레지스터를 통해 명령어가 처리되는 과정을 이해하자.
프로그램 속 명령어와 데이터는 실행 전후로 레지스터에 저장되고, 레지스터에 저장된 값만 잘 관찰해도 프로그램의 실행 흐름을 파악 할 수 있다.
CPU안에는 다양한 레지스터가 있고, 각기 다른 역할을 가지고 있는 레지스터의 이름과 역할을 학습하자.

반드시 알아야할 레지스터

  1. 프로그램 카운터
  2. 명령어 레지스터
  3. 메모리 주소 레지스터
  4. 메모리 버퍼 레지스터
  5. 플래그 레지스터
  6. 범용 레지스터
  7. 스택 포인터
  8. 베이스 레지스터

프로그램 카운터(PC;Program Counter)

메모리에서 읽어들일 명령어의 주소를 저장한다. 명령어 포인터(Instruction Pointer)라고 부르는 경우도 있다.

명령어 레지스터(IR;Instruction Register)

방금 메모리에서 읽어들인 명령어를 저장하는 레지스터. 제어장치는 명령어 레지스터 속 명령어를 받아들이고 이를 해석한뒤 제어신호를 내보낸다.

메모리 주소 레지스터(MAR;Memory Address Register)

메모리의 주소를 저장하는 레지스터. CPU가 읽어들이고자 하는 주소값을 주소 버스로 보낼 때 메모리 주소 레지스터를 거치게 된다.

메모리 버퍼 레지스터(MBR;Memory Buffer Register)

메모리에 쓰고 싶은 값이나 메모리로부터 전달 받은 값은 메모리 버퍼 레지스터를 거칩니다. 데이터버스로 주고 받을 값은 메모리 버퍼 레지스터를 거치게 된다.

메모리에 저장된 프로그램을 실행하는 과정

  1. CP로 실행할 프로그램이 1000번지 부터 1500번지까지 저장되어 있다고 가정하고, 1000번지에는 1101(2)이 저장되있다고 가정한다.
  2. 프로그램을 처음부터 실행하기 위해 프로그램 카운터에는 1000이 저장된다. 이는 메모리에서 가져올 명령어가 1000번지에 있다는 것을 의미한다.
  3. 1000번지를 읽어들이기 위해서는 주소버스로 1000번지를 내보내야 한다. 이를 위한 메모리 주소 레지스터에는 1000이 저장된다.
  4. '메모리 읽기' 제어 신호와 메모리 주소 레지스터 값이 각각 제어 버스와 주소버스를 통해 메모리로 보내진다.
  5. 메모리 1000번지에 저장된 값은 데이터 버스를 통해 메모리 버퍼 레지스터로 전달되고, 프로그램 카운터는 증가되어 다음 명령어를 읽어들일 준비를 한다.
  6. 메모리 버퍼 레지스터애 저장된 값은 명령어 레지스터로 이동한다.
  7. 제어장치는 명령어 레지스터의 명령어를 해석하고 제어신호를 발생시킨다.

5단계에서 프로그램 카운터 값이 증가하는 것처럼 프로그램 카운터는 지속적으로 증가하여 계속해서 다음 명령어를 받아들일 준비를 하면서 CPU는 프로그램을 차레대로 실행해나간다.

명령어 중 JUMP, CONDITIONAL JUMP, CALL과 같이 특정메모리 주소로 실행흐름을 이동하는 명령어가 실행되거나 인터럽트가 발생하면 프로그램의 순차적인 실행 흐름은 끊어질 수 있다.

범용 레지스터

다양하고 일반적인 상황에서 자유롭게 사용할 수 있는 레지스터이다. 데이터와 주소를 모두 저장할 수 있다.

플래그 레지스터

연산결과 또는 CPU상태에 대한 부가적인 정보를 저장하는 레지스터 이다.

특정 레지스터를 이용한 주소 지정방식(1) - 스택 주소 지정 방식

스택 주소 지정 방식

스택 포인터는 스택 주소 지정방식에 사용된다. 스택 포인터란 스택의 꼭대기를 가리키는 레지스터 이다. 즉, 스택 포인터는 스택에 마지막으로 저장한 값의 위치를 저장하는 레지스터 이다. 쉽게 말해 스택의 어디까지 데이터가 채워져 있는지에 대한 표시라고 보면된다.

스택은 메모리안에 있다. 정확히는 메모리안에 스택처럼 사용할 영역이 정해져 있고, 이를 스택 영역이라고 한다. 이 영역은 다른 주소 공간과는 다르게 스택처럼 사용하기로 암묵적으로 약속된 영역이다.

특정 레지스터를 이용한 주소 지정방식(2) - 변위 주소 지정 방식

변위 주소 지정 방식이란 오퍼랜드 필드의 값(변위)과 특정 레지스터의 값을 더하여 유효 주소를 얻어내는 주소 지정 방식이다.
유효주소 : 연산에 사용할 데이터가 저장된 주소
변위 주소 지정 방식을 사용하는 명령어는 다음 그림과 같이 연산코드 필드, 어떤 레지스터의 값과 더할지를 나타내는 레지스터 필드, 그리고 주소를 담고 있는 오퍼랜드 필드가 있다.

어떤 레지스터를 더하는지에 따라 상대 주소 지정 방식, 베이스 레지스터 지정 방식등으로 나뉜다.

상대 주소 지정 방식

오펀랜드와 프로그램 카운터의 값을 더하여 유효 주소를 얻는 방식. 상대 주소 지정방식은 프로그래밍 언어의 if문과 유사하게 모든 코드를 실행하는것이 아닌, 분기하여 특정 주소의 코드를 실행할 때 사용된다.

베이스 레지스터 주소 지정 방식

오퍼랜드와 베이스 레지스터의 값을 더하여 유효 주소를 얻는 방식. 여기서 베이스 레지스터는 '기준 주소', 오퍼랜드는 '기준 주소로부터 떨어진 거리' 로서의 역할을 한다.

확인 문제!

답 : 프로그램 카운터가 저장하고 있던 2100번지를 메모리 주소 레지스터에 저장한다.

답 : 1 - 플래그 레지스터, 2 - 프로그램 카운터 , 3 - 범용 레지스터, 4 - 명령어 레지스터

답 : 스택은 LIFO 자료구조이므로 6번지가 저장된다.

답 : 4

명령어 사이클과 인터럽트

CPU가 하나의 명령어를 처리하는 흐름인 명령어 사이클과 그 흐름을 방해하는 인터럽트에 대해 학습한다.

CPU가 하나의 명령어를 처리하는 과정엔 어떤 정해진 흐름이 있고, 흐름을 반복하여 명령어들은 처리한다. 이 정형화된 흐름을 명령어 사이클이라고 한다.

간혹 이 흐름이 끈어지는 상황을 인터럽트라고 한다.

명령어 사이클

CPU는 명령어들을 하나씩 실행하는데 일정한 주기가 반복되며 실행한다. 이 주기를 명령어 사이클이라고 한다.

이름과 달리 매우 단순한 개념으로 메모리에 저장된 명령어 하나를 실행하기 위해선 가장 먼저 명령어를 메모리에서 가져와야한다. 메모리에 있는 명령어를 CPU로 가져오는 단계를 인출 사이클이라고 한다.

명령어를 인출했다면 명령어를 실행하는게 명령어 사이클의 두번째 과정이다. CPU로 가져온 명령어를 실행하는 단계를 실행 사이클이라고 한다. 제어장치가 명령어 레지스터에 담긴 값을 해석하고, 제어신호를 발생시키는 단계가 실행 사이클이다.

하지만 모든 명령어가 이렇게 간단히 실행되는 것은 아니다. 명령어를 인출하여 CPU로 가져왔다고 하더라고 곧바로 실행할 수없는 경우도 있다. 예를 들어 간접 주소 지정방식의 경우 메모리 접근을 한번 더 해야 하기 때문이다. 이 단계를 간접 사이클이라고 한다.

인터럽트

인터럽트는 영어로는 'interrupt'이며, '방해하다, 중단시키다'를 의미한다. CPU의 작업을 방해하는 신호를 인터럽트라고 한다.

인터럽트의 종류에는 크게 동기 인터럽트비동기 인터럽트가 있다.

동기 인터럽트(예외)

동기 인터럽트는 CPU에 의해 발생하는 인터럽트이다. CPU가 명령어들을 수행하다가 예상치 못한 상황에 마주쳤을 때와 같은 예외적인 상황에 마주쳤을 때 발생하는 경우이다. 예외라고 부른다.

비동기 인터럽트(하드웨어 인터럽트)

비동기 인터럽트는 주로 입출력장치에 의해 발생하는 인터럽트이다.

  • 키보드, 마우스와 같은 입출력장치가 어떠한 입력을 받아들였을 때 이를 처리하기 위해 CPU에 입력 알림(인터럽트)을 보낸다.

일반적으로 비동기 인터럽트를 인터럽트라 칭하기도 하지만, 여기서는 하드웨어 인터럽트라는 용어를 사용한다.

하드웨어 인터럽트

하드웨어 인터럽트는 알림과 같은 인터럽트이다. CPU는 입출력 작업 도중에도 효율적으로 명령어를 처리하기위해 이런 알림과 같은 하드웨어 인터럽트를 사용한다.

하드웨어 인터럽트 처리순서

  1. 입출력장치는 CPU에 인터럽트 요청 신호를 보낸다.
  2. CPU는 실행 사이클이 끝나고 명령어를 인출하기 전 항상 인터럽트 여부를 확인한다.
  3. CPU는 인터럽트 요청을 확인하고 인터럽트 플래그를 통해 현재 인터럽트를 받아들일 수 있는지 여부를 확인한다.
  4. 인터럽트를 받아들일 수 있다면 CPU는 지금까지의 작업을 백업한다.
  5. CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행한다.
  6. 인터럽트 서비스 루틴 실행이 끝나면 4.에서 백업해둔 작업을 복구하여 실행을 재개한다.
  • 인터럽트 요청신호 : CPU의 작업을 방해하는 인터럽트에 대한 요청
  • 인터럽트 플래그 : 인터럽트 요청 신호를 받아들일지 무시할지를 결정하는 비트
  • 인터럽트 벡터 : 인터럽트 서비스 루틴의 시작 주소를 포함하는 인터럽트 서비스 루틴의 식별 정보
  • 인터럽트 서비스 루틴 : 인터럽트를 처리하는 프로그램

확인문제

답 : 4. 인터럽트는 프로그램의 순차적인 흐름을 방해하는 경우이다.

답 : 3 - 인터럽트 플래그를 설정한다고 해도 보든 인터럽트를 막을 수는 없다.

답 : 인터럽트 서비스 루틴

답 : 2

답 : 3

빠른 CPU를 위한 설계 기법

클럭과 코어, 스레드라는 개념을 학습하고, 빠른 CPU를 만드는 설계 기법인 멀티코어와 멀티스레드란 무엇인지 이해한다.

클럭

이전 내용에서 '1. 컴퓨터 부품들은 '클럭신호'에 맞춰 일사불란하게 움직인다. 2. CPU는 '명령어 사이클'이라는 정해진 흐름에 맞춰 명령어들을 실행한다.' 라고 학습했다.

클럭 신호가 빠르게 반복되면 CPU를 비롯한 컴퓨터 부품들은 그만큼 빠른 박자에 맞춰 움직일 것이고, 실제로 클럭속도가 높은 CPU는 일반적으로 성능이 좋다. 그래서 클럭 속도는 CPU 속도 단위로 간주되기도 한다.

클럭 속도는 헤르츠(Hz) 단위로 측정하고, 이는 1초에 클럭이 몇번 반복되는지를 나타낸다.

클럭속도는 계속 일정한 속도를 유지하기보단 필요에 따라 속도를 높이거나 낮추기도한다. 최대 클럭 속도를 강제로 끌어 올리는 기법을 오버클럭킹이라 한다.

하지만 CPU속도를 무작정 올리면 발열이 문제가 심각해진다. 클럭 속도만으로 CPU의 성능을 올리는 데엔 한계가 있는 것이다.

코어와 멀티코어

클럭속도를 높이는 방법외에 CPU의 성능을 높이는 방법에는 어떤 것들이 있을까? 대표적으로 CPU의 코어와 스레드 수를 늘리는 방법이 있다.

오늘날 CPU는 많은 기술이 발전하여 CPU 내부에 '명령어를 실행하는 부품'을 얼마든지 만들 수 있게 되었다. 이 부품은 오늘날 코어라는 용어로 사용하게 된다.

코어를 여러 개 포함하고 있는 CPU를 멀티코어 CPU또는 멀티코어 프로세서라고 부른다. 이는 CPU내에 명령어를 처리하는 일꾼이 여러명 있는것과 같다.

하지만 CPU의 연산속도가 꼭 코어 속도에 비례하는 것은 아니다. 중요한 것은 코어마다 처리할 명령어들을 얼마나 적절하게 분배하느냐이고, 그에 따라 연산 속도는 크게 달라진다.

스레드와 멀티스레드

스레드의 사전적 의미는 '실행흐름의 단위'이다. 하지만 CPU에서와 프로그래밍에서의 스레드는 용례가 다르다.

스레드에는 CPU에 사용되는 하드웨어적 스레드가 있고, 프로그램에서 사용되는 소프트웨어적 스레드가 있다.

하드웨어적 스레드

하드웨어적 스레드의 정의는 '하나의 코어가 동시에 처리하는 명령어 단위'를 의미한다.

여러 스레드를 지원하는 CPU는 하나의 코어로도 여러개의 명령어들을 동시에 실행 할 수 있다. 예를 들어 2코어 4스레드 CPU는 명령어를 실행하는 부품을 두 개 포함하고, 한 번에 네 개의 명령어를 처리할 수 있는 CPU를 의미한다.

이처럼 하나의 코어로 여러 명령어를 동시에 처리하는 CPU를 멀티스레드 프로세서 또는 멀티스레드 CPU라고 한다.

하이퍼스레딩이라는 인텔의 멀티 스레드기술을 자주 접하게 될 것이다.

소프트웨어적 스레드

소프트웨어적 스레드는 '하나의 프로그램에서 독립적으로 실행되는 단위'를 의미한다.

하나의 프로그램은 실행되는 과정에서 한 부분만 실행될 수도 있지만, 프로그램의 여러 부분이 동시에 실행될 수도 있다.

멀티스레드 프로세서

하나의 코어로 여러 명령어를 동시에 처리하는 기술인 하드웨어적 스레드이다.

멀티스레드 프로세서는 하나의 코어로 여러 명령어를 동시에 처리하는 CPU이다. 멀티스레드 프로세서를 실제로 설계하는 일은 매우 복잡하지만, 가장 큰 핵심은 레지스터이다. 하나의 명령어를 처리하기 위해 꼭 필요한 레지스털르 여러개 가지고 있으면 된다.

그림에서 처럼 레지스터 세트가 두 개인 CPU는 두 개의 명령어를 처리하기 위한 정보들을 기억하고, ALU와 제어장치가 명령어를 해석하고 실행하면 하나의 코어에서 두 개의 명령어가 동시에 실행된다.

하드웨어적 스레드를 이용해 하나의 코어로 여러 명령어들을 동시에 처리할 수 있다고 하였는데, 메모리 속 프로그램에서는 하드웨어 스레드는 마치 '한 번에 하나의 명령어를 처리하는 CPU'나 다름없다. 가령 2코어 4스레드 CPU는 한 번에 네개의 명령어를 처리하지만, 프로그램 입장에선 CPU가 네 개 있는 것처럼 보이고, 논리 프로세서라고 부르기도 한다.

정리

  • 코어는 명령어를 실행할 수 있는 '하드웨어 부품'이다.
  • 스레드는 '명령어를 실행하는 단위'이다.
  • 멀티코어 프로세서는 명령어를 실행할 수 있는 하드웨어 부품이 CPU안에 두 개 이상 있는 CPU를 의미한다.
  • 멀티스레드 프로세서는 하나의 코어로 여러개의 명령어를 동시에 실행할 수 있는 CPU를 의미한다.

확인문제

  1. 클럭에 대한 설명 옳지 않은 것을 고르세요.
    ① CPU는 클럭 신호에 맞춰 작동한다.
    ② 클럭 신호는 CPU의 속도 단위이다.
    ③ 클럭신호를 높여도 컴퓨터 부품은 발열 없이 빠르게 작동한다
    ④ 클럭신호는 항상 일정하게 유지 되지않는다.

    답 : 3 - 클럭신호를 높이면 발열이 발생하게 되는 문제가 생긴다. 이는 클럭 신호를 높여 성능을 향상시키는 것의 한계이다.

  2. 멀티코어와 멀티스레드에 대한 설명 중 옳지 않은 것을 고르세요.
    ① 코어는 명령어를 인출하고 해석하고 실행하는 부품의 집합입니다.
    ② 스레드는 코어가 처리할 수 있는 작업 단위입니다.
    ③ 여러 개의 스레드를 처리할 수 있다면 하나의 프로그램을 동시에 처리할 수 있습니다.
    ④ 하나의 코어는 하나의 스레드만 처리할 수 있습니다.

    답 : 4 - 하나의 코어에 여러개의 스레드를 처리하는 것이 멀티스레드이다.

  3. 스레드와 관련된 설명으로 보기에서 알맞은 말을 찾아 써 넣으세요
    보기 : 소프트웨어, 하드웨어, 시스템버스
    스레드에는 빈칸 1적 스레드와 빈칸 2적 스레드가 있습니다.

    답 : 소프트웨어, 하드웨어

  4. 다음 그림은 멀티코어 CPU를 간략하게 도식화한 그림입니다. 빈칸에 알맞은 용어를 써 넣으세요.

    답 : 코어, 멀티코어 CPU는 CPU내에 2개 이상의 코어가 있는 것을 의미한다.

명령어 병렬 처리 기법

명령어를 빠르고 효율적으로 처리하기 위해 CPU를 한시도 쉬지 않고 작동시키는 명령어 병렬 처리 기법을 알아보자.

대표적인 명령러 처리 기법에는 명령어 파이프 라이닝, 슈퍼스칼라, 비순차적 명령어 처리가 있다.

명령어 파이프라인

명령어 처리과정을 클럭단위로 나눈다면 1. 명령어 인출 2. 명령어 해석 3. 명령어 실행 4. 결과저장과 같은 단계로 나뉠 수 있다. 여기서 중요한 점은 같은 단계가 겹치지 않는다면 CPU는 '각 단계를 동시에 실행할 수 있다'는 것이다.

이처럼 마치 공장 생산라인과 같이 명령어들을 명령어 파이프라인에 넣고 동시에 처리하는 기법을 명령어 파이프라이닝이라고 한다.

하지만 특정 상황에서는 성능 향상에 실패하는 경우도 있다. 이런 상황을 파이프라인 위험이라고 부르고, 크게 데이터 위험, 제어 위험, 구조적 위험이 있다.

데이터 위험

데이터 위험은 명령어 간 '데이터 의존성'에 의해 발생한다. 모든 명령어를 동시에 처리 할 수는 없다. 어떤 명령어는 이전 명령어를 끝까지 실행해야 실행할 수 있는 경우가 있다.

명령어 1: R1 <- R2 + R3  // R2, R3레지스터 값을 더한값을 R1에 저장
명령어 2: R4 <- R1 + R5  // R1, R5레지스터 값을 더한값을 R4에 저장

위의 경우 명령어 1을 수행해야만 명령어 2를 수행할 수있다. 이처럼 데이터 의존적인 두 명령어를 무작정 동시에 실행하려고 하면 제대로 작동하지 않는 것을 '데이터 위험'이라고 한다.

제어위험

제어위험은 주로 분기 등으로 인한 '프로그램 카운터의 갑작스러운 변화'에 의해 발생한다. 기본적으로 프로그램 카운터는 '현재 실행중인 명령어의 다음 주소'로 갱신되지만 프로그램 실행 흐름이 바뀌어 프로그램 카운터 값에 변화 생긴다면 명령어 파이프라인에 미리 가지고 와서 처리중이었던 명령어들은 아무 쓸모가 없어지고, 이를 '제어위험'이라고 한다.

이를 위해 사용하는 기술 중 하나가 분기예측이다. 이는 프로그램이 어디로 분기할지 미리 예측한 후 그 주소를 인출하는 기술이다.

구조적 위험

구조적위험은 명령어들을 겹쳐 실행하는 과정에서 서로 다른 명령아 동시에 ALU, 레지스터 등과 같은 CPU부품을 사용하려고 할때 발생한다. 자원 위험이라고도 부른다.

슈퍼스칼라

CPU내부에 여러개의 명령어 파이프라인을 포함한 구조를 슈퍼스칼라라고 한다.

슈퍼스칼라 구조로 명령어 처리가 가능한 CPU를 슈퍼스칼라 프로세서 또는 슈퍼스칼라 CPU라고 한다. 슈퍼스칼라 스포레서는 매 클럭 주기마다 동시에 여러 명령어를 인출, 실행 할 수도 있어야한다.

슈퍼스칼라 프로세서는 이론적으로 파리으파인 개수에 비례하여 프로그램 처리속도가 빨라지지만 파이프라인 위험등의 예상치 못한 문제로 실제로는 반드시 개수에 비례하지 않는다.

이 때무에 슈퍼스칼라 방식을 차용한 CPU는 고도의 설계가 필요하고, 하나의 파이프라인을 사용할 때마다 위험을 피하기가 더욱 까다롭다

비순차적 명령어 처리

비순차적 명령어 처리는 Out-of-order execution으로 보통 OoOE로 줄여 부른다. 오늘날 CPU 성능향상에 크게 기여한 기법이자 대부분의 CPU가 차용하는 기법이다.

비순차적 명령어 처리 기법은 이름에서도 알 수 있듯 명령어들을 순차적으로 실행하지 않는 기법이다.

1. M(100) <- 1
2. M(101) <- 2
3. M(102) <- M(100) + M(101)
4. M(150) <- 1
5. M(151) <- 2
6. M(152) <- 3

여기서 주목해야 할 점은 3번 명령어를 처리하기 위해선 1,2번 명령어 실행이 끝날 때까지 기다려야한다. 하지만 4,5,6번 명령어들은 앞선 명령어들 중에 서로 데이터 의존성이 없으므로 순서가 수행결과에 영향을 미치지 않는다.

1. M(100) <- 1
2. M(101) <- 2
4. M(150) <- 1
5. M(151) <- 2
6. M(152) <- 3
3. M(102) <- M(100) + M(101)

이렇게 순서를 바꿔 실행하면 순차적으로 실행할 때보다 더 효율적으로 처리할 수있다. 이렇게 명령어를 순차적으로만 실행하지 않고 순서를 바꿔 실행해도 무방한 명령어를 먼저 실행하여 명령어 파이프라인이 멈추는 것을 방지하는 기법을 비순차적 명령어 처리 기법이라고 한다.

확인문제

  1. 명령어 파이프라이닝에 대한 설명으로 옳지 않은 것을 고르세요.
    ① 명령어 파이프라이닝은 명령어를 병렬적으로 처리하는 기법이다.
    ② 슈퍼스칼라는 단일한 명령어 파이프라인을 이용하여 명령어를 처리하는 기법이다.
    ③ 제어 위험은 프로그램 카운터의 갑작스러운 변화에 의해 발생한다.
    ④ 데이터 위험은 명령어 간의 데이터 의존성에 의해 발생한다.

    답 : 2 - 슈퍼스칼라 구조는 여러개의 명령어 파이프라인을 포함한 구조이다.

  2. 다음 보기를 바탕으로 올바른 정의를 짝지으세요.
    보기 : 슈퍼스칼라, 비순차적 명령어 처리
  • 1번 : 순서를 바꾸어 명령어를 실행하는 기법
  • 2번 : 여러개의 파이프라인을 이용하여 명령어를 동시에 처리하는 기법

답 : 1 - 비순차적 명령어 처리 , 2 - 슈퍼스칼라

CISC와 RISC

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

명령어 집합

모든 CPU가 이해하고 실행하는 명령어들의 세세한 생김새, 명령어로 할 수 있는 연산, 주소 지정 방식 등은 CPU마다 조금씩 차이가 있다. CPU가 이해할 수 있는 명령어들의 모음을 명령어집합(Instruction Set)또는 명령어 구조(ISA; Instruction Set Archtectrue)라고 한다.

ISA가 다르다는건 CPU가 이해할 수 있는 명령어가 다르다는 뜻이고, 명령어가 달라지면 어셈블리어도 달라진다. 같은 소스 코드로 만들어진 프로그램이어도 ISA가 다르면 CPU가 이해할 수 있는 명령어도 어셈블리어도 달라진다.

ISA가 다르면 그에 따른 나비효과로 제어장치가 명령어를 해석하는 방식, 사용되는 레지스터의 종류와 개수, 메모리 관리방법 등 많은것이 달라진다. 이는 곧 CPU 하드웨어 설계에도 큰 영향을 미친다.

ISA는 CPU의 언어임과 동시에 CPU를 비롯한 하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속이라고도 볼 수 있다.

명령어 병렬 처리 기법을 적용하기에 용이한 ISA가 있고, 그렇지 못한 ISA도 있다. 그렇다면 명령어 병렬 처리 기법을 도입하기 유리한 ISA는 무엇인지 알아보자.

CISC(Complex Istruction Set Computer)

CISC를 해석하면 '복잡한 명령어 집합을 활용하는 컴퓨터'를 의미한다. 이름 그대로 복잡하고 다양한 명령어들을 활요하는 CPU설계방식이다. x86, x86-64가 대표적인 CISC기반의 ISA이다.

CISC는 다양하고 강력한 기능의 명령어 집합을 활용하기 때문에 명령어의 형태와 크기가 다양한 가변 길이 명령어를 활용한다. 메모리에 접근하는 주소 지정방식도 다양해서 아주 특별한 상황에서만 사용되는 독특한 주소 지정 방식들도 있다.

다양하고 강력한 명령어를 활용한다는 것은 상대적으로 적은수의 명령어로도 프로그램을 실행할 수 있다는 것을 의미한다.

프로그램을 실행하는 명령어 수가 적다는 말은 '컴파일된 프로그램의 크기가 작다는'의미다.

CISC는 이런 장점으로 메모리 공간을 절약할 수있다는 장점이 있었지만, 치명적인 단점으로 활용하는 명령어가 워낙 복잡하고 다양한 기능을 제공하는 탓에 명령어의 크기와 실행되기 까지의 시간이 일정치 않고, 복잡한 명령어 때문에 명령어 하나를 실행하는데에 여러 클럭 주기를 필요로한다.

이는 명령어 파이프 라인을 구현하는데에 큰 걸림돌이 된다. 명령어 수행시간이 길고 가지각색이기 때문에 효율적으로 명령어를 처리할 수없기 때문이다. 또한 명령어 집합이 다양하고 복잡한 기능을 지원하지만 실제로는 자주 사용되는 명령어만 쓰인다는 것이다.

정리하면 CISC명령어 집합은 복잡하고 다양한 기능을 제공하기에 적은 수의 명령으로 프로그램을 동작하고 메모리를 절약할 수 있지만, 명령어의 규격화가 어려워 파이프라이닝이 어렵다. 이러한 이유로 CISC기반의 CPU는 성에 한계가 있다.

RISC

CISC의 한계가 우리에게 준 교훈은 크게 두가지가 있다.

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

이런 원칙하에 등장한 것이 RISC이다. Reduced Instruction Set Computer의 약자이다. 이름처럼 CISC에 비해 명령어의 종류가 적다. 그리고 짧고 규격화된 명령어, 되도록 1클럭 내외로 실행되는 명령어를 지향한다.

즉, RISC는 고정 길이 명령어를 활용한다.

명령어가 규격화 되어있고, 하나의 명령어가 1클럭내외로 실행되기 때문에 RISC 명령어 집합은 명령어 파이프라이닝에 최적화되어있다.

그리고 RISC는 메모리에 직접 접근하는 명령어를 load,store 두 개로 제한하여 메모리 접근을 단순화하고 최소화를 추구한다. CISC보다 주소 지정방식의 종류가 적은 경우가 많다.

이런 점에서 RISC를 load-store 구조라고 부르기도 한다.

RISC는 메모리 접근을 단순화, 최소화 하는 대신 레지스터를 적극적으로 활용하고, 일반적인 경우보다 범용 레지스터 개수도 더많다. 다만 사용가능한 명령어 개수가 CISC보다 적으므로 보다 많은 명령어로 프로그램을 작동시킨다.

CISCRISC
복잡하고 다양항 명령어단순하고 적은 명령어
가변길이 명령어고정길이 명령어
다양한 주소 지정 방식적은 주소 지정방식
프로그램을 이루는 명령어의 수가 적음프로그램을 이루는 명령어의 수가 많음
여러 클럭에 걸쳐 명령어 수행1클럭 내외로 명령어 수행
파이프라이닝하기 어려움파이프라이닝하기 슁무

확인 문제

  1. CISC에 대한 설명중 옳지 않은 것을 고르세요.
    ① 명령어의 규격화가 어렵습니다.
    ② RISC보다 다양하고 강력한 기능을 가진 명령어들이 있습니다.
    ③ 적은 수의 명령어로 프로그램을 수행합니다.
    ④ 일반적으로 명령어 주소 지정방식의 종류가 적습니다.

    답 : 4 - 명령어 주소 지정방식 종류가 많다!

  2. RISC에 대한 설명 중 옳지 올바르지 않은 것을 고르세요.
    ① CISC보다 프로그램을 실행하는 명령어가 수가 적습니다.
    ② CISC보다 적은 메모리 접근 방식이 있습니다.
    ③ CISC보다 파이프라이닝에 유리합니다.
    ④ CISC보다 명령어의 크기가 규격화 되어있습니다.

    답 : 1 - CISC보다 명령어의 종류가 적고 단순하므로 보다 많은 명령어로 프로그램을 실행시킨다.

참고

본 내용은 '혼자 공부하는 컴퓨터 구조+운영체제' 서적의 내용을 개인적으로 공부한 내용입니다.

profile
개발자 되고싶다..

0개의 댓글