llmbench.ru

Растеризатор 2D-сцены

Модели пишут на чистом Python растеризатор: он превращает описание сцены из прямоугольников, кругов, эллипсов, многоугольников и линий в пиксели. В сцене есть прозрачность, градиенты и аффинные преобразования. Картинку каждой модели сравнивают попиксельно с эталоном на 202 сценах и проверяют двумя замерами скорости.

29 октября 2026. 7 прогонов, 5 моделей, ещё 1 исключён из рейтинга.

тест пройденпроваленкод не запустился
1Claude Opus 5.5 (агент)202из 2022Claude Opus 5.5 (агент, effort max)202из 2023Qwen3.8-Max202из 2024Kimi K3.1 Pro202из 2025DeepSeek Flash (V4.1)202из 2026GPT-6.1 Sol202из 2027Claude Opus 5.5 (effort max)202из 20246 ручных сцен150 случайных сцен6 сцен с ошибкой
Каждое деление означает один тест. Столбцы общие для всех прогонов и отсортированы так, что слева стоят тесты, которые прошли почти все, а справа те, что не дались никому.

Как модели нарисовали контрольную сцену

Это одна и та же сцена 320×200, увеличенная вдвое: закат с градиентом, полупрозрачные горы, звёзды с правилами заливки nonzero и evenodd, повёрнутый прямоугольник, скошенный круг и линии. Переключатель «Отличия от эталона» подсвечивает красным пиксели, которые не совпали с эталоном.

Что выяснили

Правильно нарисовали все.Все шесть моделей, которые сдали код, прошли 202 сцены из 202 и нарисовали контрольную сцену пиксель в пиксель с эталоном. Задача проще первой, и её ловушки (полуоткрытые границы, правила заливки, короткие записи цвета, округление на половине) никого не поймали.

Различает их скорость кода.Opus-агент рисует 400 фигур за 0,10 секунды, Qwen за 0,14, Kimi за 0,20, DeepSeek Flash за 0,27, GPT за 0,28. Эталон делает это за 0,45, так что пять моделей из шести написали код быстрее нашего. Opus через API не отсекал фигуры по рамке и не уложился в лимит.

Быстрый код не значит быстрый ответ.Qwen написал второй по скорости растеризатор, но думал над ним 27,5 минуты. DeepSeek Flash ответил за 2 минуты 20 секунд, и его код всего вдвое медленнее.

Глубина размышления снова решила спор двух Opus.Агентом Opus думал около 10 минут и написал самый быстрый код. Через API с адаптивным мышлением он ответил за 34 секунды почти без рассуждения: код правильный, но медленный.

Шлюз мешает длинным ответам.Партнёрский шлюз дважды оборвал поток посреди рассуждения: один раз у GPT, несколько раз у Grok. У прямых API провайдеров таких обрывов не было.

Все прогоны

МестоМодельТестыЛовушкиСлучайныеОшибкиСкоростьВремяРассуждениеВсего токеновТокенов/сСтрок кодаС правкой
🥇 1Claude Opus 5.5 (агент)202 (100.0%)46/46150/1506/62/210 мин 29 с72K*82K130*777—
🥈 2Claude Opus 5.5 (агент, effort max)202 (100.0%)46/46150/1506/62/253 мин 16 с350K*355.6K111*602—
🥉 3Qwen3.8-Max202 (100.0%)46/46150/1506/62/227 мин 25 с55.9K66.5K401229—
4Kimi K3.1 Pro202 (100.0%)46/46150/1506/62/211 мин 42 с18K21.2K30403—
5DeepSeek Flash (V4.1)202 (100.0%)46/46150/1506/62/22 мин 20 с23.3K26.5K190426—
6GPT-6.1 Sol202 (100.0%)46/46150/1506/62/24 мин 28 сскрыто11.6K43348—
7Claude Opus 5.5 (effort max)202 (100.0%)46/46150/1506/61/234 с03.8K111287—

В колонке «С правкой» указан результат того же кода после исправления одной-двух строк, он нужен только для понимания. Звёздочка означает оценку. «Токенов/с» показывает, как быстро модель пишет: все токены ответа, включая рассуждение, делённые на полное время ответа.

Время и токены

Время ответа

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

0 мин10 мин20 мин30 мин40 мин50 мин60 минClaude Opus 5.5 (агент)10 мин 29 сClaude Opus 5.5 (агент, effort max)53 мин 16 сQwen3.8-Max27 мин 25 сKimi K3.1 Pro11 мин 42 сDeepSeek Flash (V4.1)2 мин 20 сGPT-6.1 Sol4 мин 28 сClaude Opus 5.5 (effort max)34 с

Сколько модель написала

