[컴퓨터 구조] 파이프라이닝

LeeJaeHoon·2022년 6월 8일
0

명령어 파이프라이닝

앞에서 배운 것처럼 컴퓨터는 클록에 맞추어 매 클록 마다 한 개씩의 명령을 실행한다. 서로 다른 명령어들은 서로 다른 개수의 단계를 밟으며 실행되므로 실행시간이 다를 수 있지만 클록의 주기는 일정해야 하므로 가장 긴 실행시간을 필요로 하는 명령의 실행 시간에 맞추어 실행된다. 즉 비효율성이 발생한다.

우리 예제에서는 ldr 명령이 가장 긴 실행시간을 필요로 한다. 즉 한 명령이 실행되려면 다음과 같이 5단계를 밟는다.

  1. IF (Instruction Fetch)
  2. ID (Instruction Decode) and register read
  3. EX (Execute) = ALU
  4. MEM (Memory Access)
  5. WB (Register Write Back)

이런 비효율성을 극복할 수 있는 한 가지 방법이 명령어 파이프라이닝 instruction pipelining 이다. 명령어 파이프라이닝은 명령이 실행되는데 소요되는 각 단계들을 중첩해서 여러 개의 단계들이 동시에 일어나도록 하는 방법이다.

스크린샷 2022-06-05 오후 9.42.40.png

명령어 파이프 라이닝을 적용하면 어느 정도의 성능 향상 speed up 을 얻을 수 있을까? 앞의 예제에서 본 것처럼 중첩되는 단계 stage 의 수 만큼 얻을 수 있다. 대학교의 경우 4년간을 중첩하므로 4배 빨라질 수 있고, 초등학교의 경우 6년간을 중첩하므로 6배 빨라질 수 있는 것이다.

주의해야 할 점은 명령어 파이프라이닝을 적용하더라도 한 개 명령을 실행하는데 소요되는 시간이 짧아지는 것은 아니다. 다만 단위 시간당 실행되는 명령어 개수가 증가하는 효과가 있다.

앞에서 ARM 프로세서는 프로그램 카운터 pc 의 값이 현재 실행 중인 명령의 주소보다 8바이트 더한 값이라고 말한 적이 있다. 명령어 길이가 4바이트이므로 pc 는 두 개 명령을 앞서 가고 있는 것이다. 이런 현상은 ARM 프로세서가 명령어 파이프라이닝을 적극 사용하고 있기 때문이다.

파이프라이닝을 위한 프로세서 설계

명령어 파이프라이닝을 적용하기 위해 가장 중요한 조건은 그림 13.1에 보인 것처럼 각 단계별 소요 시간이 동일해야 한다는 것이다. 대학교의 경우에도 각 학년 별 소요 기간은 1년으로 동일하기 때문에 중첩을 할 수 있다.

파이프라이닝 적용을 위해 프로세서는 다음과 같이 설계되고 있다.

  1. 모든 명령어의 길이는 동일하다. 명령어 길이가 다르다면 instruction fetch 에 소요되는 시간이 달라질 수 있다. 파이프라이닝 지원을 위해 instruction fetch 시간은 일정해야 하므로 최근의 프로세서는 모든 명령어 길이를 동일하게 맞추고 있다. ARM 의 경우 명령어 길이는 모두 32비트로 동일하다.
  2. load/store 구조를 따른다. 데이터 처리 명령에서 연산의 대상, 즉 오퍼랜드는 레지스터로 한정하며, 메모리에 있는 변수는 오퍼랜드가 될 수 없다. 빠른 속도의 레지스터에 비해 메모리를 오퍼랜드로 사용하면 실행 늦어질 수 있기 때문에 파이프라이닝의 조건인 일정 시간 조건을 만족시키지 못할 수 있기 때문이다.
  3. 메모리 데이터는 4의 배수 번지에 위치한다. 32비트 컴퓨터인 경우 ldr 등 명령을 사용하여 한 번에 4바이트의 데이터를 메모리에서 가져올 수 있는데, 만일 그 데이터가 4의 배수가 아닌 주소에 있다면 두 번에 걸쳐 가져와야 한다. 즉 데이터 위치에 따라 접근시간이 달라질 수 있으므로 파이프라이닝의 조건인 일정 시간 조건을 만족시키지 못할 수 있다. 이런 문제를 일으키지 않도록 메모리 데이터는 항상 4의 배수 번지에 위치해야 한다.

