Uknow's Lab.
article thumbnail

 

 

 

 

혼공스터디 컴퓨터 구조 + 운영체제 2주차

컴퓨터 구조 + 운영체제 2주차 Chapter 4~5인 CPU편입니다.

 

 

 

CPU의 작동원리

ALU와 제어장치

CPU는 메모리에 저장된 명령어를 읽고, 해석하고, 실행하는 장치입니다.

ALU는 CPU 내부에서 계산을 담당하는 장치로,

 

레지스터로부터 피연산자를 받아들이고,

제어장치로부터 제어 신호를 받아들입니다.

 

피연산자와 제어 신호로 산술 연산 / 논리 연산 등을 수행합니다.

그리고 그 결과값은 바로 메모리에 저장되는 것이 아닌 일시적으로 레지스터에 저장됩니다.

 

CPU가 메모리 보다 레지스터에 접근하는 속도가 더 빠르기 때문입니다.

 

 

 

ALU는 계산 결과와 함께 플래그도 보냅니다.

플래그란, 연산 결과에 따른 추가적인 정보로써,

부호, 인터럽트, 슈퍼파이저, 오버플로우 등 CPU가 반드시 알아야 할 부가적인 정보들입니다.

 

 

 

제어 장치

제어장치는 제어 신호를 내보내고 명령어를 해석하는 부품입니다.

제어 신호
컴퓨터가 부품들을 관리하고 작동시키기 위한 전기 신호

 

제어 장치가 받아들이는 정보는 아래와 같습니다.

 

1. 클럭 신호

클럭이란 컴퓨터의 부품을 움직이게 할 수 있는 시간 단위로써,

클럭의 주기에 맞게 특정 작업이 실행됩니다.

 

단, 한 클럭당 한 작업이 실행되는 것은 아니며, 

모든 부품이 한 클럭마다 작동하는 것이 아닌,

클럭이라는 박자에 맞춰 작동합니다.

 

때문에 한 명령어가 여러 클럭에 걸쳐 작동할 수 있습니다.

 

 

 

 

장범준 게임에 비유하자면,

흐어어~ 할 때마다 한 잔(한 작업)을 원샷하는게 아닌,

흐어어~ 하는 박자에 맞춰 한 모금 씩 마시는 느낌이 되겠네요!

 

 

2. 해석해야 할 명령어 받기 : 명령어 레지스터로부터 해석할 명령어를 받아들이고,

해석하여 부품들에 수행해야 할 내용 전달

 

3. 플래그 레지스터 속 플래그 값 받기 : 플래그로부터 추가 정보를 받기

 

4. 제어 버스로 전달된 제어 신호 받아들이기

제어 신호는 CPU 뿐 아니라 입출력장치같은 다른 장치도 발생시킬 수 있으므로,

시스템 버스 (제어 버스)로부터 제어 신호를 받아들입니다.

 

 

 

명령어 사이클과 인터럽트

명령어 사이클

명령어 사이클이란 CPU가 하나의 명령어를 처리하는 정형화된 흐름을 의미하며,

이런 정해진 흐름이 끊어지는 상황을 인터럽트라 합니다.

 

명령어를 실행하려면 메모리에서 CPU로 가져와야 합니다.

이 과정을 인출 사이클,

인출한 명령어를 실행 시키는 것을 실행 사이클이라 합니다.

인출 사이클 실행 사이클

 

 

 

간접 주소 지정 방식과 같이 명령어를 인출하여 CPU로 가져왔다 하더라도 바로 실행할 수 없을 경우,

메모리 접근을 한 번 더 진행하는 간접 사이클이 있을 수 있습니다.

 

 

 

인터럽트

인터럽트란 CPU의 작업을 잠시 중단하는 상황인데요.

지금 처리해야 할 일 보다 더 우선시되야하는 일이 생겼을 경우입니다.

 

 

동기 인터럽트

동기 인터럽트는 인터럽트 중에서도 CPU에 의해 발생하는 인터럽트이며,

CPU가 명령 수행 중 예상치 못한 상황을 마주쳤을 때 발생하비다.

흔히 예외 (Exception) 이라 부릅니다.

 

비동기 인터럽트

비동기 인터럽트는 하드웨어 인터럽트라고도 하며,

주로 입출력 장치에 의해 발생됩니다.

 

입출력장치는 CPU 보다 속도가 느려

CPU는 입출력 장치의 결과를 바로 받아볼 수 없습니다.

때문에 주기적으로 입출력장치의 완료 여부를 체크해야 하는 일이 있을 수 있는데,

하드웨어 인터럽트를 사용하면 입출력장치의 완료 인터럽트를 받을 때 까지 다른 일을 하다가,

인터럽트가 발생하면 그때 입출력장치의 결과를 처리하는 것입니다.

 

프로그래밍에 비유하자면 리액티브 프로그래밍과도 비슷하다고 할 수 있는데,

