파이프라인의 정상적인 수행을 방해하는 요소들
Structure Hazard
하나의 Resource를 여러 Stage에서 동시에 접근 / 사용
Data Hazard
앞의 명령어에서 사용중인 데이터를 뒤의 명령어에서 접근 / 사용
Control Hazard
branch / jump 명령어에서 생기는 문제점
Waiting으로 모든 Hazard는 해결 가능하지만,
이렇게 되면 Pipeline을 쓰는 의미가 없어짐
여러 Pipeline Stage에서 같은 Resource(메모리, 레지스터 등)를 동시에 참조하는 것
Pipeline Stage의 데이터 접근 순서에 따라 문제가 생길 수 있음
같은 메모리 혹은 레지스터를 참조하는 명령어 i와 j에서,
명령어 i 이후 j가 실행된다고 가정할 때
RAR은 데이터가 변경되지 않으므로 문제되지 않음
위와 같이 Stage의 실행 시간을 맞춰주는 경우 문제 해결 가능
같은 데이터를 두 레지스터로 나누어 관리
---------------------------
a = x + b; // WAR
x = c + 1; // RAW
d = x / 2;
-->
a = x + b;
x1 = c + 1;
d = x1 / 2; // WAR 해결
---------------------------
x = a + b; // WAW
x = c + 1; // RAW
d = x / 2;
-->
x = a + b;
x1 = c + 1;
d = x1 / 2; // WAW 해결
---------------------------
add
에서 r1
에 대한 처리가 끝나지 않았음에도 다른 명령어에서 이를 참조하고 있음
Solution 1 - Delay
Delay가 늘어날수록 성능이 떨어지기 때문에 좋은 방법은 아니다.
Solution 2 - Register file
레지스터 접근을 같은 Cycle에서 처리하여 Delay를 줄임
Solution 3(1) - Forwarding[ALU]
ALU
의 작동이 끝난 시점에 이미 값을 알고 있으므로, 그 값을 다음 연산에서 활용Solution 3(2) - Forwarding[Load]
1. Load
명령이 아닌 경우
EX hazard
/ 메모리 접근 단계인 MEM hazard
로 구분EX/MEM.RegWrite
혹은 MEM/WB.RegWrite
가 발생Destination Register != $zero
(0번 레지스터는 변경 불가능)EX/MEM.RegWrite
일 때 Forwarding Unit은 MUX에 들어가는 신호를 10
으로 설정MEM/WB.RegWrite
일 때 Forwarding Unit은 MUX에 들어가는 신호를 01
으로 설정EX/MEM/WB Solution
add -> sub
, sub -> or
이외에 add -> or
에서도 Data Hazard가 발생할 수 있음
EX/MEM.RegWrite
이면서 MEM/WB.RegWrite
가 아닌 경우(혹은 반대의 경우)를 추가해주면 해결 가능Load Solution
적절한 위치에 nop(no operation)을 넣어 처리
위의 경우에 Hazard Detection Unit에서 다음 Pipeline에 nop을 넣고, IF/ID 단계에 받은 명령어를 반복하여 넣어줌으로써 다음 단계에서 동작하도록 처리
컴파일러가 명령어 순서를 적절히 조절하여, dependency가 발생하지 않도록 함
위와 같이 load
를 앞에 배치함으로서 Delay를 넣어주고, dependency를 없애는 효과가 생김
컴파일러가 명령어 구조를 최적화해주면, 하드웨어를 사용하지 않고 Hazard를 줄일 수 있기 때문에 컴파일러의 역할이 상당히 중요해졌다.