한 권으로 읽는 컴퓨터 구조와 프로그래밍 - 4장

Jajuna_99·2022년 12월 8일
0

4장 '컴퓨터 내부 구조', 컴퓨터 하드웨어는 어떻게 구성되는가

현대 컴퓨터는 크게 메모리, 입출력, CPU 세 가지 부분으로 나눌 수 있다. 이번 장에서는 이들이 어떻게 연관되는지 알아본다.

메모리

컴퓨터에는 조작할 비트들을 저장할 장소가 필요하고 이 장소를 메모리라고 부른다.

메모리는 집이 빈틈없이 늘어선 거리와 같다. 집 크기는 모두 같고 정해진 개수 만큼 비트를 저장할 수 있는 방이 있다. (보통 1바이트를 저장)

그리고 이 집마다 주소(address)가 부여된다. 예를 들어 컴퓨터 메모리 크기가 64MiB라면, 전체는 64×1,024×1,024=67,108,86464 \times 1,024 \times 1,024 = 67,108,864 바이트를 저장할 수 있는 집이 있는 것이다.

메모리의 기본 단위가 바이트라고 꼭 바이트 단위로만 읽어야 한다는 것은 아니다. 32비트 컴퓨터는 메모리를 4바이트로, 64비트 컴퓨터는 8바이트 덩어리로 구성한다. (이는 4차선 도로, 8차선 도로를 이용하는 것과 비슷하다. 메모리 단위가 클수록 버스에 더 많이 실고 더 많은 양의 데이터를 처리할 수 있다.)

포플렉스(fourplex), 듀플렉스(duplex), 유닛(unit)에 대해 각각 긴 워드 주소, 워드 주소, 바이트 주소에 빗대어 설명하는 그림을 보면 더 이해가 쉬울 것이다. (p.167)
ex) 정렬이 맞지 않는 접근 (nonaligned access)

메모리 종류에는 3장에서 본 것 같이 여러 가지가 있다. 서로 가성비(가격/성능 비율, price/performance ratio)가 다르다.
ex) SRAMP은 고속도로 근처의 고급 부유층 마을처럼 빠르고 비싸다. 디스크는 저렴하지만 느려서 마치 비포장 도로와도 같다.

사용하는 프로세서에 따라 메모리 버스에 데이터를 싣는 순서가 달라진다. (p.168)에 엔디안(endian) 참고

유닉스 운영체제를 다른 컴퓨터로 포팅 할때 위에 말한 데이터 순서를 염두하지 않고 포팅해서 데이터 순서가 바뀌어 "Unix"를 "nUxi"로 출력한 사건을 눅시 신드롬(nuxi syndrome)이라고 우스꽝스럽게 부르기도 한다.

입력과 출력

입력/출력(input/output, I/O) : 컴퓨터에 정보를 전달하거나 정보를 가져오는 방법을 통칭하는 단어, I/O에 연결되는 장치를 I/O 장치(I/O device, peripheral device)라고 한다.

컴퓨터가 물리적으로 큰 과거에는 전기적 연결이 한정적인 작은 패키지에 모든 것을 욱여넣기 힘들었기 때문에 I/O와 메모리 버스 경로를 분리하는 것이 타당했다. 또한 메모리가(집이) 많지 않았기 때문에 제한된 주소를 I/O를 지원하느라 낭비하는 것은 바람직하지 않았다.

요즘의 컴퓨터는 메모리가 훨씬 많아졌고, 모든 주소에 메모리가 있지 않게 됐다. (빈 주소가 많아졌다는 뜻) 때문에 이 메모리들을 I/O 장치에 할당하는 것이 더 타당해졌다.

그리고 더 많은 부분을 연결이 한정적인 패키지에 구겨 넣어야 하기 때문에 I/O와 메모리가 같은 버스를 사용하는 것이 타당하다. (p.169 그림 참고)

중앙 처리 장치

중앙 처리 장치(CPU, Central Process Unit) : 실제 계산을 처리하는 컴퓨터 부품

산술 논리 장치

산술 논리 장치(arithmetic logic unit, ALU) : CPU의 핵심 부품으로, 산술 계산, 불리언 대수 및 기타 연산을 수행하는 장치이다.

간단하게 내 맘대로 (p.170) 그림을 수식화 해보면

ALU(피연산자A+피연산자B+연산코드)=결과,조건코드ALU(피연산자 A + 피연산자 B + 연산코드) = 결과, 조건코드 느낌이다.

  • 피연산자 (operand) : 수를 표현하는 비트
  • 연산코드 (operation code, opcode) : 피연산자에 대해 ALU가 어떤 연산자를 적용할지 지정
  • 조건코드 (condition code) : 결과에 대한 추가 정보가 들어간다. 조건 코드 레지스터에 저장된다.