파이프라이닝 위험성

1) 구조적 위험성 (structural hazard)

그림 13.1에 보인 것처럼 명령어 파이프라이닝에서는 한 명령의 IF (Instruction Fetch) 와 다른 명령의 MEM (Memory Access) 가 중첩하여 일어난다. 즉 메모리에 있는 명령을 읽어오는 동작과 메모리의 데이터를 접근하는 일이 동시에 일어나는 것이다. 하나의 메모리에서 두 군데 내용을 동시에 읽는다는 의미다.

폰 노이만 구조 컴퓨터와 같이 단일 메모리만 있는 구조라면 이런 이중 접근은 구조적으로 불가능하다. 메모리는 한 순간에 한 내용만 접근할 수 있기 때문이다.

이런 구조적 위험성을 해결하려면 하버드 구조처럼 명령 메모리와 데이터 메모리를 분리해야 한다. 또 다른 방법은 하나의 메모리만 사용하되 뒤에서 배울 내용처럼 instruction cache memory 와 data cache memory 를 함께 사용하여 해결할 수도 있다.

2) 데이터 위험성 (data hazard)

명령어 파이프라이닝에서는 여러 개의 명령들이 중첩해서 동시에 실행된다. 그러나 뒤의 명령이 앞의 명령이 만들어내는 데이터를 필요로 하는 경우라면 동시 실행이 어려울 수도 있다. 예를 들어 메모리에 다음과 같은 명령이 순서대로 들어있다고 가정하자.

add r0, r1, r2 // r0 ← r1 + r2
sub r4, r0, r3 // r4 ← r0 + r3

레지스터 r0 내용은 그 위의 add 명령에서 결정되는데, 명령어 파이프라이닝을 적용하면 add 명령이 채 끝나기도 전에 sub 명령이 실행되므로 sub 명령 실행 당시 아직 r0 에는 유효한 값이 존재하지 않을 수도 있다. 즉 앞의 명령이 완전히 끝나서 유효한 데이터가 얻어진 다음에 뒤의 명령을 실행할 수 있다면 이 두 명령을 중첩해서 동시에 실행하는 것은 불가능하다.

이런 데이터 위험성을 해결하기 위해서는 파이프라이닝의 단계를 조정하거나 하드웨어를 개선하여 앞의 명령어가 완전히 끝나기 전에 결과 데이터를 뒤의 명령어 실행으로 넘길 수 있도록 해야 한다. 이것을 포워딩 forwarding 또는 바이패스 bypassing 이라고부른다. 많은 연구자들이 다양한 포워딩 방법을 개발하여 제안하고 있다.

3) 분기 위험성 (branch hazard)

컴퓨터 프로그램에서는 조건 분기가 자주 사용된다. 즉 조건이 맞으면 분기하고 그렇지 않으면 분기하지 않는 것이다. 그러나 명령어 파이프라이닝을 적용하면 조건 분기를 실행할 시점에 아직 조건이 맞는지 여부가 결정되지 않을 수 있다.

cmp r0,r1 // r0, r1 의 내용을 비교하여
beq L1 // 같으면 분기; 아니면 무시

명령어 파이프라이닝이 적용되면 cmp 와 beq 명령이 중첩되어 동시에 실행되므로 beq 명령 실행 당시 아직 cmp 명령이 채 끝나지 않을 수 있다. 즉 cmp 결과가 아직 나오지 않았기 때문에 beq 명령은 분기 여부를 정할 수가 없는 것이다.

극단적인 방법은 stall on branch, 즉 분기 여부가 결정될 때까지 계속 기다리는 것이다. 이렇게 하면 파이프라이닝 실행이 일시적으로 중단되어 성능 저하를 가져올 수밖에 없다.

