본문 바로가기
What I Learned

[WIL] Day 16

by 케찹이 2023. 6. 18.

~~~ALU와 제어장치~~~

ALU는 피연산자를 레지스터로부터 받아오고 제어장치로 부터 제어 신호를 받아들인다. 

결과값을 레지스터에 담는다. 단지 ALU이 내보내는 정보중 하나. 

플래그. ALU가 내보내는 다른 결과, 플래그는 연산 결과애 대한 부가 정보. overflow나타날때도 플래그에 담김.

 

주된 플래그의 종류

  • 부호 플래그
  • 제로 플래그: 연산 결과가 0인지 나타냄.
  • 캐리 플래그
  • 오버플로우 플래그
  • 인터럽트 플래그: 인터럽트 가능한지 나타냄
  • 슈퍼바이저 플래그: 커널 모드로 실행하는지 사용자 모드로 실행중인지 나타낸다.

위의 플래그들은 플래그 레지스터에 저장이 된다. 

 

제어장치

제어장치가 받아들이는 정보, 클럭 이라는게 있다.

클럭신호는 컴퓨터의 모든 부품을 일사불란하게 움직일 수 있게 하는 시간 단위, 클럭주기에 맞춰 발생하는 신호.

클럭신호에 맞춰 명령어들이 실행이 된다. 

 

다음으로 받아드리는 것은 해석할 명령어를 받아들인다. 해당 명령어는 명령어 레지스터라는 특별한 레지스터에 저장되어 있음. 

플래그 값도 받아들인다. 제어신호도 받아들인다. 주변 장치들도 제어신호를 받아들일수가 있음. 

 

내보내는 정보, 제어신호. cpu내부에 전달하는 제어신호가 있고 외부에 전달하는 제어신호 존재. 

cpu내부에 보내는 신호는 ALU에 보내는 것과 레지스터에 보내는 것이 있고, cpu외부에 전달하는 것은 메모리 또는 입출력장치로 보내는 신호가 있음. 

 

~~~레지스터~~~

프로그래머 입장에서 조금 더 중요한 부품이다.

cpu마다 레지스터가 다르지만 공통된 레지스터는 다음과 같다. 

  • 프로그램 카운터: 메모리에서 가져올 명령어의 주소(메모리에서 읽어 들일 명령어의 주소)
  • 명령어 레지스터: 해석할 명령어(방금 메모리에서 읽어들인 명령어), 여기 있는 명령어를 제어장치가 받아들여서 해석한다. 
  • 메모리 주소 레지스터: 메모리의 주소 저장. CPU가 읽어 들이고자 하는 주소를 주소 버스로 보낼 때 거치는 레지스터
  • 메모리 버퍼 레지스터: 메모리와 주고받을 값(데이터와 명령어), CPU가 정보를 데이터 버스로 주고받을 때 거치는 레지스터 
  • 플래그 레지스터: 연산 결과 또는 CPU상태에 대한 부가적인 정보
  • 범용 레지스터: 다양하고 일반적인 상황에서 자유롭게 사용
  • 스택 포인터
  • 베이스 레지스터

 

프로그램 카운터는 반드시 1씩 증가하는 것은 아니고 메모리 주소 실행흐름을 이동하는 명령어(JUMP, CALL,…)이런거 호출되면 확바뀔수가 있음.

 

스택주소 지정 방식: 스택과 스택 포인터를 이용한 주소 지정 방식

스택 포인터: 스택의 꼭대기를 가리키는 레지스터(스택이 어디까지 차 있는지에 대한 표시)

스택은 메모리안에 연속되어 스택 영역으로 존재

 

변위 주소 지정 방식: 오퍼랜드 필드의 값(변위)과 특정 레지스터의 값을 더하여 유효 주소 얻기

변위 주소 지정 방식은 두가지가 있음. 

  1. 오퍼랜드 + 프로그램 카운터(상대 주소 지정 방식)
  2. 오퍼랜드 + 베이스 레지스터(베이스 레지스터 주소 지정 방식, 베이스 레지스터는 기준 주소가 담긴다.)

 

 

 

~~~명령어 사이클과 인터럽트~~~

cpu는 정해진 명령어 사이클로 수행을 하는데 간혹 흐름을 끊는 신호를 인터럽트라고 부른다.

 

명령어 사이클:

프로그램속 명령어들은 일정한 주기가 반복되며 실행 이 주기를 명령어 사이클이라고 한다. 

메모리에서 cpu로 가지고 오는 것을 인출, 그리고 실행 주기에서 인출 사이클이라고 한다. 

실행 사이클: 갖고 왔으면 실행.

명령어 사이클은 인출, 실행이 반복되면서 실행된다. 

하지만 인출을 해서도 바로 실행이 안되는 경우가 있다. 그래서 간접 사이클이 필요할 수도 있다(메모리 접근이 더 필요할 경우에는).

 

