■ 명령어 병렬 처리 기법 (ILP; Instruction-Level Paallelism)
좋은 성능의 CPU 제작을 위해 높은 클럭 속도, 멀티 코어, 멀티 스레드를 지원하는 CPU를 만드는 것도 중요하다. 하지만, 코어와 하드웨어 스레드 개수에 상관없이 효율적으로 CPU 자원을 사용하기 위해서는 명령어 병렬처리 기법이 필요하다.
대표적인 종류는
(1) 명령어 파이프라인
(2) 슈퍼스칼라
(3) 비순차적 명령어 처리
위 세 가지가 있다.
■ 명령어 파이프라인
명령어 처리 과정은 크게 '인출', '해석', '실행', '메모리 접근', '결과 저장' 의 여러 단계를 순서대로 진행된다.
처리 단계가 겹치지만 않다면 CPU는 각 단계를 동시에 [클럭 한 번에] 실행할 수 있다. 그렇기에 여러 개의 명령어를 단계가 겹치지 않게 병렬적으로 처리한다면 CPU를 효율적으로 사용할 수 있게 된다.
예시 이미지는 아래와 같다. (이전에 포스팅했던 것을 캡처함)
https://yjhdevelopdiary.tistory.com/205
위 기법의 처리 과정을 보면, 명령어 처리 과정이, 공장 생성 라인과 비슷하게 생겨서 명령어 파이프라이닝 이라고 한다.
만약 ILP 기법이 없었다면 명령어1이 끝나는 t4까지 명령어2~5는 대기하고 있다가 명령어 2가 실행되고 그 이후에도 순차적으로 동일하게 실행될 것이다
명령어 하나에 클럭 4번이 필요하니 ILP기법을 사용을 안했을 경우 명령어 5개를 처리하기 위해 총 20번의 클럭 이 필요했으나, 위 명령어 파이프라이닝을 통해 8번의 클럭으로 5개 명령어를 모두 끝낼 수 있게 되었다.
하지만 파이프라이닝의 위험성이 존재한다. 크게 데이터 위험, 제어 위험, 구조적 위험이 있다.
(1) 데이터 위험
명령어 간의 데이터 의존성에 의해 발생하는 이슈이다. 아래 예를 들어보자. 편의를 위해 명령어1를 I1 로 레지스터1를 R1으로 기재했다.
I1: R1 <- R2 + R3 I2: R4 <- R1 + R5 |
R1에는 R2 값과 R3 값을 더한 결과값을 저장한다. R4에는 R1 값과 R5 값을 더한 결과값을 저장한다. |
즉, 명령어1[I1]이 실행이 모두 다 되고 나서야 I2가 R1을 참조할 수가 있는데 I1이 끝나기 전에 I2의 인출이 시작되면 R1에 결과값이 저장되기 전에 엉뚱한 값을 가져올 수 있는 이슈가 발생할 수 있다.
(2) 제어 위험
제어 위험은 '프로그램 카운터(PC)의 갑작스러운 변화'에 의해 발생한다. 주로 Jump, Call, Interrupt와 같은 분기 등으로 인해 PC가 비순차적으로 변하게 되어 발생하는 이슈이다.
PC는 보통 '현재 실행 중인 명령어의 다음 주소'로 순차적으로 갱신이 되는데 프로그램 실행 흐름이 바뀌면서 PC값이 바뀌게 되면 명령어 파이프라인에 가져와서 처리중이었던 명령어들이 쓸모가 없어지게 되어 지연(stall) 되어버린다.
글로만 봤을 때 무슨 소리인가 싶을 것이다. 이미지로 표현 해봤다.
(3) 구조적 위험
구조적 위험은 명령어 파이프라이닝 중에 서로 다른 명령어가 동시에 ALU, 레지스터 등과 같은 CPU 자원을 사용하려고 할 때 발생한다. 한정된 자원을 공유하기에 일어나는 문제라서 '자원 위험(Resoruce Hazrad)'라고도 부른다.
이런 경우 후순위 명령어가 위에 제어 위험처럼 지연(Stall)이 되어버린다.
■ 슈퍼스칼라
오늘날 대부분의 CPU에서는 슈퍼 스칼라의 구조를 띄고 있다. 슈퍼스칼라란 CPU 내부에 여러 개의 명령어 파이프라인을 포함한 구조를 뜻한다.
파이프라인 개수에 비례하여 CPU 처리 속도도 증가하겠지만, 그만큼 위에 나열되어있었던 파이프라인 위험도 증가하므로 실제로는 파이프라인 개수를 비례하여 처리 속도를 증가시키지는 않다고 한다.
■ 비순차적 명령어 처리
비순차적 명령어 처리 (OoOE; Out-of-Order Execution)은 오늘날 CPU 성능 향상에 크게 기여한 기법이며 차용되어지고 있다.
위에 파이프라인 위험 중 '데이터 위험'을 떠올려보자.
데이터 의존성으로 인해 뒤에 코드들을 실행 못하는 상황이 되었을 때 뒤에 처리되고 있는 명령어들이 지연된다는 것을 볼 수 있었다.
이와 같은 상황에 대비하여 데이터 의존성이 전혀 없는 명령어들을 먼저 앞에서 처리를 해주고 의존성이 없는 명령어들을 뒤에서 처리해줌으로써 데이터 위험으로 인하여 파이프라인이 멈추는 것을 방지하는 기법을 비순차적 명령어 처리라고 한다. 순서를 바꿔가며 처리하기 때문에 이름이 의미하는 바를 이해할 수가 있을 것이다.
'Computer Science > Computer Architecture' 카테고리의 다른 글
[컴퓨터 구조] RAM (0) | 2024.12.01 |
---|---|
[컴퓨터 구조] ISA, CISC, RISC (1) | 2024.10.06 |
[컴퓨터 구조] 명령어 사이클, 인터럽트 (2) | 2024.10.02 |
[컴퓨터 구조] 레지스터 (Register) (2) | 2024.09.17 |
[컴퓨터 구조] 명령어, 주소 지정 방식 (0) | 2024.09.17 |