컴퓨터(Computer Science)/컴퓨터구조(Computer Arichitecture)

Control Hazard [컴퓨터구조]

게임이 더 좋아 2021. 6. 19. 21:08
반응형
728x170

 

이번에는 Control Hazard이다.

 


Branch할 때 많이 일어난다고 했다.

 

즉, Branch가 된다면 실제로 우리가 IF했던 것들이 쓸모가 없어질 수 있다.

 

 

 

또한 해당 결과는 MEM stage 에서 나오는데

MEM stage 동안 실행된 instruction을 다 Flush 시켜야 한다는 말이다.

**Flush란 우리가 물내리는 거랑 같다.

 

그렇게 세 개의 싸이클이 날라가면 또한 그것도 엄청난 성능 손해다.

 

그래서 우리는 Load and Use에서도 봤다시피

Mem stage가 끝난 뒤 포워딩하는 것을 미리 ID에서 미리 detect 한 것과 같이

ID 단계에 장치를 추가한다.

 

Target address adder Register comparator를 추가시킨다.

 

 

 


 

?? 어떻게 그렇게 하느냐?

 

 

ID에서 판단하고 결과를 알아내야 한다.

그래야 다음 싸이클에서 lw 명령어라는 제대로 된 명령어가 fetch 된다.

 

 

 

하지만 그렇게 ID 에 결과를 알아도

1싸이클은 stall이 된다.

 

그러나 3개짜리가 1개가 된 것만해도 엄청난 발전이다.

 


 

또 다른 Control Hazard가 있다.

 

 

beq가 쓰려는 레지스터가 

branch instruction보다 2번 앞선, 3번 앞선 instruction의 결과에서 나온다.

 

포워딩이 EX, MEM 후에 가능하기 때문에 실제로 branch instruction의 ID 단계에서 쓸 수 있다.

 

 

그렇지만 이 경우에는

 

즉, beq에서 쓰려는 레지스터들이

바로 직전 instruction의 결과거나 2번째 앞선 read해야하는 경우

ID 단계에서 branch instruction이 제대로 된 데이터를 받을 수 없다.

때문에 stall이 또 발생한다.

 

 

이런 경우도 있다.

 

 

Bracnh instruction 앞에 바로 Load instruction이 있는 경우에는

MEM이 끝나야 하기 때문에 2 싸이클이나 stall이 된다.

 


 

지난 글에서 배웠지만 

prediction 으로 성능을 좋게하는 방법이 있었다.

여기서도 Branch의 stall을 최소화하기 위한 방법으로

Dynamic prediction을 적용할 수 있다.

 

 

Branch prediction buffer에

해당 address에  버퍼를 직접적으로 가지고 있다.

또한 버퍼는 그 해당 주소에 대해 taken/not taken을 구분해서 저장을 한다.

 

 

 

즉, branch를 실행할 때 해당 table을 보고 저장된 값을 바탕으로 prediction을 한다.

-> 즉, 바로 전 실행결과가

실패하면 기존의 결과도 바꾸고 파이프라인을 flush한 다음 그것에 맞게 실행한다.

 

예를 들어 Loop를 실행한다면

 

loop가 2개가 있어서

inner lopp를 돌 땐

inner 위치로 taken 되므로 바로 실행이 되는데

inner루프가 끝나게 되면 마지막 branch는 taken으로 예측함에도 not taken이 되므로 1번 misprediction이 발생하고

 

outer로 가서 다시 inner로 들어오면 다시 해당 마지막 branch는 outer로 갈 때 not taken의 결과가 저장되었으므로

not taken을 예측하지만 아직 inner loop를 다 돌지 않아서 taken이 되어야 한다. 때문에 misprediction이 한 번 더 발생한다.

 

inner loop의 마지막 브랜치를 주목하라는 말이다.

inner loop의 마지가 branch 의 버퍼가 1비트이기 때문에 발생하는 일이다.

** 1 - Bit Predictor

 


 

그렇다면 늘리면??

 

2-Bit Predictor의 상태 다이어그램이라고 할까.

 

00 상태는 Taken을 예측하는 상태다.

Taken이 들어오면 현 상태유지

아니면 01

 

01 상태는 Taken을 예측하는 상태다.

Taken이 들어오면 00

아니면 10

 

10 상태는 Not Taken을 예측하는 상태다.

Taken이 들어오면 01

아니면  11

 

11 상태는 Not Taken을 예측하는 상태다

Not Taken이 들어오면 현 상태유지

아니면 10

 

즉, 2번의 Misprediction이 발생할 때만 예측 결과를 바꾼다는 말이다.

 

예를 들어 Taken을 예측 연속 2번 틀리면 이제 Not Taken을 예측하겠다는 말이다.

 


 

그렇다면 앞의 Loop 예에 적용시키면 어떻게 될까?

 

 

1번만 misprediction이 발생한다.

inner에서 taken을 예측하고

outer로 나갈 때도 1번 mispredicton이지만 계속 Taken을 예측한다.

그럼 다시 inner로 들어왔어도 taken을 예측하게 되므로 

아까와 같이 mispredcition이 발생하지 않는다.

 


 

그리고 Branch를 하기 위해선 Target address를 알아야한다.

 

 

만약 Taken이 된다면 PC가 원래 가리키던 instruction을 flush 되어야하니 1-cycle penalty를 가지게 된다.

 

그래서 Branch history buffer말고도

Branch target buffer도 생각해냈다.

target address를 캐싱하는 것이다.

 

해당 instruction이 fetch 될 때

taken이 된다고 하면 계산할 필요 없이 캐싱된 target address를 이용해서

바로 instruction fetch를 할 수 있다.

 

 

반응형
그리드형