인터럽트의 종류는 동기 인터럽트(예외), 비동기 인터럽트(하트웨어 인터럽트)가 있다.  

동기 인터럽트(예외): CPU가 예기치 못한 상황을 접했을 때 발생.

동기인터럽트의 종류: 폴트, 트랩, 중단, 소프트웨어 인터럽트가 있다. OS에서 다룰 예정

 

비동기 인터럽트: 주로 입출력 장치에 의해 발생, 알림과 같은 역할

예) cpu가 프린트한테 출력시키고 출력완료되면 알려줘, 

입출력 작업 도중에도 효율적으로 명령어를 처리하기 위해서 사용한다. 

 

인터럽트 처리 순서:

  1. 입출력 장치는 cpu한테 인터럽트 요청 신호를 보낸다. 
  2. CPU는 실행 사이클이 끝나고 명령어를 인출하기 전에 항상 인터럽트 여부를 확인한다.
  3. CPU는 인터럽트 요청을 확인하고 인터럽트 플래그를 통해 현재 인터럽트를 받아들일 수 있는지 여부를 확인한다.
  4. 인터럽트를 받아들일 수 있다면 CPU는 지금까지의 작업을 백업한다.
  5. CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행한다.
  6. 인터럽트 서비스 루틴 실행이 끝나면 4에서 백업해둔 작업을 복구하여 실행을 재개한다. 

 

인터럽트 요청 신호:

입출력 장치들이 cpu에 끼여들어도 되냐는 요청을 보내는 신호. 

CPU가 인터럽트 요청을 받아들이려면? 

인터럽트 플래그를 확인. 유의할점, 모든 인터럽트를 인터럽트 플래그로 막을 수 있는 것이 아니다. 일부 인터럽트, 하드웨어 고장, 정전, 긴급한 인터럽트도 존재, 이러한 것은 막을 수가 없음. Non maskable interrupt라고 부름.

 

cpu가 인터럽트를 받아들이기로 했다면 인터럽트 서비스 루틴을 실행.

인터럽트 서비스 루틴은 실행, 해당 인터럽트를 어떻게 처리하기 위한 프로그램. 그리고 메모리에 저장이 되어 있음. 

 

인터럽트 벡터: 인터럽트마다 고유한 인터럽트 서비스 루틴의 시작주소를 가지고 있음. 그래서 각각의 인터럽트를 구분하기 위한 정보를 인터럽트 벡터라고 한다. 메모리에 인터럽트 벡터 테이블 또한 존재한다. 인터럽트 서비스 루틴의 시작 주소를 포함하는 인터럽트 서비스 루틴의 식별 정보

 

정리하자면 cpu가 인터럽트를 처리한다는 것은 인터럽트 서비스 루틴을 실행하고 본래 수행하던 작업으로 다시 되돌아온다라고 정리할 수가 있음.

인터럽트하기 전까지 있었던 레지스터는 백업을 해야한다. 그래서 백업해야할 값들은 전부 스택에 저장을 해놓는다. 

 

인터럽트 서비스 루틴 : 인터럽트를 처리하는 프로그램

 

~~~빠른 CPU를 위한 설계 기법~~~

클럭신호가 빠르면 cpu를 비롯한 컴퓨터 부품들은 그만큼 빠른 박자에 맞춰 움직이나? 일반적으로 yes. 

클럭속도: 헤르츠 단위로 측정

헤르츠: 1초에 클럭이 반복되는 횟수

실제 cpu는 1초에 클럭이 기본적으로 25억번, 순간적으로 최대 49억번 반복된다. 

 

클럭신호를 마냥 높이면? 필요 이상으로 클럭을 높이면 발열이 심각해짐.

클럭 속도를 늘리는 방법 이외에는?

  1. 코어 수를 늘리는 방법
  2. 스레드 수를 늘리는 방법이 있음.

 

코어란?

  • 현대적인 관점에서 “CPU”라는 용어를 재해석 해야함. 
  • ‘명령어를 실행하는 부품’
  • 전통적으로 ‘명령어를 실행하는 부품’은 원칙적으로 하나만 존재
  • 그러나 오늘날 CPU에는 ‘명령어를 실행하는 부품’이 여러개 존재
  • ‘명령어를 실행하는 부품’을 코어라는 용어로 사용.

  멀티코어 프로세서란 여러 개의 코어를 포함하고 있는 CPU를 말한다.

코어수에 비례해서 속도가 증가하는 것은 아니다.

 

스레드와 멀티 스레드

스레드는 하드웨어적 스레드와 소프트웨어적 스레드가 존재한다.

 

하드웨어 스레드: 하나의 코어가 동시에 처리하는 명령어 단위