рассуждениекод и ответпровайдер скрывает разбивку
0K20K40K60K80K100K120K140K160K180K200K220K240K260K280K300K320K340K360KClaude Opus 5.5 (агент)82KClaude Opus 5.5 (агент, effort max)355.6KQwen3.8-Max66.5KKimi K3.1 Pro21.2KDeepSeek Flash (V4.1)26.5KGPT-6.1 Sol11.6K, разбивка скрытаClaude Opus 5.5 (effort max)3.8K

Разбор по участникам

Claude Opus 5.5 (агент)Anthropic, claude-opus-5-5
202 сцены из 202 и оба замера скорости, причём быстрее всех: 400 фигур на холсте 800×600 он рисует за 0,10 секунды, а крупные полупрозрачные фигуры с градиентом за 0,13. Это в 4–6 раз быстрее эталона. Агент работал вслепую: одно чтение задания, одна запись решения, код ни разу не запускался (протокол проверен). Прогон занял 10,5 минуты, код самый длинный, 777 строк: модель потратила их на быстрые пути для каждого типа фигуры.
Claude Opus 5.5 (агент, effort max)Anthropic, claude-opus-5-5
202 сцены из 202 и оба замера скорости, 0,08 и 0,22 секунды. Результат тот же, что у агента с уровнем по умолчанию, но думал он в пять раз дольше: 53 минуты и около 350 тысяч токенов рассуждения против 10 минут и 72 тысяч. Opus через API на том же effort: max за 34 секунды написал код, который не уложился во второй замер. Протокол соблюдён: одно чтение задания и одна запись решения.
Qwen3.8-MaxAlibaba, qwen3.8-max
202 сцены из 202 и оба замера скорости, 0,14 и 0,17 секунды: это второй по скорости код после Opus-агента. Зато ответ занял больше всех, 27,5 минуты, из них около 56 тысяч токенов ушло на рассуждение, а код вышел самым длинным среди API-моделей, 1229 строк. В первом тесте Qwen подвела одна опечатка, здесь ошибок нет.
Kimi K3.1 ProMoonshot AI, kimi-k3.1-pro
202 сцены из 202 и оба замера скорости, 0,20 и 0,30 секунды, второе место по скорости кода. Ответ занял 11,7 минуты, из них около 18 тысяч токенов ушло на рассуждение. Код компактный, 402 строки.
DeepSeek Flash (V4.1)DeepSeek, deepseek-flash
202 сцены из 202 и оба замера скорости, 0,27 и 0,41 секунды, это тоже быстрее эталона. После провала в первом тесте из-за опечатки здесь всё чисто. Ответ пришёл за 2 минуты 20 секунд, это самый быстрый из безошибочных прогонов, на рассуждение ушло 23 тысячи токенов.
GPT-6.1 SolOpenAI, gpt-6.1-sol
202 сцены из 202 и оба замера скорости, 0,28 и 0,60 секунды. Первая попытка оборвалась на стороне шлюза на 115-й секунде без ответа, вторая прошла за 4,5 минуты. Код 347 строк.
Claude Opus 5.5 (effort max)Anthropic, claude-opus-5-5
202 сцены из 202, но только один замер скорости из двух. Растеризатор правильный, однако каждая фигура проверяется по всему холсту без отсечения по её рамке, поэтому 400 фигур на 800×600 не уложились даже в 60 секунд. Ответ пришёл за 34 секунды, это самый короткий код (286 строк), и адаптивное мышление снова почти не включалось.

Как устроен тест

Задание

Нужно написать функцию render(scene), которая возвращает картинку как список строк пикселей (r, g, b). Пиксель закрашивается, если его центр лежит внутри фигуры. Фигуры бывают пяти видов: прямоугольник с полуоткрытыми границами, круг, эллипс, многоугольник с правилами заливки nonzero и evenodd и толстая линия. Цвет задаётся в форматах #rgb, #rgba, #rrggbb и #rrggbbaa, у фигуры может быть opacity, линейный градиент и аффинное преобразование. Цвета смешиваются по формуле floor(src*α + dst*(1-α) + 0.5).

Напиши на Python 3.12 растеризатор двумерной сцены: один модуль, только стандартная библиотека. Сторонние библиотеки (PIL, numpy и любые другие) использовать нельзя.

## Интерфейс

```python
def render(scene: dict) -> list[list[tuple[int, int, int]]]:
    ...
```

Функция возвращает картинку как список строк сверху вниз. Каждая строка это список пикселей слева направо, каждый пиксель это кортеж `(r, g, b)` из целых чисел от 0 до 255. Элемент `result[j][i]` соответствует пикселю в столбце `i` и строке `j`.

## Сцена

```python
{
  "width": 320, "height": 200,          # размер холста в пикселях
  "background": "#0b1d3a",              # цвет фона
  "shapes": [ {...}, {...} ]            # фигуры, рисуются по порядку, каждая следующая поверх предыдущих
}
```

## Координаты и пиксели

