[컴퓨터구조 2주차] 컴퓨터의 구성과 성능
Sep 9(Tue)
컴퓨터의 구성
우리 주변의 컴퓨터는 정말 다양하게 존재한다. 데스크톱이나 스마트폰, 노트북등의 PC(Personal Computers), 공학과 예측 분야에서 쓰이는 Super Computers, 네트워크 기반의 Server Computers, 그 외에 가전 제품들에 베이스로 깔려 있는 Embedded Computers까지 정말 다양하다. 그런데 왜 이렇게 컴퓨터 시스템이 널리 쓰일까?
컴퓨터의 핵심인 본체에는 마더보드(Motherboard)로 연결된 중앙처리장치(CPU), 계산을 위한 GPU, 메모리인 DRAMs과 SSDs(혹은 HDD)가 들어 있다. 출력 장치인 화면(Display)과 스피커(Speaker) 등도 있다.
이중 컴퓨터구조 과목에서 집중적으로 볼 것은 CPU와 Memory이다. 제어와 데이터의 흐름을 볼 것이다.
폰 노이만 구조(Von Neumann Architecture)
컴퓨터는 항상 같은 workflow로 동작한다. 이를 폰 노이만 구조(Von Neumann Architecture)라 하는데, 어떻게 CPU와 Memory가 상호작용하는지를 나타내는 도식이다.
처리 장치인 CPU와 저장 장치인 Memory 사이에는 데이터(data)와 명령어(instruction)가 오간다. 주소는 데이터를 접근(access) 및 할당(allocate)하게 도와주고, 명령어는 데이터에 관한 실행(execute)을 지시한다.
조금 더 자세히 말하면, 데이터(data)와 산술/논리 명령(operations) 및 제어(control)가 돌아다닌다.
처리장치의 발전
요즘은 마이크로프로세서(Microprocessor)라고 해서 정말 작은 반도체 칩 하나가 CPU 역할을 해내기 시작했다. 과거 4bit였던 코어가 어느새 64bit까지 왔다는 것은 격세지감이다(물론 내가 느끼진 못하지만..)
무어의 법칙(The Moore’s Law)에 따르면 격년마다 칩의 성능은 2배씩 는다고 한다. 트랜지스터를 더 집약적으로 박기 때문이다. 물론 한계는 있기에 점점 그 성장이 정체중이지만, 현재의 집약도는 밀도를 유지한 채 부피를 키운다는 조건 하에 출력 밀도가 가히 원전에 필적한다.
빠른 처리는 집약적인 밀도 이외에도 병렬 처리(Parallelism)가 한 몫을 하고 있다. 명령어에 동기(동시성)를 맞추는 ILP, 데이터에 맞추는 DLP, 작업에 맞추는 TLP 등 종류는 다양하지만 그 역량은 대단하다.
병렬 처리와 함께 코어도 멀티코어로 발전하기 시작했는데, ILP Wall과 Memory Wall(CPU에 비해 메모리의 접근 속도가 현저히 느려서 발생하는 문제), Power Wall 등의 한계도 존재한다.
명령어(Instructions)
한편 폰 노이만 구조에서 명령어는 저수준언어로 구성되어야 한다. 데이터의 흐름은 곧 전기신호이기에 0과 1로 되어있기 때문. 이렇게 SW와 HW를 연결하는 명령어의 집합을 ISA(Instruction Set Architecture)라 하는데, 일상에서는 ISA를 고려할 필요가 없다. 컴파일러가 다 알아서 변환해주기 때문이다.
intro의 결론
결론적으로 우리는 컴퓨터 구조를 대충 알고만 있어도 큰 문제는 없다. 이미 embedded된 시스템이 알아서 처리해주기 때문.
그러나! 더 나은 프로그램을 작성하고 싶거나, 다른 인터페이스나 구조에서 문제의 원인을 찾고 싶다면? 컴퓨터 구조를 알아야 한다. 아무리 고수준의 언어로 프로그램을 짜더라도, 프로세서에서 0/1 변환이 안 되면 말짱 도루묵이다. 열심히 해보자!
컴퓨터 구조에서 배울 Topic 3가지
- How to Design Interface?
- How to Implement?
- What about the Memory?
Sep 11(Thu)
시간: 컴퓨터의 성능 판단 기준
SW는 MIPS나 GFLOPS/s, HW는 CPI나 GHz로 성능을 평가할 수 있다. 결국 중요한 건 시간이다. 처리 시간이 얼마나 짧고 빠른가? 이게 성능을 판단하는 기준이 된다.
따라서 성능은 처리 시간(execution time)의 역수로 생각할 수 있다. 더 짧은 시간이 걸릴 수록, 성능은 좋은 것이기 때문이다. 그랬을 때 X에 대한 Y의 성능은 다음과 같이 생각해볼 수 있다.
\[n=\frac{\text{Performance}_X}{\text{Performance}_Y}=\frac{\text{Execution time}_Y}{\text{Execution time}_X}\]줄어든 처리 시간은 성능의 개선을 의미한다. 예를 들어 하나의 작업을 처리하는데 X는 5ms, Y는 10ms가 걸린다면, 이전 공식에 따라 X의 성능은 200, Y의 성능은 100으로 X가 Y보다 2배의 성능을 갖고 있는 것이다.
클럭 주기 vs 클럭 속도
하드웨어에서 0이 1로 바뀌었다가(positive edge) 다시 0으로 바뀔 때까지(negative edge)의 주기를 Clock Cycle Time(클럭 주기)라고 한다. 주기가 길다는 것은 0과 1간의 변환이 느리므로, 처리속도가 느리고 처리시간이 길어짐을 의미한다.
이의 역수에 해당하는 개념이 Clock Rate(Frequency)(클럭 속도)이다. 보통 Hz를 위시한 MHz, GHz와 같은 헤르츠로 단위를 표시한다.
logic design에서 순차논리는 상태에 따라 input에 따른 output이 바뀌지만, 조합논리는 상태와 무관하게 input에 따른 output이 정해져있다. 순차논리는 데이터를 입력 받고 업데이트하는데 쓰이고, 조합논리는 데이터를 계산하는 데 쓰이는데, 보통 조합논리가 시간을 가장 많이 차지한다.
이 정보입력(1, 순차논리)->계산(2, 조합논리)->업데이트(3, 순차논리)의 주기가 클럭 주기 안에 끝나야 프로그램이 빠르게 동장하는데, 이중 2번 계산의 시간을 longest propagation delay(critical path delay)라고 한다. 전파 지연은 1, 2, 3번 과정에서 모두 발생하는데, 그중 2번 과정이 가장 길기 때문에 이렇게 표현하는 듯 하다.
다시 처리시간으로 돌아오자면, 한 프로그램에 대한 처리시간은 프로그램을 돌리는 데 필요한 사이클의 수와 각 사이클의 시간을 곱하면 알 수 있다. 즉
\[\text{(Execution time)}=\text{(Clock cycles for program)}\times \text{(Clock cycle time)}\]그런데 클럭 주기는 클럭 속도로도 변환이 가능하므로
\[\text{(Execution time)}=\frac{\text{(Clock cycles for program)}}{\text{(Clock rate)}}\]또한 프로그램당이라는 기준은 직관적이지도 못하고, 쉽게 알아내기도 어렵다. 따라서 명령어 단위로 파헤쳐서 해석할 수 있는데, 이는
\[\text{(Execution time)}=\text{(# of Instructions)}\times \text{CPI}\times \text{(Clock cycle time)}\]라고 해석할 수 있다. 어? #가 numbers인 것은 알겠는데 CPI는 뭐지?
CPI(Cycles Per Instruction)
CPI는 명령어 하나를 처리하는데 걸리는 사이클의 평균 횟수를 의미한다. 폰 노이만 구조에서 모든 workflow는 폰 노이만 구조를 따르기에, data와 address가 오가는 상황은 모두 명령어로 이루어진다. 따라서 데이터의 흐름이나 산술/논리적 계산, 제어 및 전송 등을 담당하는 명령어를 기준으로하는 CPI는 아주 강력한 기준이 된다!
상술한 등식들을 통해 성능이 좋으려면(처리 시간이 낮으려면) 다음 조건들이 해당돼야함을 알 수 있다.
Execution time을 낮추기 위해선?
- 높은 clock frequency(rate)(엔지니어가 정하기 어려움)
- 낮은 clock cycle time(역시 엔지니어가 정하기 어려움)
- 프로그램을 적은 명령어로 구성
- CPI(명령어 하나에 걸리는 사이클)를 줄임
여기서 CPI를 줄이는 것, 그리고 명령어 수를 줄이는 것이 가장 쉬운 방법임을 알 수 있다. 그런데 CPI 하나만을 건드린다고 모든 것이 해결될까?
보면 알겠지만 Instruction Count를 줄이기 위해서는 program 말고도 컴파일러와 ISA도 조정을 해야한다. 컴파일러의 성능도 높아야하고, ISA를 어떻게 디자인함에 따라서 명령어 수가 바뀌기 때문에 이 요인들도 신경써야한다.
비슷하게 CPI도 ISA와 하드웨어의 구조(Process Architecture; Organization)가 data movement의 횟수를 좌우하므로 CPI에 영향을 준다.
클럭 속도(clock rate) 역시 organization과 technology가 결부되어 있다. 따라서 간단히 생각할 문제는 아닌 듯 하다. 또한 명령어를 어떻게 설정하냐에 따라 속도가 바뀔 수 있다.
명령어에 대한 Trade-offs에 대한 것인데, (나중에 더 다루겠지만) 명령어에 병렬기능(여러가지 부가 기능)을 줄 경우 명령어의 수 자체는 줄지만, 명령어가 복잡해지면서 해당 명령어에 대한 사이클 수는 늘게 된다. 따라서 trade-offs가 발생하게 된다.
CPI Examples
Machine A는 1ns의 주기와 2.0의 CPI를 가지고, Machine B는 2ns의 주기와 1.2의 CPI를 가진다고 하자. 누가 더 빠른가?
CPI만 낮다고 좋은게 아니라고 말했다. 둘을 곱했을 때 A는 2.0, B는 2.4이므로 각 Machine이 같은 수의 명령어로 구성되어 있다고 하면 앞서 말한 \(\text{(Execution time)}=\text{(# of Instructions)}\times \text{CPI}\times \text{(Clock cycle time)}\)에 따라서 A가 B보다 1.2배 빠르다고 해석할 수 있다.
즉 CPI는 성능을 온전히 나타내지 못한다. CPI는 클럭 주기를 고려하지 않기 때문이다. CPI만으로 성능을 판단하는 것은 성급하다.
별개로, 명령어마다 CPI가 다르기 때문에 앞서 말하긴 했지만 CPI는 평균치를 사용한다. 평균 공식은 뭐 다음과 같이 당연하다.
\[CPI=\frac{\sum_{i=1}^n(CPI_i\times C_i)}{\text{(Total instruction count)}}\]계산하는 예는 아래의 사진을 참고하자
출처: 컴퓨터구조(COSE222) ㄱㅇㄱ 교수님