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
