3,583 papers
arXiv:2512.14018 68 15 дек. 2025 г. FREE

PerfCoder: двухшаговая оптимизация через явные стратегии

КЛЮЧЕВАЯ СУТЬ
PerfCoder — модель, которая оптимизирует код в два шага: сначала генерирует понятные человеку стратегии оптимизации ("замени цикл на хеш-таблицу", "используй бинарный поиск вместо линейного"), потом применяет их к коду. Работает в двух режимах: либо сразу выдаёт стратегии + оптимизированный код, либо только стратегии — чтобы передать их другой (обычно более крупной) модели для реализации.
Адаптировать под запрос

TL;DR

PerfCoder — модель, которая оптимизирует код в два шага: сначала генерирует понятные человеку стратегии оптимизации ("замени цикл на хеш-таблицу", "используй бинарный поиск вместо линейного"), потом применяет их к коду. Работает в двух режимах: либо сразу выдаёт стратегии + оптимизированный код, либо только стратегии — чтобы передать их другой (обычно более крупной) модели для реализации.

Главная находка: крупные модели плохо оптимизируют производительность кода, потому что не умеют артикулировать стратегии оптимизации. Они пытаются улучшить код "в лоб", без явного плана — получается хаотично. GPT-5 в одиночку даёт 1.96× ускорение, но если маленькая модель PerfCoder (1.5B параметров) сначала сгенерирует стратегии, а GPT-5 их реализует — ускорение взлетает до 4.82×. Проблема не в мощности модели, а в отсутствии структурированного мышления об оптимизации.

PerfCoder обучали на траекториях реальных оптимизаций — взяли 30,649 пар медленный код → быстрый код с соревнований по программированию, автоматически извлекли стратегии ("что изменилось и почему стало быстрее"), отбалансировали датасет (чтобы редкие мощные стратегии не потерялись среди частых простых), обучили модель генерировать стратегии + код. Потом через reinforcement learning с реальными замерами времени выполнения усилили способность генерировать эффективные стратегии.

🔬

Схема метода

Single-step режим (одним запросом):

Вход: медленный код
↓
Модель генерирует:
[SUGG/] Стратегии оптимизации с объяснениями [/SUGG]
[OPT/] Оптимизированный код [/OPT]

Two-step режим (планировщик + исполнитель):

ШАГ 1: Маленькая модель (PerfCoder) → стратегии оптимизации
ШАГ 2: Большая модель (GPT-5/Qwen2.5-32B) → код по стратегиям

Требует двух отдельных запросов.

🚀

Пример применения

Задача: Написал функцию на Python для парсинга прайс-листа поставщика (CSV, 50 тысяч позиций), но она работает 30 секунд — клиент ждёт, пока загрузится страница. Нужно ускорить.

Промпт (two-step):

Вот мой код на Python, который парсит CSV-файл с 50 тысячами строк. 
Он работает медленно (30 секунд). 

Твоя задача: 
1. Проанализируй код
2. Опиши 2-3 конкретные стратегии оптимизации производительности
3. Для каждой стратегии объясни ПОЧЕМУ она ускорит выполнение

Не пиши код сразу — только стратегии.

[код]

После получения стратегий — второй запрос:

Теперь примени эти стратегии к коду. Оптимизируй его.

Стратегии:
[стратегии из первого ответа]

Исходный код:
[код]

Результат:

Первый запрос выдаст структурированный список стратегий с объяснениями — например, "замени append в цикле на list comprehension (избежишь переаллокаций памяти)", "используй csv.DictReader вместо ручного split (оптимизирован в C)", "читай файл батчами по 1000 строк (снизишь пиковое потребление памяти)".

Второй запрос применит эти стратегии к коду — получите рефакторенную версию с комментариями, объясняющими каждое изменение.

🧠

Почему это работает

Слабость LLM: модели плохо оптимизируют производительность, потому что не различают "работает корректно" и "работает быстро". Они обучены на корпусе кода, где функциональная правильность встречается часто, а явные рассуждения об оптимизации — редко. Модель видит быстрый код, но не понимает почему он быстрый и какие принципы за этим стоят.