주체가 다른 객체의 상태를 주기적으로 확인하여 변경 여부를 감지하는 것이 아닌,

객체의 상태가 변화하면 주체에게 연락을 주는 옵저버 패턴을 떠올리면 쉬울 것 같습니다.

 

일상에 비유하자면

우편배달부가 우편을 배달했는지 1시간마다 우체통을 확인하는 경우와,

우편배달부가 우편을 배달하면 알림톡을 전송해주는 경우로 생각하면 될 것 같아요.

 

 

 

 

CPU 성능 향상 기법

먼저 용어에 대해 알아봅시다.

 

 

사실 이 이미지 하나면 되긴 함

 

 

 

 

클럭은 위에서 말했듯이 컴퓨터 부품들이 움직이는 신호입니다.

헬스장에서 발라드를 듣는 것 보다 전투력 상승 힙합을 듣는 것이 더 잘되듯이 (농담입니다)

클럭 주기가 빠를수록 부품들은 더 빠른 박자로 일을 합니다.

 

코어는 일반적으로 명령어를 실행하는 부품을 의미합니다.

다나와 등에서 조립식 컴퓨터를 사신 분들 혹은 CPU 사양을 보신 분들은

'듀얼코어', '쿼드코어' 등의 용어를 보신 적이 있을 겁니다.

이는 '명령어를 실행하는 부품'이 2개, 4개인 것을 의미하며,

일하는 노예가 여러명 있는 것과 비슷합니다.

듀얼코어, 쿼드코어 등 복수개의 코어를 멀티코어 CPU라 부릅니다.

 

 

스레드란 '실행 흐름의 단위'로써 프로그래밍을 하신 분들이라면 꽤나 친숙하실 겁니다.

다만, '하드웨어적 스레드'와 '소프트웨어적 스레드'는 다른 개념입니다.

 

하드웨어적 스레드

하드웨어적 스레드는 '하나의 코어가 동시에 처리하는 명령어 단위'로써,

위와 같이 2코어 4스레드 CPU는

코어 두 개로 한 번의 4개의 명령을 실행합니다.

이와 같이 하나의 코어가 여러 명령어를 동시에 실행하는 것을 멀티스레드 CPU라 합니다.

 

 

소프트웨어적 스레드

프로그래밍 언어를 공부하셨던 분들에게는 꽤나 익숙할 소프트웨어 스레드입니다.

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

병렬성을 사용해 동시성을 구현할 때 쓰입니다.

 

 

 

 

끝나기 전에 한 번 더 보고 한 번 더 이해하기

 

 

 

 

명령어 병렬 처리 기법

명령어 파이프라인

명령어 처리 과정을 클럭 단위로 나누면 아래와 같습니다.

1. 명령어 인출

2. 명령어 해석

3. 명령어 실행

4. 결과 저장

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

즉 위 그림에서 t1은 해석/인출을, t2에서는 실행 / 해석/ 인출을 동시에 할 수 있는 것이지요.

이와 같이 공장 생산 라인과 같은 기법을 명령어 파이프라이닝이라 합니다.

파이프라인은 높은 성능을 발휘하나, 만능은 아닙니다.

 

데이터 위협

데이터 위험은 각 명령어간의 '데이터 의존성'에 의해 발생합니다.

일을 처리하기 위해 그 전에 먼저 끝내야하는 일이 있는 경우가 종종 있습니다.

라면을 끓일 때 면과 스프를 넣기 전에 물을 먼저 끓여야 하는 것처럼요.

이 처럼 명령어 1을 수행해야만 명령어 2를 수행해야 하는 경우가 있으며,

이 경우 명령어 2는 명령어 1에 의존적이라고 합니다.

의존적인 두 명령어를 무작정 동시 실행할 때 발생하는 위험을 데이터 위험이라 합니다.

 

제어 위험

반면에 제어 위험은 '프로그램 카운터의 갑작스러운 변화'로 발생합니다.

 

프로그램 카운터는 일반적으로 '현재 실행 중인 명령어의 다음 주소'로 갱신되나,

프로그램 실행 흐름이 바뀌어 명령어가 실행되며 프로그램 카운터 값에 변화가 생긴다면?

명령어 파이프라인에서 미리 처리중이였던 명령어들은 아무 소용 없어집니다.

 

구조적 위험

구조적 위험은 명령어들을 겹쳐 실행하는 과정에서

서로 다른 명령어가 동시에 같은 CPU 부품을 사용하려 할 때 발생합니다.

 

 

 

슈퍼스칼라

 

앞서 말한 파이프라인을 통해 한 번에 여러 명령어를 처리할 수 있습니다.

그리고 현대의 CPU는 이런 파이프라인을 여러 개 사용하는 기법인 슈퍼 스칼라를 사용해

동시에 여러 명령어를 인출/실행할 수 있습니다.

 

 

 

비순차적 명령어 처리

'비순차적' 이라는 이름에서 알 수 있듯이

