컴퓨터는 기본적으로 메모리 계층 구조를 가지는데, CPU - 캐시 - 메인 메모리 - 디스크 순서로 처리 속도가 빠르다. 실제 파일 등의 데이터는 물리적인 디스크 안에 저장이 되어 있는데, 컴퓨터를 뜯어보면 알 수 있다시피 하드 디스크는 일종의 레코드판과 같은 구조를 가지고 있다. 어떤 파일에 대해 읽기/쓰기 작업을 수행하려면 디스크 암(Arm)이 찾고자 하는 파일이 위치한 섹터가 위치한 실린더로 헤드를 움직여야 하기 때문에 탐색 시간(Seek time)이 소요되며, 디스크 자체도 회전을 하면서 필요한 섹터를 그 헤드에 위치시켜야 하므로 회전 지연(Rotation delay)이 발생한다. 게다가 디스크로부터 읽어들인 데이터를 운영체제 측에 넘겨주어야 하므로 전송 지연(Transfer delay)도 또한 발생한다.
따라서 요약을 하면 디스크에 대한 접근시간(Access time)은 다음과 같이 나타낼 수 있다.
Access time = Seek time + Rotation delay + Transfer delay즉, 수많은 연산을 처리하기 위해서 이렇게 매번 디스크에 접근을 한다면 매우 비효율적이다. 따라서 컴퓨터는 내부적으로 더 빠른 장치로 데이터를 옮겨서 처리하려는 경향이 있다. 이러한 과정을 흔히 캐싱(Caching)이라고 한다. 물리 디스크에 있는 데이터를 메인 메모리에 올리고, 그 메인 메모리에 있는 데이터를 캐시로 불러와서 처리하는 식의 과정을 거친다. 하드웨어의 성능에 있어서 위 그림의 higher level로 갈수록 속도가 비약적으로 증가하기 때문에 소프트웨어의 관점에서도 알고리즘이나 프로그램을 짤 때 '캐시 활용률'을 중요하게 생각한다.
CPU core의 내부에는 심지어 메인 메모리와 캐시보다 더 빠른 하드웨어가 내장되어 있는데, 그것이 바로 레지스터 파일(Register file)이다. 제조사마다 다르지만 MIPS CPU의 경우, 이 Register file은 32 bit 워드 체계를 기준으로 32 bit 짜리 레지스터(Register) 32개와 PC(Program Counter)로 이루어져 있다. 각각의 Register는 32 bit 짜리 데이터를 담을 수 있는 일종의 저장소이며, 산술이나 논리 연산 등 아주 간단한 연산을 할 때 활용된다. 처리속도가 매우 빠르기 때문에 컴파일러(Compiler)가 프로그램을 컴파일할 때 이 Register들을 적극적으로 활용한다. 조사한 바에 따르면, 각 저장 장치들에 대한 access time을 CPU의 cycle 수로 측정했을 때 대략적으로 다음과 같은 수치가 나온다고 한다.
1 cycle to read a register그리고 instruction들을 수행할 때도 cycle을 매우 적게 잡아먹는다. MIPS의 CPU는 다음과 같이 거의 3~5 cycles 정도가 소모된다고 한다.
4 cycles to reach to L1 cache
10 cycles to reach L2 cache
75 cycles to reach L3 cache
200 cycles to reach main memory
Load (5 cycles)
Store (4 cycles)
R-type (4 cycles)
Branch (3 cycles)
Jump (3 cycles)
Register file의 구조는 위의 그림과 같이 생겼다. 주소를 통과시키는 선은 5 bit, 그리고 데이터를 통과시키는 선은 32 bit를 사용하는데, 디코더(Decoder)를 떠올려보면, 5 bit로 32개의 decimal number를 가리킬 수 있기 때문이다. 즉 src1 addr, src2 addr, dst addr은 모두 Register의 number를 가리킨다. 흔히 instruction을 수행할 때 "몇 번 레지스터에 있는 값을 불러와서 연산을 하고 몇 번 레지스터에 저장해라~"라는 식으로 진행이 되기 때문에 이렇게 Register number로 indexing을 하면 매우 편리하다.
이 Register file을 Verilog 코드로 간단하게 구현하면 다음과 같다.
module regfile(input clk,
input we,
input [4:0] ra1, ra2, wa,
input [31:0] wd,
output [31:0] rd1, rd2);
reg [31:0] rf[31:0];
// three ported register file
// read two ports combinationally
// write third port on rising edge of clock
// register 0 hardwired to 0
always @(posedge clk)
if (we) rf[wa] <= wd;
assign rd1 = (ra1 != 0) ? rf[ra1] : 0;
assign rd2 = (ra2 != 0) ? rf[ra2] : 0;
endmodule
Computer Organization and Design by David Patterson and John Hennessy, 5th edition, Morgan Kaufmann, 2013
Lecture 4. MIPS & MIPS Instructions #1, Prof. Taeweon Suh, Computer Science & Engineering, Korea University
댓글 없음:
댓글 쓰기