조건을 여전히 확인해야하는 경우 분기 예측은 어떻게 작동합니까?


30

https://stackoverflow.com/q/11227809/555690 에서 Branch Prediction에 대한 인기있는 답변을 읽었으며 혼란스러운 점이 있습니다.

  • 당신이 올바르게 추측하면 계속됩니다.
  • 당신이 틀렸다고 생각하면, 선장이 멈추고, 백업하고, 스위치를 뒤집으라고 소리 칠 것입니다. 그런 다음 다른 경로를 다시 시작할 수 있습니다.

매번 제대로 추측 하면 기차를 멈출 필요가 없습니다.

너무 자주 잘못 추측 하면 기차가 멈추고 백업하고 다시 시작하는 데 많은 시간이 걸립니다.

그러나 이것은 내가 얻지 못하는 것입니다 : 당신의 추측이 옳았 는지 아닌지 를 알기 위해서는 어쨌든 조건 점검을해야 합니다 . 두 가지 방법으로 여전히 동일한 조건부 검사를 수행한다면 분기 예측은 어떻게 작동합니까?

내가 말하려고하는 것은, 당신이 어쨌든 동일한 조건부 검사를 수행하기 때문에 분기 예측이 전혀없는 예측과 전혀 동일하지 않습니까? (분명히 틀렸지 만 얻지 못했습니다)


1
위키 기사는 그것을 잘 설명합니다.
enderland

8
최신 CPU는 파이프 라인이며 동시에 여러 작업을 수행 할 수 있습니다. 따라서 올바른 추측인지 여전히 알아내는 동안 추측 실행을 시작할 수 있습니다. 추측이 맞다면 파이프 라인은 계속 작동합니다. 틀린 추측으로 파이프 라인이 던져지고 "올바른 답"지점에서 실행이 다시 시작됩니다.
markspace

2
관련 읽기 : pipeline . 또한 여기에 귀하의 질문에 대한 답변이 있으므로 해당 SO 질문에 대해 수락 된 답변을 다시 읽는 것이 좋습니다.

답변:


19

물론 조건은 매번 확인됩니다. 그러나 확인 될 때까지는 CPU 파이프 라인으로 훨씬 올라갑니다. 그 동안 다른 명령어도 파이프 라인에 들어 갔으며 다양한 실행 단계에 있습니다.

일반적으로 조건 바로 뒤에는 조건 분기 명령이 나옵니다. 조건 분기 명령은 조건이 TRUE이면 분기되거나 조건이 FALSE이면 떨어집니다. 이는 조건이 TRUE 또는 FALSE인지 여부에 따라 조건 명령 및 분기 명령 이후 파이프 라인에로드 될 수있는 두 개의 서로 다른 명령 스트림이 있음을 의미합니다. 불행하게도, 조건 명령 및 분기 명령을로드 한 직후에 CPU는 조건이 무엇을 평가할지 아직 알지 못하지만 여전히 파이프 라인에 항목을로드해야합니다. 따라서 조건이 무엇을 평가할지에 대한 추측을 기반으로 두 명령 세트 중 하나를 선택합니다.

나중에 조건 명령이 파이프 라인을 따라 이동하면 평가할 시간입니다. 그때 CPU는 추측이 옳았는지 아닌지를 알아냅니다.

추측이 옳은 것으로 판명되면 지점이 올바른 위치로 이동하고 올바른 지침이 파이프 라인에로드되었습니다. 추측이 틀린 것으로 판명되면 조건부 분기 명령 이후 파이프 라인에로드 된 모든 명령이 잘못된 것이므로 버려야하며 명령 가져 오기는 올바른 위치에서 다시 시작해야합니다.

개정

StarWeaver의 의견에 따라 단일 명령을 실행하기 위해 CPU가 수행해야 할 작업에 대한 아이디어를 제공합니다.

