Тензорные ядра RTX 3060 разблокированы: прирост 83 %, но на квантованной модели он почти исчезает
23 октября 2026 года в репозиторий Zagitta/gpu-unlock приняли поддержку GA106, то есть RTX 3060. К тому времени мы уже почти сутки изучали собственную карту. Мы успели сделать замеры до и после разблокировки и получили данные, которых нет в чужих отчётах.
Итог в двух словах: производительность FP16 на матрице 8192³ выросла с 27,1 до 49,5 TFLOPS (×1,83). Контрольный FP32 не изменился даже на десятую долю. На нашей квантованной модели прирост нулевой. На квантованном стеке в целом он составляет около пяти процентов, но об этом отдельно ниже. Оба результата получены на одной карте и одним и тем же скриптом.
Эта статья не инструкция по воспроизведению. Она о том, как отличить реальное ускорение от эффектной цифры, и о том, почему на это у нас ушло двое суток.
Что на самом деле ограничивают в «урезанных» картах
Когда говорят об «урезанных картах», обычно смешивают два разных явления. Это первая ловушка.
|
|
Что ограничивают |
Чем |
Обратимо ли |
|---|---|---|---|
|
Отбраковка |
количество SM, ширину шины, объём VRAM |
фьюзы и лазерная подрезка на заводе |
нет, это физическое ограничение |
|
Гейтинг |
скорость конвейеров |
регистр-селектор, значение которого пересчитывается при каждом холодном старте |
да, пока не загружен драйвер |
Отбраковка честна: кристалл с двумя неисправными SM не выбрасывают, а продают как младшую модель. Гейтинг же служит маркетинговой сегментации. Один и тот же кристалл попадает в RTX 3090, в 3080 Ti и в A6000, и чтобы A6000 не покупали по цене 3090, на неё ставят замок.
Этот замок хранится в регистрах, которые прошивка карты вычисляет заново при каждой подаче питания. Любое значение, которое каждый раз считается с нуля и до поры не защищено, может перезаписать кто-то другой. Окно для этого ровно одно: между подачей питания и загрузкой драйвера.
На GA102 и GA106 за это отвечают три регистра в BAR0:
|
Регистр |
Смещение |
Назначение |
|---|---|---|
|
|
|
маска привилегий: младшие 4 бита определяют чтение по уровням, следующие 4 бита определяют запись |
|
|
|
восемь 4-битных полей: DP, FFMA, FMLA16, FMLA32, IMLA0…3 |
|
|
|
единственное поле, IMLA4 |
Порядок имён в таблице не следует считать строгим: апстрим перечисляет набор полей, но не их позиции. Поэтому мы читаем значения, но не привязываем имена к конкретным нибблам.
Холодное значение FEAT_OVR_PLM одинаково у всех GA10x, для которых у нас есть логи (GA102 и GA106): 0xffffff8f. Младший байт 1000 1111 означает, что читать могут все четыре уровня, а писать — только L3. Поэтому модуль не обращается к селекторам напрямую. Сначала он повышает уровень привилегий и лишь затем записывает во все поля нужную скорость.
В каждом поле старший бит служит флагом «override включён», а три младших задают скорость (00 — полная, 01 — половина, 10 — четверть, 11 — одна восьмая; два последних значения автор репозитория не подтверждал). Отсюда вытекает деталь, которую легко понять наоборот: 7 и 8 не являются соседними ступенями одной шкалы. Значение 7 — это 0111: override выключен, и младшие биты ничего не определяют. Значение 8 — это 1000: override включён, скорость полная. Числа, различающиеся на единицу, отвечают на разные вопросы и не описывают разную скорость.
Разведка перед записью
Мы начали с чтения, и это было верное решение не из осторожности, а в силу самой структуры задачи. У инструмента есть проверки, которые срабатывают до первой записи в карту. Их можно проверить заранее тем же доступом на чтение. Если первая из них не пройдёт, писать вообще не придётся.
Первым делом модуль разбирает VBIOS самой карты по смещению 0x300000 в BAR0 и берёт оттуда четыре поля: engine_mask, ucode_id, sig_count, sig_versions. У нас есть готовый пробник только для чтения (gpu_probe.py, отдельный от модуля). Он разбирает этот заголовок и проверяет условия в том же порядке, в каком их проходит модуль.
Вот что он выдал на нашей карте:
FWSEC geometry: engine=0x400 ucode=9 signatures=3 versions=0x7
bytes=1152 imem=0xe200 dmem=0x800
image_off=0x416bc size=0xea00
Теперь это нужно с чем-то сопоставить. В репозитории есть интеграционный тест с числами, снятыми с реального PROM платы GA102. Оговорка, без которой эти цифры значат больше, чем должны: блок с эталоном выполняется, только если тесту передан дамп PROM (в коде это if (argc == 2), рядом стоит комментарий «Optional integration check; normal tests contain no board-owned blobs»). В обычном прогоне эти строки не исполняются. Перед нами зафиксированное ожидание из чужого дампа, а не проверка, которая сработает у любого, кто клонирует репозиторий. Тем не менее свои значения с ними сравнить можно, и это полезно.
|
Поле |
GA102 (эталон) |
Наша GA106 |
|
|---|---|---|---|
|
|
|
|
совпало |
|
|
|
|
совпало |
|
|
|
|
совпало |
|
|
|
|
совпало |
|
|
|
|
совпало |
|
|
|
|
различается |
|
|
|
|
различается |
|
|
|
|
различается |
Совпали именно те поля, на основании которых модуль принимает решения: engine_mask (единственное допустимое значение — 0x400), ucode_id (определяет выбор фьюза), sig_versions (определяет слот подписи), а также sig_count и dmem. Расходятся три поля, описывающие сам образ: размер imem, смещение образа и его размер.
Это не погрешность замера, а ответ на вопрос, почему нам не потребовалось собирать собственный payload. Модуль не сверяет эти три поля с константами, а берёт их из ROM карты (memcpy(image, rom + fw.image_off, fw.image_size), при этом fw.imem_size передаётся при запуске Falcon). Всё различающееся считывается с платы, а чужими остаются только загрузчик и подпись. Поэтому ассеты от GA102 подошли к GA106 без единой правки.
Одно наблюдение мы приводим именно как наблюдение, а не как вывод: наши значения перекликаются с чужими крест-накрест. Наш imem = 0xe200 равен чужому image_size = 0xe200. Это повод не считать наш разбор полей окончательно верным. На сделанный выше вывод это не влияет (условие допуска завязано на engine_mask, а геометрия читается с самой карты). Но тем, кто будет сверять всё построчно, лучше знать, где у нас остались сомнения.
Вторая находка пробы: engine_mask = 0x400 — единственное значение, которое модуль принимает. Всё остальное он отвергает. Окажись там другое число, эксперимент завершился бы на чтении: ноль записей и честный ответ «на этой плате так нельзя».
Все проверки были пройдены. Только после этого мы собрали модуль.
Окно возможностей и холодная карта
Схема запуска выглядит так:
питание -> ROM платы -> FWSEC -> Booter -> GSP -> драйвер
| |
| +-- здесь карта принимает подпись
+-- здесь поднимается WPR2
Модуль встраивается в тот момент, когда драйвер ещё не привязан к карте. Отсюда требование, которое легко принять за суеверие: полностью выключать питание, а не перезагружаться.
Помехой становится не сама перезагрузка, а состояние, в которое карту привёл драйвер. Писать можно только в том цикле питания, в котором драйвер ещё ни разу не поднимал WPR2. Модуль сообщает об этом прямо: card already initialised since power on (WPR2 enabled); power off first. Тёплая перезагрузка в Linux селекторы не сбрасывает (это следует из чужого отчёта, о нём в разделе про отрицательный результат), но окно заново не открывает. Оно закрылось при первой загрузке драйвера, а не при выключении.
Для проверки мы сделали live-USB с Ubuntu, где nouveau занесён в чёрный список, а драйвер NVIDIA вообще не загружается. Благодаря этому карта остаётся нетронутой вплоть до момента запуска.
Три полезных подводных камня, каждый из которых стоил нам времени:
Первый. Каталог /media/ubuntu появляется лишь после монтирования флешки. Загрузочная флешка Ubuntu монтируется в /media/cdrom и только на чтение. Логи, которые пишутся «рядом со скриптом», при зависании пропадают. Решение: fsync после каждой строки и вторая флешка для записи.
Второй. Команда sudo -i открывает логин-шелл в домашнем каталоге root и не наследует текущую папку. Связка cd /media/... && sudo -i приведёт вас в /root, а не туда, куда вы рассчитывали.
Третий. Перед insmod нужно убедиться, что карту не занял драйвер. Правильная команда — lspci -nnk -s 01:00.0, а не -d 10de:01:00.0. Второй вариант — это фильтр «вендор:устройство», он вернёт пустой вывод, а пустоту легко истолковать как «драйвер не привязан».
Замеры
Скрипт замера использовался один и тот же: файл копировался на флешку и запускался и в Linux, и в Windows. Хеш зафиксирован в манифесте для Linux-прогона, а для Windows-копии мы сверку по хешу не выполняли. Это не мелочь, а существенная оговорка: без неё «тот же скрипт» остаётся словами, а не фактом.
Протокол: GEMM 4096³ и 8192³, плотная матрица, накопление в FP32, медиана из 20 прогонов после 3 прогревочных, CuPy 14.2.0 с cuBLAS из wheel.
|
Тест |
До |
После |
|
|---|---|---|---|
|
fp16 8192³ |
27,1 |
49,5 |
×1,83 |
|
fp16 4096³ |
23,9 |
46,5 |
×1,95 |
|
fp32 8192³ (контроль) |
9,9 |
9,9 |
×1,00 |
|
fp32 4096³ (контроль) |
7,8 |
7,8 |
×1,00 |
Отношение fp16/fp32: 2,74 → 5,00.
Контроль не сдвинулся даже на десятую. Это не декорация: без неподвижного контроля фраза «стало быстрее» может означать что угодно, в том числе то, что вы измерили не тот конвейер.
Питание и частота, выборка каждые 200 мс:
|
|
До |
После |
|---|---|---|
|
частота ядра |
не сэмплировалась |
1747–1777 МГц под нагрузкой (12 сэмплов от 150 Вт, медиана 1762); выше 1900 только при недогрузке |
|
пик мощности |
170 Вт, то есть упёрлась в лимит |
170,7 Вт при лимите 170 |
Лимит питания нашей платы зашит в VBIOS: Max Power Limit = Default = 170. Через nvidia-smi его не поднять, поэтому по мощности карта упирается в потолок в обеих сессиях.
Частота «до» отсутствует в таблице не случайно: в первой сессии nvidia-smi dmon записывался без колонки частот. Поэтому 1891 МГц для «до» — это вывод из 27,1 TFLOPS, а не измерение, и сопоставлять его с сэмплом нельзя. Зато сэмпл «после» даёт независимую проверку главного утверждения. Если по 49,5 TFLOPS и частоте под нагрузкой (1747–1777 МГц) рассчитать, сколько операций на SM за такт выполняет карта, получится 995–1012 против ожидаемых 1024. Удвоение видно не только в TFLOPS: оно согласуется с частотой, которую измерял отдельный прибор, а не тот же самый скрипт.
Как убедиться, что прибор измеряет именно то, что нужно
Самым полезным приёмом за все двое суток оказался бесплатный: предсказать базовую линию из первых принципов.
У GA106 28 SM, 512 флоп на SM за такт для FP16 с накоплением FP32 (это как раз та половина, которую ограничивали), частота буста около 1,89 ГГц.
28 × 512 × 1,89 = 27,2 TFLOPS (предсказание)
замер = 27,1 TFLOPS
Значения совпали. Это значит, что cuBLAS выбрал именно тот путь, который и удваивается, а не какой-то иной. Тот же приём можно проверить и на чужой карте: 84 SM × 512 × 1,384 ГГц = 59,5 против 59,6, измеренных на 3090 Ti в чужом отчёте.
Без этого шага «27,1» — просто число. С ним это уже утверждение о том, что именно вы измеряете.
Чего это ускорение не даёт
Теперь начинается неприятная часть, ради которой и стоило писать эту статью.
В том же PR, на такой же карте, автор запустил llama.cpp с квантованной моделью:
gemma-4-12B Q4_K_XL, RTX 3060:
pp512 1460,5 -> 1467,1 tok/s (+0,5 %, шум)
tg128 43,63 -> 43,65 tok/s (+0,05 %, шум)
На этой модели и в этом профиле прирост нулевой. Квантованный путь в llama.cpp проходит не через тот конвейер, который переключает unlock.
Что именно там происходит, этот замер не показывает: он лишь говорит, что выигрыша нет. INT8 на Ampere — отдельный путь со своими полями в селекторах (IMLA0…4), и его пиковую производительность мы не измеряли. Подтверждённого замера, который показал бы, какое именно ядро выполняет конкретный тип квантованного матмула в ggml на sm_86, у нас нет, и подменять его догадкой мы не станем.
Второе ограничение, не связанное с квантами: декодирование упирается в пропускную способность памяти. У 3060 это 360 ГБ/с на 192-битной GDDR6. Селектор регулирует скорость конвейеров, а не памяти, поэтому на пошаговую генерацию токенов unlock не влияет вовсе.
Мы рассчитывали, что prefill (обработка промпта) даст выигрыш, и отчасти это верно: по логам нашего движка на 37 запросах подряд prefill занимает 26 % времени, а при промахе кэша промпта доля доходит до 51 % и 95 %. Но 26 % времени не превращаются в 13 % ускорения, если внутри этих 26 % работают не те ядра.
Где ноль перестаёт быть нулём. Ноль справедлив для квантованного пути и для декодирования, но универсальным он не является: прирост равен доле математики bf16/fp16/tf32 в нагрузке. Это видно по чужим замерам, опубликованным alesha pro (числа его, мы их не перепроверяли): bf16 на тензорных ядрах 82 → 155 TFLOPS (×1,89), cuBLAS BF16 GEMM 8192³ 64 → 99, TF32 41 → 79 (×1,93). На реальной нагрузке, Strata с Qwen3.8 Flash-Next на двух картах, prefill дал +12 % на 4K и 10K и +10 % на 90K (3205 → 3536 т/с). Автор при этом прямо оговаривает, что для этого движка случай почти худший: основная часть prefill там приходится на int8 и копирования.
Есть и ещё одна точка, которая уточняет нашу прежнюю формулировку. В том же чужом отчёте есть замер на int8-стеке: vLLM с Qwen 27B (W4A8 Marlin). Профилирование показало около 29 % времени GPU в BF16/FP16-ядрах с накоплением FP32, а сквозной выигрыш составил около 5 %, на грани шума между прогонами. Иначе говоря, на квантованном стеке выигрыш не нулевой, а небольшой, потому что таких ядер там меньше трети. Это же объясняет, почему формулировка «ноль для квантованного инференса» шире замера. Верная звучит так: ноль для нашего профиля.
Итого на одной кривой шесть точек: наш ноль на Gemma Q4 в llama.cpp, наш ×1,83 на чистом FP16 GEMM, чужие ×1,89 и ×1,93 на 3090, чужие +10–12 % на живом движке и чужие +5 % на стеке, который уже опирается на int8. Наш ноль не опровергает кривую, а лежит на одном из её концов, и утверждать по нему, что «и всё остальное тоже ноль», было бы неправдой.
Отрицательный результат, который стоит зафиксировать
Мы проверили, переживут ли селекторы переход в Windows.
План был таким: разблокировать карту в Linux, не отключая питание, выполнить reboot, выбрать Windows и прогнать тот же скрипт. То, что питание между сессиями действительно не отключалось, мы тогда не зафиксировали, и это оказалось главной дырой в тесте.
Windows 10, CuPy 14.2.0, CUDA API 13.40, тот же gemm_bench.py:
fp16 8192³ = 27,1 и 27,0 TFLOPS
fp32 8192³ = 9,9 и 9,9
Это в точности сток. При этом по чужому отчёту тёплая перезагрузка в Linux селекторы сохраняет: там отношение TFLOPS на мегагерц после ребута не изменилось, то есть сам по себе ребут их не стирает.
Различающий тест короток, но мы его не провели: разблокировать в Linux, прочитать FEAT_OVR_SM_SPD, выполнить reboot (не poweroff), сразу загрузить Windows и прогнать тот же скрипт. Результат около 43–48 TFLOPS означал бы, что селекторы живы и обход до загрузки ОС не нужен. Результат около 27 при подтверждённой непрерывности питания означал бы, что их сбрасывает инициализация драйвера.
Практическая рекомендация на сегодня: либо отдельный диск с Linux, либо подход, работающий до загрузки ОС. Второй вариант уже реализован другими: есть UEFI-решение для Windows, которое стартует до bootmgr, разблокирует карту и передаёт управление дальше. Автор проверил его на одной системе (RTX 3090 FE, BIOS ASUS 3057), и для работы требуются отдельный EFI-раздел, отключённый Secure Boot и снятый BitLocker. Для 3060 готового проверенного варианта там нет.
Что остаётся неизвестным
-
GA106 и квантованный инференс. Ни у кого нет замера, который разделил бы «int8-ядра» и «деквантование в fp16» для конкретного ядра ggml на sm_86. Ближайшее, что есть, — чужой профиль int8-стека (около 29 % времени в BF16/FP16-ядрах, около 5 % сквозного выигрыша), и он не относится к ggml.
-
Потолок питания. У 3060 значение
Max Power Limitзависит от платы и, по внешним отчётам, бывает от 170 до 212 Вт. У нашей платы оно заблокировано на 170, и поднять его нельзя. Возможно, у кого-то есть запас, но проверить это можно только собственной командойnvidia-smi -q -d POWER. -
Что мы не сделали. Мы не прог
Новый драйвер Nvidia вызвал проблемы: владельцы GeForce RTX 5080 и RTX 4090 жалуются на чёрный экран и зависания
Разработчик установил iOS 16.5 на Xiaomi Mi 8, и смартфон стал похож на iPhone
Флагманская камера, зарядка на 100 Вт, аккумулятор на 5700 мАч и разогнанный чип: стали известны характеристики Huawei Pura 90 Plus
Батареи уменьшились, а цены? Xiaomi 18 Pro и Xiaomi 18 Pro Max добрались до Европы
США стремятся опередить Китай в лунной гонке: космическая программа набирает темп
Американские власти годами обращались к Маску с просьбами включать и отключать Starlink на Украине и на Ближнем Востоке
Склад аэропорта опустошили: воры унесли поддоны с RTX 5090, а часть карт потом нашлась на OLX
От неприятия к тревоге: ведущие американские операторы выступили единым фронтом против Starlink Mobile и добиваются ограничений для конкурента