Перейти к содержанию

Масштабирование вычислений при инференсе (Test-Time Compute)

~7 минут чтения

Test-time compute, inference-time scaling, parallel/sequential scaling, Best-of-N, PRM, Chain-of-Thought, MCTS, budget forcing, latent reasoning, o1/o3, DeepSeek R1, Chain of Draft, S* (2025-2026)

Предварительно: Оптимизация инференса LLM, Техники рассуждений

Зачем это нужно. Обучение GPT-4 стоило ~\(100M, а каждый следующий прирост качества через увеличение модели обходится в 3-10x дороже при diminishing returns. Test-time compute -- альтернативный путь: o1-mini (~20B параметров, ~\)0.003 за запрос с 50x inference compute) обходит GPT-4o (~1T параметров) на математических бенчмарках (90% vs 76.6% MATH). Для production это означает, что можно держать компактную модель и масштабировать "думание" только для сложных запросов, экономя 80-90% на GPU по сравнению с деплоем гигантской модели для всех запросов.


Ключевые концепции

Test-Time Compute Scaling (inference-time scaling) -- улучшение рассуждений LLM путём увеличения вычислений при инференсе, а не при обучении.

Сдвиг парадигмы

Подход Идея Проблемы
Training-time scaling Больше параметров = лучше (7B -> 70B -> 1T) Diminishing returns, огромная стоимость, сложный деплой
Test-time scaling Больше "думания" при генерации Латентность, стоимость инференса

"Think longer, not larger" -- o1-mini (~20B) обходит GPT-4o (~1T) на математике за счёт 50x inference compute.

Landscape 2026

Method Compute Quality Gain Latency
Chain-of-Thought 2-5x +10-30% Low
Best-of-N Nx (parallel) +5-15% Low (parallel)
Self-Refine 2-3x (sequential) +10-15% Medium
Tree Search (MCTS) 10-100x +20-30% High
o1/o3 (full) 10-100x +30-50% High

Четыре категории reasoning models (Sebastian Raschka)

  1. Inference-time compute scaling -- без изменения весов
  2. Pure reinforcement learning -- только RL
  3. RL + Supervised Fine-tuning -- гибрид
  4. SFT + Model distillation -- обучение на качественных данных

1. Parallel Scaling

Majority Voting (Self-Consistency)

def majority_vote(prompt, n_samples=10):
    responses = [llm.generate(prompt) for _ in range(n_samples)]
    answer_counts = Counter(extract_answer(r) for r in responses)
    return answer_counts.most_common(1)[0][0]

Cost: Nx. Best for: tasks with clear answers (math, coding).

Best-of-N with PRM

class TestTimeScaler:
    def __init__(self, llm, prm, n_samples=10):
        self.llm = llm
        self.prm = prm  # Process Reward Model
        self.n_samples = n_samples

    def generate(self, prompt):
        samples = [
            self.llm.generate(prompt, temperature=0.7)
            for _ in range(self.n_samples)
        ]
        scores = [self.prm.score(prompt, s) for s in samples]
        best_idx = torch.argmax(torch.tensor(scores))
        return samples[best_idx]

PRM (Process Reward Model): оценивает качество каждого шага рассуждения, не только финальный ответ.


2. Sequential Scaling

Chain-of-Thought (CoT)

Q: What is 15 x 27?

Think step by step:
1. 15 x 27 = 15 x (20 + 7)
2. 15 x 20 = 300
3. 15 x 7 = 105
4. 300 + 105 = 405

Answer: 405

Self-Refinement

def self_refine(prompt, iterations=3):
    response = llm.generate(prompt)
    for _ in range(iterations):
        feedback = llm.generate(f"Critique this answer: {response}")
        response = llm.generate(f"Improve based on feedback: {feedback}")
    return response

"Wait" Tokens (s1: Simple Test-Time Scaling)

Budget Forcing: принудительные "Wait" токены заставляют модель продолжать думать.

def budget_forcing(prompt, llm, min_tokens=100, max_tokens=500):
    response = ""
    while len(response.split()) < min_tokens:
        response = llm.generate(prompt, max_tokens=max_tokens)
        if len(response.split()) < min_tokens:
            prompt = f"{prompt}\n{response}\nWait, let me continue..."
            response = ""
    return response
Technique Accuracy Tokens
Standard 70% 100
CoT ("think step by step") 82% 300
s1 with "Wait" tokens 87% 400
Budget forcing 89% Variable

3. Tree Search Methods

MCTS for LLM Reasoning