ALU 명령코드에 대한 도표 (p.171)

ALU는 앞절에서 배운 실렉터와 논리 게이트들을 복잡하게 연결한 것일 뿐이다. (ALU의 내부의 일부분 스키매틱 p.172)

시프트

시프트 또한 명령코드 중 하나지만, 시스프 명령어를 제외한 ALU의 모든 기능은 조합 논리로 구현할 수 있다.

시프트 레지스터는 클록에 따라 내용을 1비트씩 시프트하는 플립플롭을 사용해 만들 수 있다. 오버플로우 여부는 조건 레지스터에 OO비트에 저장한다.

순차적인 시프트 레지스터는 1비트를 시프트할 때 한 클록이 필요하기 때문에 느리다. 그래서 실렉터와 조합 논리를 사용하는 배럴 시프터(barrel shifter)를 사용하면 이 문제를 해결할 수 있다.

시프터는 부동소수점 연산을 구현할 때도 핵심 부품이다. 두 피연산자의 가수를 지수에 따라 시프트함으로써 소수점을 정렬한 다음 서로 더하거나 뺄 수 있다.

실행 장치

실행 장치(execution unit, control unit) : 메모리의 정해진 장소에서 명령코드와 피연산자들을 가져와서 ALU에게 어떤 연산을 수행할지 알려주고, 결과를 메모리에 돌려준다.

우리는 실행 장치에게 명령어 목록을 제공한다. 명령어 예시로는 '주소 10에 있는 수를 주소 12에 있는 수와 더해서 결과를 주소 14에 넣어라."

실행장치는 메모리에서 이러한 명령어 목록을 찾을 수 있고, 이처럼 실행되는 컴퓨터를 프로그램 저장 방식 컴퓨터(stored-program computer)라고 한다.

명령어 : 컴퓨터에게 어떤 일을 할지 알려주는 비트 패턴, 명령의 비트 패턴은 CPU마다 고유한 설계에 속한다.

실행장치는 프로그램 카운터(program counter, pc)를 사용해 메모리에서 명령어를 가져와야할 위치를 알 수 있다. PC는 현재 위치를 알려주는 카운터로 이루어진 레지스터이다.

명령어 집합

명령어

DRAM 주소 지정 기법을 활용한 주소 확장 레지스터(address extension register)를 두고 별도의 명령어를 사용해 상위 주소를 지정한다.

이 방법은 32비트 CPU를 사용해 4GiB 이상의 메모리에 접근할 때 사용했던 방법이다. 인텔은 이를 PAE(pyhsical address extension)라고 불렀다.

하지만 이는 명령을 수행하는 회로를 아주 복잡하게 하고, 게다가 한 번에 한 주소에만 접근하면 좀 더 많은 비트를 주소에 활용할 수 있다.

레지스터 버스에 다른 메모리를 추가하면 이를 해결할 수 있고, 이 레지스터를 누산기(accumulator)라고 한다.

주소 지정 모드

누산기를 사용하면 12비트를 주소 지정에 쓸 수 있고, 여전히 사용 가능한 주소가 충분하지 않다. 이런 방식을 주소를ㄹ 가리키는 경우를 직접 주소 지정(direct addressing)이라고 부른다. 이 말은 사용할 주소가 명령어에 직접 들어가 있다는 뜻이다.

간점 주소 지정(indirect addressing)을 추가하면 더 많은 메모리를 사용할 수 있다. 여기서 CPU는 명령어에 들어 있는 값을 피연산자 주소로 해석하지 많고, 피연산자 주소를 얻을 수 있는 메모리 위치를 가리키는 주소로 사용한다.

위 2 가지 주소 지정 모드 만으로도 메모리를 다루기에는 충분하지만 상수를 지정할 때는 특별한 방식이 필요한다. 즉시 주소 지정 모드(immediate addressing mode)라는 또 다른 주소 지정 모드를 추가할 수 있다. 이 경우 주소에 해당하는 비트를 그냥 값으로 간주한다.

조건 코드 명령어

조건 코드를 원하는 값으로 설정하거나, 조건 코드의 값을 살펴볼 수 있는 방법으로 조건 코드 레지스터의 값을 누산기로 복사하는 cca 명령어와 누산기의 값을 조건 코드 레지스터에 복사라는 acc라는 명령어를 추가할 수 있다.

분기 명령어

명령어를 처음부터 끝까지 순서대로 수행하는 방법 대신 의사결정을 내리고 코드 중 일부를 선택적으로 실행할 수 있는 프로그램을 위해 분기(branch)명령어가 있고 이 명령어는 프로그램 카운터의 값을 변경할 수 있는 명령어가 필요하다.

분기 명령어 조건 (p.181)

최종 명령어 집합 구성