Ось x направлена вправо, ось y вниз. Пиксель `(i, j)` занимает квадрат от `i` до `i+1` по x и от `j` до `j+1` по y. Пиксель закрашивается фигурой, если **центр пикселя** `(i + 0.5, j + 0.5)` лежит внутри фигуры. Сглаживания нет.

## Цвета

Цвет задаётся строкой: `#rgb`, `#rgba`, `#rrggbb` или `#rrggbbaa`, шестнадцатеричные цифры в любом регистре. В коротких формах каждая цифра удваивается (`#a3f` означает `#aa33ff`). Если альфа не указана, она равна 255. У фона альфа игнорируется, фон всегда непрозрачный. Любая другая строка считается ошибкой.

## Фигуры

У каждой фигуры есть поле `type` и поле `fill` (цвет или градиент). Необязательные поля: `opacity` (число от 0 до 1, по умолчанию 1) и `transform` (см. ниже). Все координаты фигуры заданы в её локальной системе.

- `rect`: поля `x`, `y`, `w`, `h`. Точка внутри, если `x <= px < x + w` и `y <= py < y + h`. При `w <= 0` или `h <= 0` фигура пустая.
- `circle`: поля `cx`, `cy`, `r`. Точка внутри, если `(px - cx)² + (py - cy)² <= r²`.
- `ellipse`: поля `cx`, `cy`, `rx`, `ry`. Точка внутри, если `((px - cx) / rx)² + ((py - cy) / ry)² <= 1`. При `rx <= 0` или `ry <= 0` фигура пустая.
- `polygon`: поле `points` (список точек `[x, y]`, не меньше трёх, многоугольник замкнут) и необязательное `fill_rule`: `"nonzero"` (по умолчанию) или `"evenodd"`. Принадлежность точки определяется лучом из неё вправо. Ребро `(x0, y0) → (x1, y1)` пересекает луч, если `y0 <= py < y1` или `y1 <= py < y0`, и при этом `x0 + (py - y0) * (x1 - x0) / (y1 - y0) > px`. Каждое такое ребро добавляет к числу оборотов `+1`, если `y1 > y0`, иначе `-1`. Для `nonzero` точка внутри, если сумма не равна нулю, для `evenodd` точка внутри, если число пересекающих рёбер нечётное.
- `line`: поля `x1`, `y1`, `x2`, `y2`, `width`. Точка внутри, если расстояние от неё до отрезка не больше `width / 2`. Если концы совпадают, получается круг.

## Преобразование

`transform` задаётся шестью числами `[a, b, c, d, e, f]` и переводит локальную точку `(x, y)` в точку холста `(a*x + c*y + e, b*x + d*y + f)`. Чтобы проверить пиксель, его центр переводится обратным преобразованием в локальные координаты, и проверка идёт там. Поэтому круг под масштабом становится эллипсом, а толщина линии масштабируется вместе с ней. Если преобразование вырожденное (`a*d - b*c == 0`), фигура не рисуется. Без `transform` локальные координаты совпадают с координатами холста.

## Градиент

```python
{"type": "linear", "x1": 0, "y1": 0, "x2": 100, "y2": 0, "stops": [[0, "#000"], [0.5, "#f00"], [1, "#fff"]]}
```

Координаты градиента тоже локальные. Для точки `p` параметр `t` равен скалярному произведению `(p - p1)` на `(p2 - p1)`, делённому на `|p2 - p1|²`, и обрезается до отрезка `[0, 1]`. Если `p1` совпадает с `p2`, то `t = 0`. Точки остановки `stops` идут по возрастанию смещения. Если `t` не больше первого смещения, берётся первый цвет. Если не меньше последнего, берётся последний. Иначе берутся соседние остановки с `o_i <= t <= o_{i+1}`, и каждый канал, включая альфу, интерполируется линейно, без округления на этом шаге. Если две соседние остановки стоят в одной точке, берётся цвет второй. Пустой список `stops` считается ошибкой.

## Наложение цветов

Для закрашиваемого пикселя берётся цвет заливки `(r, g, b, a)` в этой точке. Непрозрачность равна `α = a / 255 * opacity`. Каждый канал холста заменяется на `floor(src * α + dst * (1 - α) + 0.5)`, где `dst` это текущее целое значение канала. Результат ограничивается отрезком от 0 до 255.

## Ошибки

Неверный цвет, неизвестный тип фигуры, многоугольник меньше чем из трёх точек и градиент без остановок должны вызывать `ValueError`.

## Производительность

Холст 800×600 с 400 небольшими фигурами и холст 640×480 с несколькими крупными полупрозрачными фигурами и градиентом должны рисоваться не дольше 4 секунд каждый на обычном ПК.

## Формат ответа