하이퍼스레딩은 인텔의 멀티스레드 기술. 8코어 16스레드이면 각 코어가 동시에 수행할 수 있는 명령어가 2개이다.

 

소프트웨어 스레드: 하나의 프로그램에서 독립적으로 실행되는 단위

동시에 여러 작업. 스레드를 3개만들어서 각각 실행되게 하면 워드 프로세서 프로그램에서 3개의 실행 흐름, 그리고 동시에 실행.

나중에 OS에서 자세히…

 

다시 하드웨어 스레드.

멀티스레드 프로세서를 설계한다 할때 가장 큰 핵심은 레지스터.

하나의 명령어를 실행하기 위해 꼭 필요한 레지스터들을 편의상 ‘레지스터 세트’로 표기

레지스터 세트가 하나의 코어 내부에 여러개가 있으면 하나의 코어가 여러 명령어를 동시에 처리할 수가 있다. 

하드웨어 스레드를 논리 프로세서라고 부른다. 

 

~~~명령어 병렬 처리 기법~~~

어떻게 시간 낭비 없이 메모리의 명령어를 빨리 실행할 수 있는지도 중요

 

명령어 파이프라인

명령어가 처리되는 과정을 비슷한 시간 간격으로 나누면?

  1. 명령어 인출(Instruction Fetch)
  2. 명령어 해석(Instruction Decode)
  3. 명령어 실행(Execute Instruction)
  4. 결과 저장(Write Back)

 

같은 단계가 겹치지만 않는다면 CPU는 ‘각 단계를 동시에 실행할 수 있다’

파이프라인 위험: 명령어 파이프라인이 성능 향상에 실패하는 경우

  1. 데이터 위험
  2. 제어 위험
  3. 구조적 위험 

 

데이터 위험: 명령어 간의 의존성에 의해 야기

모든 명령어를 동시에 처리할 수는 없다.(이전 명령어를 끝까지 실행해야만 비로소 실행할 수 있는 경우)

1이 결정이 되어야지 2가 실행가능, 의존성에 의해서 야기하는 위험

 

제어 위험: 프로그램 카운터의 갑작스러운 변화

메모리 주소 번지가 갑자기 바뀌는 경우(CALL, JUMP) 이어서 동시에 처리하고 있던 명령어들은 헛수고가 된다. 이러한 상황을 방지하기 위해서 미리 어디로 점프할지 예측을 할수가 있음. 그런걸 분기 예측(branch prediction)이라고 함.

 

구조 위험: 서로 다른 명령어가 같은 CPU부품(ALU, 레지스터)를 쓰려고 할때.

 

슈퍼스칼라

CPU내부에 여러개의 명령어 파이프라인을 포함한 구조.(오늘날의 멀티스레드 프로세서)

이론적으로 파이프라인 개수에 비례하여 처리 속도 증가, 그러나 파이프라인 위험도의 증가로 인해 파이프라인 개수에 비례하여 처리 속도가 증가하진 않음. 

 

비순차적 명령어 처리

비순차적 명령어 처리 기법은 파이프라인의 중단을 방지하기 위해 명령어를 순차적으로 처리하지 않는 명령어 병렬 처리 기법이다.(합법적 새치기)

명령어의 순서를 영향이 없을때 바꾸는 방식.

 

~~~명령어 집합 구조, CISC와 RISC~~~

명령어가 어떻게 생겨야 명령어 파이프라이닝에 유리할까요?

 

명령어 집합: CPU가 이해할 수 있는 명령어들의 모음. CPU언어인 셈. ISA라고도 부른다. ISA는 CPU의 언어이자 하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속이다. 

 

명령어 집합의 두축 : CISC & RISC

CISC(Complex Instruction Set Computer)복잡한 명령어를 활용하는 컴퓨터. X86, x86-64다 CISC기반.

복잡하고 다양한 명령어 활용. 명령어의 형태와 크기가 다양한 다변 길이 명령어를 활용. 

메모리를 최대한 아낄수 있지만 명령어 파이프라이닝이 불리하다. 복잡한 탓에 명령어의 크기와 실행되는 시간이 일정하지가 않다.명령어 하나를 실행하는데 여러 클럭이 필요. 대다수 복잡한 명령어는 사용 빈도수가 낮다. 

 

RISC(Reduced Instruction Set Computer)

명령어 종류 짧고 규격화된 명령어 사용. 고정 길이. 메모리 접근 최소화, 레지스터 십분 활용.더 많은 명령어가 필요하게 된다. 

 

'What I Learned' 카테고리의 다른 글

[WIL] Day 18  (0) 2023.06.19
[WIL] Day 17  (0) 2023.06.19
[WIL] Day 15  (0) 2023.06.17
[WIL] Day 14  (0) 2023.06.10
[WIL] Day 13  (0) 2023.06.09

댓글