Сильная сторона LLM: модели отлично работают со структурированными инструкциями. Если дать явный план ("сделай X, потом Y, потому что Z"), они хорошо его выполняют. Это подтверждают Chain-of-Thought и подобные техники.

Как метод использует сильную сторону: PerfCoder материализует стратегии оптимизации — превращает неявное знание ("этот код быстрее") в явное ("быстрее потому что используется хеш-таблица вместо линейного поиска, сложность O(1) против O(n)"). Обучение на траекториях с категоризированными стратегиями (15 типов: Loop Efficiency, Data Structure Selection, Algorithm Design и т.д.) создаёт структурированное понимание оптимизации.

Почему two-step лучше чем single-step для сложных задач: разделение мышления (генерация стратегий) и реализации (применение к коду) позволяет использовать специализацию. Маленькая модель (1.5B), обученная думать про оптимизацию, генерирует лучшие стратегии, чем большая универсальная модель (GPT-5). А большая модель, получив готовый план, хорошо его реализует — у неё мощная база для кодогенерации.

Это как разделение труда: узкий специалист по производительности делает аудит, senior-разработчик пишет код по его рекомендациям.

Рычаги управления:

  • Количество стратегий (2-3 vs 5-7) → больше стратегий = глубже оптимизация, но можно переоптимизировать
  • Специфичность стратегий ("оптимизируй цикл" vs "замени цикл for на list comprehension") → конкретные инструкции дают предсказуемый результат
  • Категории стратегий (15 типов в исследовании) → можно попросить фокус на конкретной категории ("только алгоритмические оптимизации, без микрооптимизаций")
📌

Универсальный принцип (экстраполяция на не-код)

Этот принцип работает не только для кода. Логика "сначала стратегии, потом реализация" применима к любой оптимизации контента:

🔧 Оптимизация текста:

ШАГ 1: 
Вот статья для блога (3000 знаков). Она плохо конвертит — читают, но не кликают CTA.

Не переписывай сразу. Сначала опиши 3 стратегии улучшения конверсии 
с объяснением ПОЧЕМУ каждая сработает.

[текст статьи]

ШАГ 2 (после получения стратегий):
Теперь примени эти стратегии. Перепиши статью.

Стратегии:
[стратегии из первого ответа]

Исходный текст:
[текст]

Модель сначала проанализирует ("слабый оффер в начале — читатель не понимает выгоду", "CTA в конце — теряем внимание по пути", "нет социальных доказательств") — потом применит осознанно.

🔧 Улучшение промпта:

ШАГ 1:
Мой промпт для генерации описаний товаров даёт слишком общие результаты.

Проанализируй промпт и опиши 2-3 стратегии его улучшения 
для более специфичных описаний.

[промпт]

ШАГ 2:
Примени эти стратегии. Перепиши промпт.

[стратегии + исходный промпт]

Почему экстраполяция работает:

Принцип не про код — про разделение анализа и действия. Когда модель сначала генерирует план, она: 1. Активирует релевантные паттерны из обучающих данных 2. Структурирует своё "мышление" 3. Создаёт якоря для второго шага

Это аналог Chain-of-Thought, но для творческих/оптимизационных задач, не для логики.

📋

Шаблон промпта

📌

Для оптимизации кода:

Анализируй код и предложи стратегии оптимизации производительности.

[АНАЛИЗ]
Код: {код}
Контекст: {описание что делает, какие узкие места известны}

[ЗАДАЧА]
1. Выдели 2-3 ключевые стратегии оптимизации
2. Для каждой стратегии объясни:
   - Что конкретно изменить
   - Почему это ускорит выполнение
   - Какой примерный эффект ожидать

Формат ответа:
[СТРАТЕГИЯ 1] Название
Что делать: ...
Почему быстрее: ...
Эффект: ...

[СТРАТЕГИЯ 2] ...

Не пиши код сразу — только стратегии.

Плейсхолдеры: - {код} — исходный код для оптимизации - {описание} — что делает код, где тормозит (опционально, если знаете)

После получения стратегий:

Примени эти стратегии к коду:

[СТРАТЕГИИ]
{стратегии из первого ответа}

[ИСХОДНЫЙ КОД]
{код}

Оптимизируй код согласно стратегиям. Добавь комментарии к изменениям.