Ответь ТОЛЬКО кодом модуля в одном блоке ```python.
Как проверяли
  • 46 ручных сцен с ловушками. Среди них полуоткрытые границы прямоугольника и включительная граница круга, короткие записи цвета #abc и #f808, самопересекающаяся звезда с разными правилами заливки, вершины ровно на центрах пикселей, вырожденное преобразование, круг под масштабом, который становится эллипсом, толщина линии под масштабом, градиенты с обрезкой, со ступенькой и с совпадающими точками, а также смешивание цветов ровно на половине, где round() в Python даёт другой ответ.
  • 150 случайных сцен из генератора с фиксированным seed, в каждой от 2 до 9 фигур с прозрачностью, градиентами и преобразованиями.
  • 6 сцен, которые обязаны закончиться ошибкой ValueError: неверные цвета, неизвестный тип фигуры, многоугольник из двух точек, градиент без остановок.
  • 2 замера скорости: 400 небольших фигур на холсте 800×600 и несколько крупных полупрозрачных фигур с градиентом на холсте 640×480. На каждый даётся 4 секунды, эталон укладывается в 0,5 и 0,8 секунды.
  • Картинка сравнивается с эталоном попиксельно. Разница в 1 единицу по каналу допускается, потому что формулы можно записать по-разному. Сцена засчитывается, если не совпало не больше 0,1% пикселей, но не меньше трёх, это запас на центры пикселей ровно на границе фигуры.
  • Сам стенд проверен эталоном: он проходит 202 сцены из 202 и оба замера скорости.
Условия
  • Участвуют модели, которые дали рабочий код в первом тесте, плюс Grok 4.7. Каждая получила задание слово в слово, одним сообщением, без системного промпта и без инструментов, и не могла запустить свой код.
  • Параметры рассуждения такие же, как в первом тесте: у Qwen включён enable_thinking, у GPT и Grok reasoning_effort: high, Opus через API получал thinking: adaptive и effort: max через нативный /v1/messages, Kimi и DeepSeek работали в режиме по умолчанию.
  • Opus 5.5 дополнительно решал задачу агентом Claude Code с чистым контекстом. Ему разрешено одно чтение файла задания и одна запись решения, запускать код нельзя.
  • В зачёт идёт код как есть. Вариант с правкой одной строки считается отдельно, только для понимания.
  • Время считается от отправки запроса до последнего токена и зависит от загрузки серверов провайдера.
Нюансы
  • Эталонный растеризатор написан по тексту задания, и стенд проверен им самим: 202 сцены из 202 и оба замера скорости за 0,45 и 0,83 секунды.
  • При одинаковом числе сцен и замеров место определяет суммарное время двух замеров скорости.
  • Первая попытка GPT-6.1 Sol оборвалась на шлюзе на 115-й секунде без ответа, засчитана вторая.
  • Grok 4.7 через партнёрский шлюз не смог закончить ни одну задачу: его потоки обрывались посреди рассуждения, поэтому он в разделе исключённых.
  • Время и токены Opus-агента оценочные, по объёму кэша контекста. Протокол агента проверен: одно чтение задания и одна запись решения.
  • Opus-агент с effort: max добавлен 29.10.2026, после основного прогона, по тому же протоколу: одно чтение задания и одна запись решения, без запуска кода. Его запустили, чтобы сравнить с Opus через API на том же effort: max: через партнёрский шлюз модель рассуждает заметно меньше.
Исключены из рейтинга

Эти прогоны не попали в рейтинг: результат определила не модель, а условия запуска. Ответы и код сохранены в папке.

  • Grok 4.7 (0 из 202): Партнёрский шлюз каждый раз обрывал поток посреди рассуждения, и модель не успевала выдать ни строки кода. Это проблема доступа, а не модели. Grok стоит проверить через прямой API xAI. Две попытки оборвались на 652-й и 840-й секунде.
Участники и доступ
МодельРазработчикIDДоступЛимит ответа
Claude Opus 5.5 (агент)Anthropicclaude-opus-5-5субагент Claude Code, чистый контекст, без запуска кода—
Claude Opus 5.5 (агент, effort max)Anthropicclaude-opus-5-5субагент Claude Code, effort: max, чистый контекст, без запуска кода—
Kimi K3.1 ProMoonshot AIkimi-k3.1-proAPI api.moonshot.ai (через VPN роутера)128K
GPT-6.1 SolOpenAIgpt-6.1-solпартнёрский шлюз, reasoning_effort: high128K
Qwen3.8-MaxAlibabaqwen3.8-maxAPI token-plan.maas.qwencloudapi.com131.1K
Claude Opus 5.5 (effort max)Anthropicclaude-opus-5-5партнёрский шлюз, нативный /v1/messages, thinking: adaptive, effort: max128K
DeepSeek Flash (V4.1)DeepSeekdeepseek-flashAPI api.deepseek.com384K
Grok 4.7xAIgrok-4.7партнёрский шлюз, reasoning_effort: high128K