비순차적 명령어 처리 기법은 명령어를 순차적으로 실행하지 않는 기법입니다.

 

 

앞서 언급한 기법들은 모두 순차적 처리를 고려한 기법입니다.

 

 

 

3번 명령어를 실행하기 위해서는  M(100), M(101) 의 값이 확정된 후,

즉 1, 2번 명령어가 완전이 끝난 후에 인출이 시작합니다.

 

때문에 명령어 파이프라인의 장점 중 하나인 "각 단계를 동시에 실행한다" 라는 장점을 사용할 수 없게 됩니다.

하지만, 4, 5, 6번 명령어는 어떤가요?

1~3번의 명령어와 크게 관련이 없습니다.

그럼, 4~6번 명령어를 먼저 실행하며 3번 명령어를 뒤로 미루면?

 

명령어 파이프라인 기법으로 4~6번 명령어를 실행하며 3번 명령어를 동시에 실행할 수 있게 됩니다!!!

 

 

CISC와 RISC

명령어 집합

세상에는 많은 CPU 제조사가 있습니다.

CPU마다 기능과 성능, 모양 심지어 명령어까지 다릅니다.

인텔의 CPU는 x86, x86-64 ISA를, 아이폰의 CPU는 ARM ISA를 이해합니다.

이 두 CPU는 서로의 명령어를 이해할 수 없어

아이폰의 CPU의 명령어를 그대로 인텔의 CPU에 준다면, 이해하지 못합니다.

 

 

동일한 소스 코드를 작성하여도, 각 컴퓨터가 이해할 수 있는 어셈블리어로 컴파일되기에

위와 같이 서로 상이한 코드로 컴파일된 결과를 얻습니다.

ISA는 일종의 CPU 언어인 셈이지요.

서로 다른 ISA를 사용하는 CPU끼리는 서로가 서로의 언어를 이해할 수 없습니다.

 

ISA는 CPU의 언어이자,

하드웨어가 소프트웨어를 어떻게 이해할지에 대한 약속입니다.

때문에 ISA가 달라지면 레지스터 종류와 개수, 명령어 해석 방식, 메로리 관리 방법 등 많은게 달라집니다.

 

 

언어가 사고를 지배한다

 

한 사람이 세상을 이해하는 방법과 행동이 그 사람이 쓰는 언어의 문법적 체계와 관련이 있다는...

사실 무슨 의미인지 잘은 모릅니다.

그냥 여기 인용문 하나 넣으면 멋있을 것 같아서

어디서 주워들은 그럴듯한 말 가져와봤습니다.

 

가설이긴 하나, 적어도 프로그래밍 언어에서는 어느정도 맞는 것 같습니다.

 

 

 

CISC

CISC(Complex Instruction Set Computer)는

복잡한 명령어 집합을 활용하는 컴퓨터 정도로 해석할 수 있을 것 같습니다.

x86, x86-64 등이 대표적인 CSIC ISA 입니다.

 

CISC는 다양하고 강력한 기능의 명령어 집합을 사용하기에 가변 길이 명령어를 활용합니다.

상대적으로 적은 수의 명령어로도 프로그램을 실행할 수 있기 때문에

메모리를 아껴 개발해야 할 시절에는 인기가 좋았습니다.

 

하지만, 명령어가 워낙 복잡하고 다양하다보니

명령어의 크기와 실행되기까지의 시간이 일정하지 않습니다.

 

때문에 복잡하고 다양한 명령어를 활용할 수 있긴 하지만,

사실 복잡한 명령어의 사용 빈도는 낮습니다.

 

 

 

RISC

RISC(Reducced Instruction Set Computer)는 CISC에 비해 명령어 종류가 적습니다.

짧고 규격화되어 있으며 되도록 1클럭 내외로 실행되는 것을 지향하죠.

즉, 고정 길이 명령어라고 할 수 있습니다.

 

 

 

숙제

p. 125의 확인 문제 2플래그 레지스터 : 연산 결과 혹은 CPU 상태에 대한 부가 정보를 저장하는 레지스터

프로그램 카운터 : 메모리에서 가져올 명령어의 주소를 저장하는 레지스터

범용 레지스터 : 데이터와 주소를 모두 저장할 수 있는 레지스터

명령어 레지스터 : 해석할 명령어를 저장하는 레지스터

 

p. 155의 확인 문제 4번

코어

 

Ch.05(05-1) 코어와 스레드, 멀티 코어와 멀티 스레드의 개념을 정리하기

본문 내용으로 대체

 

 

 

마치며

1~3 챕터에 비해 매워지긴 했으나,

그래도 한 번 배웠던 내용이였기에 그리 어렵지는 않았던 것 같습니다.

엄청 큰 빠따를 든 채 기다리고 있을 후반부 챕터가 걱정되지만...

profile

Uknow's Lab.

@유노 Uknow

인생은 Byte와 Double 사이 Char다. 아무말이나 해봤습니다.