🚀 Быстрый старт — вставь в чат:

Вот шаблон two-step оптимизации кода. Адаптируй под мою задачу: {опиши свою задачу}
Задавай вопросы, чтобы заполнить поля.

[вставить шаблон выше — первый блок]

LLM спросит про язык программирования, тип оптимизации (скорость/память/читаемость), известные узкие места — потому что стратегии зависят от контекста. Она возьмёт структуру two-step и адаптирует под вашу ситуацию.

📌

Универсальный шаблон (не только код):

Анализируй {тип контента} и предложи стратегии улучшения.

[КОНТЕНТ]
{контент для оптимизации}

[ЦЕЛЬ]
{что улучшить: скорость, конверсию, читаемость, и т.д.}

[ЗАДАЧА]
1. Выдели 2-3 ключевые стратегии улучшения
2. Для каждой стратегии объясни:
   - Что конкретно изменить
   - Почему это улучшит {цель}
   - Какой эффект ожидать

Формат:
[СТРАТЕГИЯ 1] Название
Действие: ...
Почему сработает: ...
Эффект: ...

Не переписывай сразу — только стратегии.
⚠️

Ограничения

⚠️ Нужны навыки измерения результата: Метод работает когда можно объективно проверить улучшение. Для кода — замерить время выполнения. Для текстов — A/B-тесты. Без обратной связи не поймёте, сработали ли стратегии.

⚠️ Two-step дороже: Два запроса к LLM вместо одного. Для больших моделей (GPT-5) это ощутимо по деньгам и времени.

⚠️ Стратегии могут конфликтовать: Иногда оптимизация скорости ухудшает читаемость кода или увеличивает потребление памяти. Модель может предложить противоречивые стратегии — нужно выбирать приоритет вручную.

⚠️ Не для простых задач: Если задача элементарная ("замени цикл на встроенную функцию"), one-step промпт сработает так же хорошо. Two-step оправдан для сложных многоаспектных оптимизаций.

🔍

Как исследовали

Команда взяла 30,649 пар медленный → быстрый код с соревнований по программированию (Codeforces, аналог), где люди сначала решают задачу "как-то", потом оптимизируют до прохождения по времени. Это реальные траектории оптимизации, не синтетика.

Проблема датасета: в сырых данных 77,967 пар, но многие — промежуточные версии (человек отправил 10 решений, постепенно ускоряя). Непонятно, какую версию брать за "оптимальную". Исследователи оставили только финальные версии каждого пользователя. Если финальная версия всё равно в 2+ раза медленнее лучшего решения задачи — заменили на глобально лучшее (иначе модель научится плохим паттернам).

Затем автоматически извлекли стратегии с помощью Qwen2.5-32B: модель сравнивает медленный и быстрый код, описывает "что изменилось" на естественном языке. Получили описания типа "заменил cin/cout на scanf/printf для ускорения ввода-вывода" (Input/Output Throughput Optimization), "заменил string на char array, чтобы избежать динамической аллокации" (Data Structure Selection).

Ключевая хитрость — балансировка датасета: частые стратегии (Loop Optimization) встречаются в 1000 раз чаще редких (Algorithm Design). Если обучать на сыром датасете, модель запомнит "всегда оптимизируй цикл" и пропустит мощные алгоритмические оптимизации. Исследователи взвесили каждую пару по редкости стратегий (редкая стратегия = выше вес), отобрали сбалансированное подмножество 5,000 пар, где все 15 категорий представлены равномерно.

Обучили модель в two-stage режиме: 1. Supervised fine-tuning — модель учится генерировать [SUGG/] стратегии [/SUGG] [OPT/] код [/OPT] 2. GRPO (reinforcement learning) — модель в planner-режиме генерирует 4 варианта стратегий для каждого кода, большая модель (Qwen2.5-32B) реализует их, компилируют и запускают — замеряют реальное время выполнения. Награда = (ускорение)² если код компилируется и работает быстрее, −100 если не компилируется. Маленькую модель (PerfCoder) fine-tune на этих наградах, большую (optimizer) не трогают.