graph TD
    ROOT["Root (Question)"] --> S1A["Step 1a"]
    ROOT --> S1B["Step 1b"]
    S1A --> S2A["Step 2a"]
    S1A --> S2B["Step 2b"]
    S1B --> S2C["Step 2c"]
    S2A --> R1["Reward: 0.85"]
    S2B --> R2["Reward: 0.42"]
    S2C --> R3["Reward: 0.71"]

    style ROOT fill:#e8eaf6,stroke:#3f51b5
    style S1A fill:#e8f5e9,stroke:#4caf50
    style S1B fill:#e8f5e9,stroke:#4caf50
    style S2A fill:#fff3e0,stroke:#ef6c00
    style S2B fill:#fff3e0,stroke:#ef6c00
    style S2C fill:#fff3e0,stroke:#ef6c00
    style R1 fill:#e8f5e9,stroke:#4caf50
    style R2 fill:#fce4ec,stroke:#c62828
    style R3 fill:#fff3e0,stroke:#ef6c00

Process: 1. Selection: выбрать node (UCB) 2. Expansion: добавить children 3. Simulation: rollout до terminal state 4. Backpropagation: обновить values вверх по дереву

import math

class ReasoningNode:
    def __init__(self, state, parent=None):
        self.state = state
        self.parent = parent
        self.children = []
        self.visits = 0
        self.value = 0

    def ucb(self, c=1.41):
        if self.visits == 0:
            return float('inf')
        exploitation = self.value / self.visits
        exploration = c * (math.log(self.parent.visits) / self.visits) ** 0.5
        return exploitation + exploration

class ReasoningMCTS:
    def __init__(self, llm, prm, max_depth=10):
        self.llm = llm
        self.prm = prm
        self.max_depth = max_depth

    def search(self, question, n_simulations=100):
        root = ReasoningNode(state=question)
        for _ in range(n_simulations):
            node = self._select(root)
            if node.visits > 0:
                node = self._expand(node)
            value = self._simulate(node)
            self._backpropagate(node, value)
        return self._best_child(root).state

    def _select(self, node):
        while node.children:
            node = max(node.children, key=lambda n: n.ucb())
        return node

    def _expand(self, node):
        next_step = self.llm.generate(f"{node.state}\nNext step:")
        child = ReasoningNode(state=f"{node.state}\n{next_step}", parent=node)
        node.children.append(child)
        return child

    def _simulate(self, node):
        return self.prm.score(node.state)

    def _backpropagate(self, node, value):
        while node:
            node.visits += 1
            node.value += value
            node = node.parent

AB-MCTS (Sakana AI, 2025)

Adaptive Branching MCTS. Combines repeated sampling (parallel) + multi-turn exploration (sequential) + principled branching decisions. Released as TreeQuest (Apache 2.0). Consistently outperforms both sampling and standard MCTS.

MCTS + Associative Memory (CoAT)

Chain-of-Associated-Thoughts: добавляет associative memory как knowledge base при tree search. Каждый node хранит reasoning step + state value + associated memories.


4. Latent Reasoning

"Scaling up Test-Time Compute with Latent Reasoning" (Feb 2025)

Итерирование в latent space вместо генерации токенов:

# Standard: generate more tokens
for _ in range(n_tokens):
    token = model.generate_next_token()

# Latent: iterate hidden state
h = model.encode(input)
for _ in range(n_iterations):
    h = recurrent_block(h)  # Refine in latent space
output = model.decode(h)

Pros: efficient (no token generation overhead). Cons: less interpretable.


5. o1/o3 Architecture

Hidden Thinking Tokens

  • Model reasons before final output, thinking tokens not shown to user
  • Trained with RL to reason effectively: backtracks, explores multiple approaches
  • Compute scales with problem difficulty
Problem Type Avg Thinking Tokens Latency
Simple chat 0 1s
Code generation ~5,000 10s
Math proof ~20,000 40s
Complex reasoning 50,000+ 100s+

o1/o3 Benchmarks

Benchmark GPT-4o o1-mini o1 o3
AIME 2024 13.4% 70.0% 83.3% 91.6%
Codeforces 11th %ile 86th %ile 89th %ile 93rd %ile
GPQA Diamond 50.6% 60.0% 77.3% 82.4%
MATH 76.6% 90.0% 94.8% 96.4%

Model Size vs Compute Trade-off

Model Params Test-Time Compute MATH Score
GPT-4o ~1T 1x 76.6%
o1-mini ~20B 50x 90.0%
o1 ~200B 100x 94.8%