MOV AX,[SI+10]우리 인간이 "SI 플러스 10에 단어가있는 AX로드"라고 생각하는 단순한 것을 고려하십시오 . 대략 CPU는 다음을 수행해야합니다.

  1. PC의 내용 ( "프로그램 카운터 레지스터")을 주소 버스로 내 보냅니다.
  2. 데이터 버스로부터 명령 연산 코드를 판독하고;
  3. 증분 PC;
  4. opcode를 디코딩하여 어떻게해야하는지 파악하십시오.
  5. PC의 내용을 주소 버스로 내 보냅니다.
  6. 데이터 버스로부터 명령어 피연산자 (이 경우 10)를 판독하고;
  7. 증분 PC;
  8. 피연산자와 SI를 가산기에 공급합니다.
  9. 가산기의 결과를 어드레스 버스로 방출하고;
  10. 데이터 버스에서 AX를 읽습니다.

이것은 무려 10 단계입니다. 이러한 단계 중 일부는 파이프 라인되지 않은 CPU에서도 최적화됩니다. 예를 들어 CPU는 거의 항상 다음 단계와 병행하여 PC를 증가시킵니다. PC는 매우 특수한 레지스터이기 때문에 수행하기가 쉽습니다. 다른 작업에는 사용되지 않으므로이 특정 레지스터에 액세스하기 위해 CPU의 다른 부분간에 경합이 발생할 가능성이 없습니다. 그러나 여전히 우리는 그러한 간단한 교육을 위해 8 단계를 밟았으며 CPU를 대신하여 어느 정도의 정교함을 이미 가정하고 있습니다. 예를 들어, 추가 단계를 수행 할 필요가 없다고 가정합니다 결과를 읽을 수 있기 전에 실제로 추가를 수행하는 가산기,

이제와 같이 더 복잡한 어드레싱 모드 MOV AX, [DX+SI*4+10]와 훨씬 더 복잡한 명령어가 있으며, MUL AX, operand실제로는 결과를 계산하기 위해 CPU 내부에서 루프를 수행합니다.

여기서의 요점은 "원자 수준"은유가 CPU 명령 수준에 적합하지 않다는 것입니다. 실제 로직 게이트 레벨로 너무 멀리 가고 싶지 않은 경우 파이프 라인 단계 레벨에 적합 할 수 있습니다.


2
허, 나는 (나를 포함하여) 사람들이 이것을 이해하는 데있어 문제의 일부가 CPU가 단일 명령에 대한 부분적인 지식 만 가지고 있다고 상상하기가 매우 어렵다는 것을 궁금합니다. 또는 "피자 벨트 오븐을 통과하는"절반의 완성 된 지시 사항을 갖기 위해… 적어도 나에게있어서, 그것은 난폭 기 세트와 금속 선반 레벨 사이의 일을하는 데 익숙 할 때 원자로의 규모 변화와 같은 느낌이 든다.
StarWeaver

1
@StarWeaver 귀하의 의견이 마음에 들었습니다. 이에 대한 답변을 수정했습니다.
Mike Nakis

1
와우, 좋은 설명입니다. 단어를 더 유용한 위치로 옮기는 데 얼마나 많은 비용이 드는지 잊어 버리는 경향이 있습니다. 나는 여전히 벨트 구동 피자 오븐 세트로 CPU를 시각화하고 있습니다 : 3.
StarWeaver

그것은 것을 염두에 둘 만하다 스택 오버플로 질문 아마도 "분기 예측은"심지어 존재 이전에 익숙하지 않은 사실에 1 백만 이상의 프로그래머를 도입 130 만 개 전망과 함께 한 - -의 예를 나타내는 영업 이익에 링크가 자바를 . Java와 같은 언어가 우리에게 제공하는 추상화 수준에서 일하는 데 익숙한 나와 같은 사람들에게는 MOV AX,[SI+10]"간단한"것이 아니라 외계인 도 있습니다 . 오늘날 대부분의 프로그래머는 어셈블리를 작성하지 않았습니다. 우리는 그것을 의미하는 것으로 "순진하게 생각"하지 않습니다.
마크

@MarkAmery 글쎄요, 저는 "우리 인간"이라는 말이 "조립을 쓰는 우리 인간"을 의미하는 것이 분명하다고 생각했습니다. 요점은 어셈블리 언어 프로그래머조차도 파이프 라인을 항상 또는 전혀 생각하지 않는다는 것입니다.
마이크 나 키스