또 다른 방법은 위의 예제에서 cmp 명령과 beq 명령 사이에 컴파일러가 여러 개의 nop (no operation) 명령을 의도적으로 넣어주는 것이다. nop 명령은 이름 뜻대로 아무 역할도 하지 않는 명령으로 단지 시간 지연만을 시킬 목적으로 사용된다. cmp 실행 후 몇 개의 nop 명령을 실행하면 그 사이에 cmp 결과가 나오게 되고 이후 beq 는 그 결과에 따라 분기 여부를 결정할 수 있다. 이 방법은 파이프라이닝 자체는 중단되지 않지만 여러 개의 nop 실행으로 인해 결국 성능 저하를 일으킬 수 있다.

세 번째 방법은 branch prediction, 즉 분기 여부를 예측하여 예측 결과에 따라 분기가 실행되거나 또는 넘어가도록 하는 것이다. 운 좋게 예측이 맞았다면 좋은 일이고, 그렇지 않다면 나중에 다시 원래 위치로 되돌아와서 (rollback) 다시 올바른 실행을 하는것이다. 예측이 정확할수록 이 방법의 성능은 좋아지는 것이고, 그렇지 않다면 성능이 오히려 떨어진다. 많은 연구자들이 다양한 분기 예측 방법을 개발하여 제안하고 있다.

CISC 와 RISC

CISC

Micro-programmed control 방식으로 CU 가 구현됨에 따라 CU 설계에 따른 복잡도가 낮아지게 되었고, 그래서 설계자들은 더 많은 종류의 명령어들과 더욱 다양한 어드레싱 모드를 프로세서에 넣을 수 있게 되었다. 이와 같이 micro-programmed control 방식의 CU 를 사용하고 다양한 명령어를 지원하는 구조의 컴퓨터를 CISC (ComplexInstruction Set Computer) 라고 부른다.

장점

  • CISC 컴퓨터는 그 이름에서 알 수 있듯이 많은 개수의 다양한 명령어를 제공하는 장점이 있다.
  • 다양한 어드레싱 모드를 지원한다.

단점

  • control ROM 을 사용하는데, ROM 의 속도는 hardwired control 방식에서 사용되는 게이트 등의 속도보다 매우 느리다. 즉 빠른 속도의 고성능 컴퓨터를 만드는 용도로는 부적합하다.
  • 오퍼랜드가 레지스터와 메모리 등으로 다양화되면 오퍼랜드 접근에 따른 시간 차이가 생긴다. 이런 시간 차이는 명령어 파이프라이닝을 적용하는 것을 어렵게 만들며, 파이프라이닝이 지원되지 않으면 고성능 컴퓨터로 사용할 수 없다.

RISC

RISC (Reduced Instruction Set Computer) 는 그 이름에서 알 수 있듯이 지원하는 명령어 개수가 줄어 있다. 즉 작은 수의 명령어들만 지원한다. 명령어 개수가 작은 이유는 micro-programmed control 방식이 아니라 hardwired control 방식의 CU 를 사용하고 있기 때문이다. 이 방식은 빠른 속도의 프로세서를 만드는데 적합하지만 설계상의 복잡도 때문에 많은 명령을 지원할 수는 없다.

장점

  • 메모리의 변수는 연산의 오퍼랜드로 사용할 수 없으며 레지스터만 사용할 수 있다. 즉 load/store 구조를 가진다. 이런 구조는 오퍼랜드 접근에 따른 시간을 일정하게 할 수 있으며 명령어 파이프라이닝 지원을 용이하게 한다. 즉 고성능 컴퓨터에 적합하다.
  • RISC 컴퓨터는 일반적으로 고정 길이 명령어 형식을 갖고 있다. 즉 ARM 프로세서와 같이 명령어 종류에 관계없이 모든 명령어의 길이가 32비트 등으로 일정한 것이다. 이렇게하면 명령어 가져오기 (instruction fetch) 시간이 일정하므로 명령어 파이프라이닝 적용이 효과적이다.

단점

  • RISC 에서는 어드레싱 모드도 제한적이다. hardwired control 방식은 설계 복잡도가 높기 때문에 다양한 어드레싱 모드를 지원하도록 만들기가 어렵다.

RISC 컴퓨터에서는 메모리의 변수를 오퍼랜드로 사용할 수 없으므로 대신 레지스터를 더 많이 사용한다.

스크린샷 2022-06-05 오후 10.14.21.png

0개의 댓글