Other Reasoning Models

  • DeepSeek R1: pure RL (no explicit inference scaling in model), generates longer responses naturally
  • Gemini 2.0 Flash Thinking: explicit thinking mode, transparent reasoning traces
  • Claude Extended Thinking: optional extended thinking, uses parallel + sequential scaling

6. Key Papers (Jan-Feb 2025)

s1: Simple Test-Time Scaling (31 Jan 2025)

Budget forcing with "Wait" tokens. "Wait" outperforms "Hmm" tokens.

Underthinking Penalty (30 Jan 2025)

Problem: reasoning models переключаются между путями вместо углубления. Solution: Thought Switching Penalty (TIP) -- penalize premature reasoning path transitions, no fine-tuning required.

1B LLM Surpass 405B LLM (10 Feb 2025)

  • 1B model + inference scaling > 405B Llama 3 (no scaling)
  • 7B model + inference scaling > DeepSeek-R1 (with better efficiency)

Chain of Draft (25 Feb 2025)

Краткие черновики вместо многословных объяснений. Similar accuracy to CoT with 80% fewer tokens.

Standard CoT:  "First, I need to calculate X. Then I will do Y..."
Chain of Draft: "X=5, Y=10, Total=15"

S*: Test Time Scaling for Code (20 Feb 2025)

Two stages: (1) Generate -> Execute -> Debug -> Iterate on public tests. (2) Generate edge cases to differentiate solutions.

Other Papers

  • Test-Time Preference Optimization (22 Jan): iterative alignment during inference
  • CoAT (4 Feb): MCTS + associative memory
  • Self-Backtracking (4 Feb): learned backtracking
  • Latent Reasoning (7 Feb): iterate in latent space

7. Compute-Optimal Strategy

Scaling Law

\[\text{Performance} = f(\text{Model Size}, \text{Train Compute}, \text{Test Compute})\]
\[\text{Effective Capacity} = \text{Model Size} \times \text{Inference Compute}\]

Problem Difficulty Calibration

def compute_optimal_scaling(problem, budget):
    difficulty = estimate_difficulty(problem)
    if difficulty < threshold_easy:
        return direct_generation()
    elif difficulty < threshold_medium:
        return cot_with_n_samples(n=5)
    else:
        return mcts_search(budget=budget)
Problem Type Recommended Compute
Simple QA Direct generation 1x
Multi-step reasoning CoT 2-3x
Math/Coding o1-style / S* 10-50x
Open-ended creative Best-of-N 5-10x
Verification needed Self-refine 3-5x
Maximum accuracy AB-MCTS or Budget forcing 50-100x

Compute Scaling Efficiency (MATH benchmark)

Compute Factor Quality Latency
1x (baseline) 76% 1s
3x (CoT) 82% 3s
10x (Best-of-10) 86% 2s (parallel)
30x (Tree search) 90% 30s
100x (o1) 95% 100s

Формулы

UCB для MCTS

\[\text{UCB} = \frac{Q}{N} + c \sqrt{\frac{\ln N_{parent}}{N}}\]

Best-of-N Expected Improvement

\[P(\text{correct}) = 1 - (1 - p)^N\]

где \(p\) = single-attempt accuracy

Compute-Optimal Allocation

\[\text{Total Compute} = C_{train} + C_{test} \cdot N_{queries}\]

Interview Questions

Q: Что такое test-time compute scaling и зачем он нужен?

❌ Red flag: "Это когда модель думает дольше и дает лучший ответ."

✅ Strong answer: "Улучшение рассуждений LLM увеличением вычислений при инференсе вместо увеличения модели. Два измерения: (1) parallel -- генерировать N ответов, выбрать лучший (Best-of-N + PRM, majority voting); (2) sequential -- итеративно улучшать один ответ (CoT, self-refine, budget forcing). o1-mini (~20B, 50x compute) обходит GPT-4o (~1T) на MATH (90% vs 76.6%). Это сдвиг парадигмы: вместо training-time scaling (7B->70B->1T с diminishing returns) масштабируем inference compute адаптивно под сложность задачи."

Q: Сравните parallel vs sequential scaling -- когда что использовать?

❌ Red flag: "Parallel быстрее, sequential точнее, зависит от задачи."

✅ Strong answer: "Parallel (Best-of-N, majority voting): Nx compute, +5-15% quality, low latency (запросы параллельны). Подходит для задач с четким ответом -- math, coding. Sequential (CoT, self-refine, budget forcing): 2-5x compute, +10-30%, higher latency. Подходит для multi-step reasoning. MCTS комбинирует оба: 10-100x compute, systematic tree exploration. Budget forcing с Wait tokens дает 89% vs 70% baseline (s1 paper). Оптимальная стратегия -- adaptive: easy -> direct, medium -> CoT, hard -> MCTS/o1-style."