28

GPS가없는 도로 여행이라고 생각하십시오. 당신은 교차로에 와서 회전해야한다고 생각하지만 완전히 확실하지는 않습니다. 그래서 당신은 차례를 가지고 있지만 승객에게지도를 확인하도록 요청하십시오. 어쩌면 당신이 어디에 있는지 논쟁을 마치기까지 길에서 3 마일 떨어진 곳일 것입니다. 당신이 옳았다면, 당신이 선회하기 전에 멈추고 논쟁했을 때보 다 3 마일 더 먼 곳입니다. 틀렸다면 돌아서야합니다.

CPU 파이프 라인은 같은 방식으로 작동합니다. 그들은 상태를 확인할 수있을 때 이미 길을 가고 있습니다. 차이점은, 그들은 3 마일을 뒤로 운전할 필요가없고, 단지 헤드 스타트를 잃는다는 것입니다. 그것은 노력에 아무런 해가 없다는 것을 의미합니다.


2
이 설명은 깔끔합니다.
sharptooth

2

내 이해에서, 분기 예측은 확인해야 할 조건이 비싸거나 여전히 진행중인 결과가 필요할 때 가장 유용하며, 그렇지 않으면 조건을 평가하기 위해 값을 기다리는 엄지 손가락을 돌리고있을 것입니다.

비 순차적 실행과 같은 방식으로 분기 예측을 사용하여 파이프 라인에서 CPU가 사용할 수없는 빈 자리를 채울 수 있습니다. 어떤 이유로 파이프 라인에 유휴주기가없는 상황에서는 분기 예측에 이득이 없습니다.

그러나 여기서 핵심은 CPU가 아직 조건 자체를 평가할 없기 때문에 예측 된 분기 중 하나에 대한 작업을 시작한다는 것입니다 .


1

짧은 형식:

일부 CPU는 이전 명령어를 완료하기 전에 새로운 명령어 작업을 시작할 수 있습니다. 이들은 분기 예측을 사용하는 CPU입니다.

의사 코드 예 :

int globalVariable;
int Read(int* readThis, int* readThat)
{
    if ((globalVariable*globalVariable % 17) < 5)
       return *readThis;
    else
       return *readThat;
}

위의 코드는 조건을 확인하고 메모리 위치에 addThis저장된 값 또는에 저장된 값을 반환해야하는 결과를 기반으로합니다 readThat. 분기 예측이 조건을로 예측 true하면 CPU는 명령문 addThis을 평가하는 데 필요한 계산을 수행하면서 메모리 위치에 저장된 값을 이미 읽습니다 if. 이것은 간단한 예입니다.


1

예, 상태가 어느 쪽이든 확인됩니다. 그러나 분기 예측의 장점은 조건 확인 결과를 기다리지 않고 작업을 수행 할 수 있다는 것입니다.

에세이를 작성해야하며 주제 A 또는 주제 B에 관한 것일 수 있습니다. 이전 에세이에서 선생님은 B보다 주제 A를 더 좋아하고 더 자주 선택한다는 것을 알고 있습니다. 그의 결정을 기다리지 않고 첫 번째 주제에 대한 에세이를 작성할 수 있습니다. 이제 두 가지 가능한 결과가 있습니다.

  1. 잘못된 주제에 대한 에세이를 시작했으며 지금까지 작성한 내용을 삭제해야합니다. 다른 주제에 대한 글을 쓰기 시작해야하며 마치 마치 마치 기다린 것과 같은 시간입니다.
  2. 당신은 옳았 고 이미 일을 마쳤습니다.

최신 CPU는 IO 응답 ​​또는 다른 계산 결과를 기다리고 있기 때문에 대부분 유휴 상태입니다. 이번에는 미래의 작업을 수행하는 데 사용될 수 있습니다.

이 유휴 시간에 수행중인 작업을 해제해야하는 경우에도 프로그램이 어떤 경로를 선택할지 추측 할 수 있으면 더 효과적 일 수 있습니다. 그리고 최신 CPU에는이 기능이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.