---
title: "speculative history 복구: PC를 되돌렸는데 예측 문맥은 아직 틀렸다"
author: "브레이브브라우저쓰자"
published_at: "2026-10-14T11:51:00.748Z"
updated_at: "2026-10-06T00:33:05.484Z"
tags: ["speculative history 복구"]
canonical_url: "https://ariser.io/@writer_a9817d5a8de0/speculative-history-%EB%B3%B5%EA%B5%AC-pc%EB%A5%BC-%EB%90%98%EB%8F%8C%EB%A0%B8%EB%8A%94%EB%8D%B0-%EC%98%88%EC%B8%A1-%EB%AC%B8%EB%A7%A5%EC%9D%80-%EC%95%84%EC%A7%81-%ED%8B%80%EB%A0%B8%EB%8B%A4"
ai_assisted: true
---

# speculative history 복구: PC를 되돌렸는데 예측 문맥은 아직 틀렸다

이 글은 AI가 활용됐습니다.

[원문](https://ariser.io/@writer_a9817d5a8de0/speculative-history-%EB%B3%B5%EA%B5%AC-pc%EB%A5%BC-%EB%90%98%EB%8F%8C%EB%A0%B8%EB%8A%94%EB%8D%B0-%EC%98%88%EC%B8%A1-%EB%AC%B8%EB%A7%A5%EC%9D%80-%EC%95%84%EC%A7%81-%ED%8B%80%EB%A0%B8%EB%8B%A4)

분기 오예측을 발견해 PC를 올바른 주소로 돌렸다. 그런데 그다음 분기 예측이 연이어 흔들린다. 명령 경로는 되돌렸지만 예측기에 남아 있는 최근 이력은 아직 틀린 경로를 포함할 수 있기 때문이다. speculative history 복구는 앞으로 가져올 주소뿐 아니라 그 주소를 어떤 과거와 함께 예측할지까지 되돌리는 작업이다.

전역 이력을 실제 결과가 확정될 때까지 갱신하지 않으면 정보가 너무 오래될 수 있다. 그래서 분기를 가져오며 예측한 방향을 이력에 먼저 넣는다. 이 빠른 정보에는 잘못된 추측도 들어갈 수 있다. 복구는 그 비용을 감당하는 절차다.

## 현재 이력에 정답 하나를 더해도 복구되지 않는다

가상의 2비트 history를 쓰고, taken은 1, not-taken은 0이라고 하자. 새 결과 h를 넣는 규칙은 H_new=((H<<1)|h) AND 3이다. 왼쪽 비트가 더 오래된 결과이며, 가장 오른쪽에 최신 결과를 넣는다.

분기 B 직전의 이력이 01이라고 하자. B를 taken으로 예측하면 11이 된다. 뒤의 분기 C를 not-taken으로 예측하면 10이 된다. 그런데 B의 실제 결과가 not-taken으로 밝혀졌다면 C는 틀린 경로에서 가져온 분기다. C의 결과를 올바른 이력에 남길 이유가 없다.

복구할 답은 B 직전 01에 B의 실제 0을 붙인 10이다. 현재 이력 10에 실제 결과 0을 단순히 더 넣으면 00이 된다. wrong-path C의 0을 과거 결과로 남긴 채 B의 실제 결과를 한 번 더 뒤에 붙인 셈이다. B 직전 snapshot 01로만 되돌리고 끝내도 01이어서 B의 실제 결과를 반영하지 못한다.

따라서 이 예에서 필요한 동작은 B 직전의 상태를 복원한 뒤 실제 결과를 정해진 순서로 반영하는 것이다. 저장하는 snapshot이 예측 전인지 예측 후인지에 따라 구현의 연산은 달라질 수 있지만, 최종 상태는 올바른 경로의 결과 열과 일치해야 한다.

BOOM의 BPD 문서는 GHR을 투기적으로 갱신하고 오예측 때 snapshot으로 복구하는 이유를 설명한다. 실제 문서에서는 snapshot을 fetch 묶음과 연결해 관리한다. 앞의 계산은 한 묶음에 관심 분기가 하나인 작은 모델이다. 여러 분기가 있는 묶음에서는 오예측 분기 앞에 있는 유효한 결과까지 함께 재구성해야 할 수 있다. [BOOM BPD, Managing the GHR](https://docs.boom-core.org/en/latest/sections/branch-prediction/backing-predictor.html#managing-the-global-history-register-ghr)

## 조회에 쓰는 상태와 학습시키는 상태를 구분한다

이력 복구와 예측 표의 학습은 같은 일이 아니다. 앞의 B를 이력 01로 조회했다면, B의 실제 결과로 훈련할 entry도 그때의 조회 조건에 해당해야 한다. 결과가 돌아올 때의 최신 이력 10을 다시 사용해 index를 만들면 다른 entry를 갱신할 수 있다.

예측 당시의 index나 필요한 정보를 함께 저장하는 이유다. BOOM의 Fetch Target Queue 설명도 예측기가 나중에 올바른 entry를 갱신하도록 조회 정보를 보관한다고 명시한다. 현재 이력만 보아 과거 조회를 재현할 수 있다고 가정하지 않는다. [BOOM BPD, FTQ for Predictions](https://docs.boom-core.org/en/latest/sections/branch-prediction/backing-predictor.html#the-fetch-target-queue-ftq-for-predictions)

틀린 경로의 C가 실행되어 방향을 계산했더라도, 그 결과를 정상적인 학습 데이터로 남길지는 별도 결정이다. BOOM은 일반적인 BPD 학습을 commit 시점에 수행하여 wrong-path 정보의 오염을 막는다고 설명한다. 최신 예측을 위해 history는 먼저 바꾸되, 확정된 학습에는 정상적으로 살아남은 결과를 사용하는 분리다. 모든 예측기의 모든 상태가 같은 시점에 갱신된다는 뜻은 아니다.

## 분기 말고도 경로를 비우는 일이 있다

오예측 분기마다 snapshot을 갖고 있어도 예외나 재실행을 위한 전체 pipeline flush가 발생할 수 있다. 이런 사건은 특정 분기의 틀린 방향 하나로만 설명되지 않는다. 어느 시점의 상태로 돌아가야 하는지 별도의 기준이 필요하다.

BOOM 문서는 commit된 이력의 복사본을 유지하고 pipeline flush를 처리할 때 사용하는 이유를 설명한다. 최근 fetch의 투기 이력, 분기 복구용 snapshot, commit 이력은 각각 다른 시점의 사실을 표현한다. 이름이 모두 history라고 해서 하나를 다른 하나의 대체물로 사용할 수 없다. [BOOM BPD, GHR의 pipeline replay 및 flush 설명](https://docs.boom-core.org/en/latest/sections/branch-prediction/backing-predictor.html#managing-the-global-history-register-ghr)

검증에서는 복구 직후의 값만 보지 말고 그 값으로 이루어진 다음 조회도 확인하는 것이 좋다. B 뒤에 여러 younger 분기를 넣고 취소한 뒤, 정상 경로만 따라간 기준 모델과 이력을 비교한다. 저장 정보가 부족하거나 update와 restore의 우선순위가 잘못되면 PC는 정상이어도 예측 표의 선택이 달라진다.

필요한 snapshot 수와 저장할 이력 길이는 회로 비용으로 이어진다. 이력을 길게 쓰는 정확도 이득을 평가할 때는 복구 상태의 크기와 여러 사건을 처리하는 지연도 함께 보아야 한다.

speculative history 복구의 목표는 옛 비트열을 아무렇게나 돌려놓는 것이 아니다. 올바른 실행 경로를 예측기에 일관된 과거로 제공하는 것이다. PC의 복구, 이력의 복원과 실제 결과 반영, 해당 조회의 학습 위치를 연결해야 다음 추측도 올바른 문맥에서 시작한다.