Q: Как работает MCTS для LLM reasoning?

❌ Red flag: "Это дерево поиска, модель перебирает варианты."

✅ Strong answer: "Четыре фазы: (1) Selection -- UCB = Q/N + c*sqrt(ln(N_parent)/N) выбирает explore vs exploit. (2) Expansion -- LLM генерирует следующий шаг рассуждения как child node. (3) Simulation -- PRM (Process Reward Model) оценивает качество каждого шага. (4) Backpropagation -- обновление value вверх по дереву. AB-MCTS (Sakana AI) добавляет adaptive branching. Результат: 1B + MCTS > 405B без scaling. Ограничение: 10-100x latency, нужен обученный PRM."

Q: Что такое Chain of Draft и почему он важен для production?

❌ Red flag: "Это как Chain-of-Thought, но короче."

✅ Strong answer: "CoD генерирует краткие черновики вместо многословных объяснений: 'X=5, Y=10, Total=15' вместо 'First I need to calculate X...'. Accuracy сопоставима с CoT, но на 80% меньше токенов. Для production это критично: при $15/1M output tokens (o1) экономия 80% токенов -- это 80% экономия на API costs. CoD позволяет получить reasoning quality без reasoning cost."

Ключевые числа

Факт Значение
o1 MATH benchmark 94.8%
o1-mini MATH 90.0%
GPT-4o MATH 76.6%
o1 AIME 2024 83.3%
o3 AIME 2024 91.6%
Chain of Draft token savings 80% fewer
s1 "Wait" tokens accuracy 89% vs 70% baseline
1B vs 405B 1B + scaling > 405B without
o1 thinking tokens (hard) 50,000+
Best-of-N expected improvement P = 1 - (1-p)^N

Источники

  1. Sebastian Raschka -- "Inference-Time Compute Scaling Methods" (Mar 2025)
  2. arXiv -- "The Art of Scaling Test-Time Compute for Large Language Models" (2512.02008)
  3. arXiv -- s1: Simple Test-Time Scaling (2501.19393)
  4. arXiv -- Underthinking of o1-Like LLMs (2501.18585)
  5. arXiv -- 1B vs 405B Compute-Optimal (2502.06703)
  6. arXiv -- Chain of Draft (2502.18600)
  7. arXiv -- S* Code Generation (2502.14382)
  8. arXiv -- CoAT: Chain-of-Associated-Thoughts (2502.02390)
  9. arXiv -- Latent Reasoning (2502.05171)
  10. arXiv -- Test-Time Preference Optimization (2501.12895)
  11. arXiv -- Test-Time Compute Survey (2501.02497)
  12. Sakana AI -- AB-MCTS / TreeQuest (2025)
  13. OpenAI -- o1 and o3 technical reports
  14. Adaptive ML -- "Test-Time Compute is Two-Dimensional"
  15. NVIDIA Blog -- "How Scaling Laws Drive Smarter AI"

Заблуждение: Best-of-N всегда лучше single generation

Best-of-N с N=64 дает ~15% прирост точности при 64x compute. Но без хорошего verifier (PRM) вы выбираете "случайно лучший", а не "проверенно лучший". На GSM8K majority voting с N=100 дает +12%, а Best-of-N с обученным PRM дает +18% при том же N. Без PRM -- Best-of-N может быть хуже majority voting, потому что длинный "уверенный" ответ не значит правильный.

Заблуждение: Chain-of-Thought работает для любых задач

CoT дает +10-30% на математике и логике, но на задачах извлечения фактов ("В каком году родился Пушкин?") CoT не улучшает результат и иногда ухудшает его -- модель начинает "рассуждать" и галлюцинировать промежуточные факты. Бенчмарк TriviaQA: CoT дает 0% improvement vs direct prompting. CoT полезен только для multi-step reasoning.

Больше thinking tokens != лучший ответ на простых задачах

o1/R1-style модели тратят 50K+ thinking tokens на сложные задачи. Но на простых вопросах ("Столица Франции?") дополнительные tokens ухудшают результат: модель начинает "overthink", генерирует ложные цепочки рассуждений. arXiv 2501.18585 показывает "underthinking" проблему: модель переключается между подходами вместо углубления одного. Правило: test-time compute scaling оправдан для AIME/GPQA-level задач, но для 60% production queries (FAQ, summarization) дешевая модель без reasoning быстрее И точнее.


See Also