Что удивило: маленькая модель 1.5B параметров как планировщик + GPT-5 как исполнитель = 4.82× ускорение, притом что GPT-5 в одиночку даёт 1.96×. То есть крохотная специализированная модель, обученная думать про оптимизацию, обыгрывает флагманскую модель в её же задаче (генерация кода). Это показывает, что размер модели не компенсирует отсутствие структурированного мышления. GPT-5 мощная, но не знает "как думать про производительность" — PerfCoder знает, передаёт план, GPT-5 реализует — и вместе получается прорыв.

Почему reinforcement learning критичен: после SFT модель умеет генерировать стратегии, но не знает какие стратегии реально ускоряют код. Некоторые стратегии выглядят разумно, но не дают профита (или даже замедляют). GRPO с реальными замерами выравнивает это — модель учится генерировать стратегии, которые измеримо работают.

🔗

Ресурсы

PerfCoder: Large Language Models for Interpretable Code Performance Optimization Hongxuan Liu, Jiuding Yang, Shengyao Lu (University of Alberta); Tomasz Czajkowski, Shayan Shirahmad Gale Bagi, Zahra Fazel (Huawei Technologies); Di Niu (University of Alberta)

Бенчмарк PIE (Performance Improvement via Edits) — Shypula et al., 2024

Техника GRPO (Group Relative Policy Optimization) — Shao et al., 2024


📖 Простыми словами

PerfCoder: двухшаговая оптимизация через явные стратегии

arXiv: 2512.14018

Суть проблемы в том, что обычные нейронки — это патологические лжецы в вопросах производительности. Они отлично умеют писать код, который просто работает, но абсолютно не отстреливают разницу между «правильно» и «быстро». Для стандартной LLM код, который считает сумму чисел за секунду, и код, который делает то же самое за час, выглядят одинаково валидными, потому что в обучающей выборке функциональная корректность всегда стоит на первом месте, а глубокие рассуждения об алгоритмах встречаются редко. В итоге модель выдает тебе рабочий костыль, даже не понимая, что он будет тормозить на реальных данных.

Это как если бы ты нанял строителя, который умеет класть кирпич, но понятия не имеет о сопромате. Он построит дом, который выглядит как дом, но рухнет от первого порыва ветра, потому что он просто копировал внешний вид других зданий. PerfCoder меняет правила игры: он заставляет модель сначала поработать архитектором и составить план оптимизации, а уже потом браться за мастерок. Вместо того чтобы гадать на кофейной гуще, нейронка обязана проговорить словами: «тут мы выкидываем линейный поиск и втыкаем хеш-таблицу».

Метод работает через интерпретируемые стратегии. Сначала PerfCoder генерирует четкий список инструкций — например, заменить вложенные циклы на матричные операции или использовать бинарный поиск. Дальше есть два пути: либо он сам переписывает код по этим пунктам, либо отдает этот «рецепт» более мощной модели типа GPT-4. Это критически важно, потому что когда у модели есть логический каркас, она перестает галлюцинировать и начинает бить точно в цель. Если в задаче с парсингом 50 тысяч строк кода модель видит стратегию «используй векторизацию», она уже не предложит тебе перебирать массив вручную.

Тестировали это на Python-скриптах, но принцип универсален для любого языка программирования и даже для системного проектирования. Неважно, оптимизируешь ты SQL-запрос или микросервис на Go — разделение на «что сломалось» и «как починить» работает везде. Это переход от слепого копирования кода к осознанному алгоритмическому мышлению. По сути, мы учим AI не просто писать буквы, а понимать физику процесса, где время выполнения — такой же важный параметр, как и отсутствие синтаксических ошибок.

Короче: эпоха, когда мы просили нейронку «сделай этот код быстрее» и надеялись на чудо, заканчивается. PerfCoder доказывает, что без явного плана оптимизация — это лотерея. Если хочешь реального прироста скорости, заставляй модель сначала объяснять свои действия словами, а потом уже лезть в редактор. Либо ты контролируешь логику изменений, либо получаешь код, который формально работает, но вешает сервер при первой же нагрузке.

Работа с исследованием

Адаптируйте исследование под ваши задачи или создайте готовый промпт на основе техник из исследования.

0 / 2000
~0.5-2 N-токенов ~10-30с
~0.3-1 N-токенов ~5-15с