이렇게 명령어를 최종 종합해보면 모드, 명령코드, 주소 3가지를 할당할 수있는 명령어 집합이 완성된다.

각 주소 지정 모드와 명령코드(p.182) 피보나치 수열을 계산하는 기계어 프로그램(p.183)이 도표로 잘 정리되어 있다.

마지막 설계

지금까지 본 모든 부분을 함께 작동 시키는 컴퓨터로 만들려면 '접착제'에 해당하는 요소가 필요하다.

명령어 레지스터

페치(fatch)로 명령어를 갖고 오고 나면, 명령어를 처리해야 할 때 메모리를 사용할 때 페치한 명령에 편한게 접근할 수 있도록 저장할 다른 위치가 필요하다.

이를 위해 명령어 레지스터(instruction register)를 추가해 현재 실행 중인 명령어를 저장한다. (p.184)

데이터 경로와 제어 신호

PC 값과 메모리 주소 버스에 넣을 방법과 메모리에 있는 데이터를 명령어 레스터로 넣을 방법이 필요하고 여러 명령어 집합을 구현하는 데 필요한 모든 연결을 결정해야 한다. 결과적으로 (p.185 그림)과 같은 형태가 되고, 앞에서 살펴본 여러 레지스터, 실렉터, ALU, 트라이스테이트 버퍼 등이 있다.

그림을 보면 간접 주소 레지스터(indirect address register)가 추가 됐는데, 이는 간접 주소 지정을 사용할 때 메모리에서 읽어온 주소를 어딘가에 저장해야 하기 때문이다.

데이터 흐름 제어

페치와 실행에 여러 단계가 필요하므로 각 단계를 추적할 카운터(즉, 신호등과 같은 것이)가 필요하다. 이 카운터의 내용과 명령의 명령코드와 모드 부분이 제어 신호를 결정한다.

가장 복잡한 연산의 경우 3단계 밖에 안돼 카운터는 2비트 카운터를 사용한다.(p.187 그림 참고)

그림의 큰 박스는 랜덤 논리(random logic)이라고 돼 있는것을 볼 수 있는데, 지금까지 살펴본 논리 다이어그램은 일반적인 패턴을 따르지만, 여기서 구현하려는 교통 제어 장치처럼 복잡한 구조를 구현하는 경우 정해진 개수의 입력이 있고 이 입력들을 정해진 개수의 출력에 연관시켜야 하느데 출력에 어떤 규칙성이 없어 보여 붙여진 이름이다.

다른 방법으로 교통 제어 장치를 구현할 수도 있다.

랜던 논리 대신 적당한 크기의 메모리를 사용하는 것이다. 카운터의 출려과 명령어의 명령코드와 주소 지정 모드 부분을 메모리 주소에 연결하는 방법이다.

그리고 이런 식으로 구현하는 방법을 마이크로코드를 썻다.라고 한다. (p.189 참고)

RISC와 CISC 명령어 집합

위처럼 유용한 컴퓨터 명령어르 만들어냈지만 컴퓨터 제어 회로도 복잡해졌다. 그리고 복잡한 명령어 중 상당수는 거의 쓰이지 않는다는 사실을 알아냈다.

이런 기계에서는 복잡한 명령어를 단순한 명령어를 조합해 처리하고 이를 RISC(reduced instruction set computer)라고 한다. 그리고 기존 설계 방식으로 만든 컴퓨터를 CISC(complicated instruction set computer)라고 한다.

이 컴퓨터들의 발전 현황은 (p.190-191)에 잘 정리 돼 있다.

GPU

그래픽 처리는 아주 특화된 작업이고 일반적인 용도에 사용할 CPU가 제공하는 모든 기능을 필요로 하지 않는다. 그리고 그래픽을 처리하려면 메모리에 접근해야 하는 횟수도 엄청나게 늘어난다. 그래서 여러 점을 동시에 찍을 수 있는 즉, 병렬화(parallelize)작업에 특화된 GPU(graphics processing unit)을 사용한다.

GPU를 CPU와 구분짓는 2가지 특징이 있다. 첫째, GPU에는 간단한 처리 장치가 아주 많이 들어 있따. 둘째, GPU는 CPU보다 메모리 버스의 폭이 더 넓다. 이로 인해 메모리에 더 빠르게 많은 양을 접근할 수 있다.

이러한 병렬 계산에 특화된 GPU는 여러 응용 분야(공학 계산, 인공지능 등)에 쓰기에 적합한 것이다.

정리

컴퓨터는 생각보다도 훨씬 복잡하게 설계되어 있다. 하지만 현재 극도로 추상화 된 컴퓨터를 그대로 사용하기보단, 컴퓨터를 공부하기로 했다면 이렇게 깊게 들여다 볼 필요가 있다.

profile
Learning bunch, mostly computer and language

0개의 댓글