GigaAM-Multilingual large_ctc перенесена с PyTorch на MLX для запуска на Apple Silicon. Порт включает четыре варианта весов: FP16, INT8, INT6 и INT4.

Сравнение показывает, сколько места и памяти требует каждый вариант, как быстро он распознает речь и где снижение разрядности меняет текст. Первый аудиопример содержит единственное расхождение INT8 с FP16 на выборке из 255 русских записей.

Аудио и эталон взяты из тестовой части русского набора google/fleurs, лицензия CC BY 4.0. Для подсчета качества текст приведен к нижнему регистру и очищен от пунктуации.

Главное кратко

4 варианта весов FP16, INT8, INT6, INT4
1,95 с пятиминутное аудио минимальная задержка у FP16
699 МБ INT8 на диске 877 МБ, максимум оперативной памяти
+4,4% ускоренный механизм внимания встроенная SDPA, полный проход INT8
Замеры выполнены на MacBook Pro с M4 Pro. INT8 выбран вариантом по умолчанию как баланс качества, размера и потребления памяти.

Как разрядность весов влияет на текст

INT8 изменил одну из 255 расшифровок относительно FP16, INT6 изменил семь, INT4 изменил 31. Это число показывает отличия от FP16, а не обязательно ошибки относительно эталона. Два примера ниже показывают оба случая: изменение обычного слова и разные варианты записи названия группы.

Еще один реальный пример · 8,34 с

Одно слово изменилось только в INT4

Эталон
Если вы хотите находиться рядом со сценой, вам нужно приехать заранее, чтобы найти место для кемпинга вблизи от музыки.
FP16 · INT8 · INT6
Совпало с эталоном после нормализации.
INT4
…чтобы найти место для кэмпинга вблизи от музыки.В эталоне: «кемпинга».
Еще один реальный пример · 5,46 с

Разрядность изменила запись названия Aerosmith

Эталон
Группа Aerosmith отменила оставшиеся концерты в своем турне.
FP16 · INT8
Группа Аэросмит отменила оставшиеся концерты в своем турне.
INT6
Группа Айросмит отменила оставшиеся концерты в своем турне.
INT4
Группа Айро Смит отменила оставшиеся концерты в своем турне.Название разделилось на два слова.
Примеры выбраны среди несовпадающих ответов. Эталон пишет Aerosmith латиницей, а модель передает произношение кириллицей, поэтому буквальное сравнение считает отличием даже понятный вариант. Общую частоту ошибок показывает WER (Word Error Rate, доля ошибок в словах) по всему набору.

Что находится внутри модели

GigaAM-Multilingual поддерживает русский, казахский, кыргызский, узбекский и английский языки. Для переноса выбран опубликованный вариант large_ctc. В нем около 600 млн параметров и 24 блока Conformer. Эти блоки находят связи в звуке. Затем CTC (Connectionist Temporal Classification) превращает их выход в последовательность символов без заранее заданной привязки каждого звука ко времени.

MLX выполняет вычисления на центральном и графическом процессорах Apple Silicon. Оба процессора используют общую память Mac. Чтобы порт вел себя как исходная модель, в MLX повторен весь путь звука: подготовка признаков, формы многомерных массивов, учет позиции, маскирование и преобразование результата в текст.

GigaAM-Multilingual large_ctc От звуковой волны к строке текста
Вход Звук 16 000 отсчетов в секунду
Признаки Частотная карта частоты во времени
Сжатие времени Две свертки число шагов уменьшается в 4 раза
Энкодер 24 блока около 585 млн параметров
Классификатор CTC вероятности символов
Результат Текст повторы и пустые позиции удалены
Один блок Conformer Одинаковая структура повторяется 24 раза
½ шага Полносвязный блок FFN: Linear → SiLU → Linear
дальний контекст Self-attention запрос, ключ и значение (Q, K, V)
локальный контекст Свертка точечная и глубинная одномерные свертки
½ шага Полносвязный блок FFN: Linear → SiLU → Linear
выход блока Нормализация LayerNorm
Два FFN68,8% параметров / 55,4% времени Внимание17,2% параметров / 25,5% времени Свертка12,9% параметров / 17,1% времени
Линейные веса: FP16, INT8, INT6 или INT4 Свертки и нормализация в Conformer остаются FP16
Верхняя часть показывает весь путь сигнала. Нижняя раскрывает один из 24 одинаковых блоков Conformer и отмечает слои с квантизированными весами. Источники: описание Conformer и реализация GigaAM на MLX.
Путь сигнала через модель
  1. Звук одноканальный сигнал, 16 кГц
  2. Log-mel-спектрограмма частоты и их изменение во времени
  3. 2 сверточных слоя последовательность становится в 4 раза короче
  4. 24 блока Conformer FFNвниманиесверткаFFN
  5. Слой CTC вероятность каждого символа на каждом шаге
  6. Декодирование повторы и пустые символы удаляются, остается текст
Основная вычислительная работа приходится на 24 блока Conformer. Каждый блок дважды пропускает данные через FFN, сопоставляет удаленные участки записи механизмом внимания и выделяет локальные звуковые признаки сверткой.
Карта работ над MLX-версией
  1. Звук Добавлен практический вход WAV, FLAC, MP3, M4A и видео; длинные записи делятся на фрагменты
  2. Признаки Переписано на MLX разбиение на окна, спектр и mel-фильтр сверены с PyTorch
  3. Сжатие времени Перенесены свертки формы тензоров, маски и расположение весов проверены отдельно
  4. 24 блока Conformer Главная зона работы перенесены все слои; линейные веса получили INT8, INT6 и INT4; отдельно измерены FFN, внимание и свертка Проверены SDPA, mx.compile(), длина фрагмента и пакетная обработка.
  5. CTC Повторен выход модели логарифмы вероятностей и последовательность символов сверены с оригиналом
  6. Текст Собран готовый инструмент CLI, субтитры, Python API и локальный сервер с совместимым API
Весь путь сигнала перенесен на MLX. Квантизация затрагивает линейные слои, сосредоточенные главным образом внутри Conformer. Эксперименты со скоростью также были направлены на этот самый тяжелый участок.

Рабочий порт должен выполнять четыре условия:

  1. для обычного распознавания достаточно MLX и библиотеки чтения аудио;
  2. версии FP32 и FP16 повторяют поведение исходной модели с допустимой численной погрешностью;
  3. все варианты проходят одни и те же публичные тесты;
  4. скорость, размер файла и память измеряются отдельно на одинаковых записях.

Основой работы служили официальная модель ai-sage/GigaAM-Multilingual и исходный код salute-developers/GigaAM. Готовая MLX-версия опубликована в репозитории ai-babai/gigaam-multilingual-mlx.

Как проверялось совпадение с исходной моделью

Конвертер читает официальный файл весов и сохраняет его в безопасном для загрузки формате safetensors. Само распознавание выполняется на MLX. PyTorch нужен только при конвертации и сравнении двух реализаций.

Сначала сравнивались промежуточные тензоры, то есть многомерные массивы чисел внутри модели. Проверка проводилась после каждого крупного этапа. Так место расхождения можно найти сразу, даже если итоговый текст случайно совпал.

  1. Зафиксировать источник версия кода, файл весов, предобработка
  2. Сравнить тензоры формы и численные отклонения после ключевых слоев
  3. Сравнить текст одинаковое декодирование на одинаковом аудио
  4. Проверить качество WER на закрепленных публичных наборах
Каждый следующий уровень имеет смысл только после успешной проверки предыдущего.

Для проверки качества закреплены публичные списки примеров и единые правила подготовки текста: нижний регистр, удаление пунктуации и другие одинаковые преобразования. Исходная модель, FP16 и квантованные варианты получают одни и те же аудиозаписи и эталонные расшифровки. Первый русский набор содержит 1533 записи из FLEURS, Russian LibriSpeech и SOVA. Финальный набор multilingual-v1 использует по 1000 закрепленных примеров FLEURS для русского, казахского, кыргызского, узбекского и английского.

Бенчмарк запускался на MacBook Pro с M4 Pro и 48 ГБ общей памяти под macOS 15.7.7. Исходная PyTorch-версия использовала систему ускорения Apple MPS. Пятиминутный русский WAV обрабатывался после загрузки и короткого прогрева модели. Каждый вариант запускался в отдельном процессе.

WER показывает долю замененных, пропущенных и лишних слов. Значение около 5% можно читать как примерно пять исправлений на сто слов. Среднее для русского, казахского, кыргызского и узбекского языков в полном отчете называется Core macro WER.

В исходном JSON также сохранены CER (Character Error Rate, доля ошибок в символах) и RTF (Real-Time Factor, отношение времени обработки к длительности аудио). RTF меньше 1 означает, что модель работает быстрее реального времени. Во всех числовых колонках ниже меньшее значение лучше.

Как разрядность влияет на размер и скорость

FP16 хранит каждый вес модели в 16 битах. INT8, INT6 и INT4 используют меньше битов и поэтому занимают меньше места. При квантизации каждая группа из 64 весов получает общий масштаб, который позволяет приблизительно восстановить исходные значения. Обозначение g64 означает размер такой группы: 64 веса. Для всех четырех вариантов опубликованы отдельные веса, описание, контрольная сумма и закрепленная версия.

Пиковый RSS (Resident Set Size, резидентный размер процесса) показывает максимальный объем оперативной памяти, занятый процессом. В него входят модель, библиотеки и рабочие буферы.

Веса на диске

меньше лучше

  1. Исходная2,342 ГБ
  2. FP161,171 ГБ
  3. INT60,573 ГБ
  4. INT40,447 ГБ

Оперативная память

пиковый RSS всего процесса, меньше лучше

  1. Исходная5,059 ГБ
  2. FP161,350 ГБ
  3. INT60,755 ГБ
  4. INT40,626 ГБ

Пять минут аудио

после прогрева, меньше лучше

  1. Исходная2,79 с
  2. FP161,95 с
  3. INT62,20 с
  4. INT42,56 с
Длина линии показывает значение относительно исходной PyTorch/MPS-реализации в каждой колонке. Синий цвет отмечает INT8, выбранный по умолчанию.
Вариант Средний WER, 4 языка 5 мин после прогрева Пиковая память (RSS) Веса на диске
Исходная PyTorch/MPS 5,046% 2,789 с 5,059 ГБ 2,342 ГБ
MLX FP16 5,066% 1,952 с 1,350 ГБ 1,171 ГБ
MLX INT8 g64, по умолчанию 5,070% 2,036 с 0,877 ГБ 0,699 ГБ
MLX INT6 g64 5,069% 2,195 с 0,755 ГБ 0,573 ГБ
MLX INT4 g64 5,219% 2,563 с 0,626 ГБ 0,447 ГБ

Данные графика и таблицы: полный JSON бенчмарка и компактный CSV с пятью вариантами.

Скорость относительно реального времени

GigaAM решает задачу ASR, или автоматического распознавания речи. Скорость таких моделей принято показывать через RTF: время обработки делится на длительность аудио. Чем меньше RTF, тем быстрее модель. Обратное значение показывает, во сколько раз обработка быстрее реального времени.

Вариант 5 минут аудио RTF Скорость к реальному времени
Исходная PyTorch/MPS2,789 с0,0093107,6×
MLX FP161,952 с0,0065153,7×
MLX INT8 g642,036 с0,0068147,3×
MLX INT6 g642,195 с0,0073136,6×
MLX INT4 g642,563 с0,0085117,0×

Данные таблицы скорости: JSON с полными замерами и CSV с RTF и скоростью обработки.

Память графического процессора учитывается отдельно от RSS, потому что центральный и графический процессоры Apple Silicon используют один общий пул памяти.

Таблица показывает три сценария выбора:

Меньший файл не гарантирует более высокую скорость. Перед умножением упакованные INT-значения приходится распаковывать и переводить в удобный для вычислений формат. На M4 Pro эти дополнительные операции сделали FP16 немного быстрее INT8, INT6 и INT4. Поэтому скорость измерена отдельно для каждого варианта.

Полная методика, доверительные интервалы и результаты по всем языкам находятся в публичном отчете о бенчмарке.

Куда уходит время

Чтобы найти самое медленное место, отдельно измерено время каждого этапа для 20 секунд звука. Запись превращается в 1999 коротких кадров спектрограммы. Затем их число сокращается примерно до 500, и основную работу выполняют 24 блока Conformer. Замеры сделаны на той же M4 Pro с MLX 0.32.0. После каждого этапа mx.eval() заставлял MLX завершить вычисления перед измерением времени.

Полный проход FP16 после прогрева 120,23 мс
  1. WAV 20 секунд звука
  2. Аудиофронтенд 1999 log-mel-кадров 0,28 мс / 0,2%
  3. Последовательность 4× короче 500 × 1024 1,36 мс / 1,1%
  4. Учет позиции кадра позиционное кодирование RoPE 0,18 мс / 0,1%
  5. Энкодер 24 блока Conformer 118,75 мс / 98,8%
  6. Слой CTC оценки символов 0,21 мс / 0,2%
  7. Декодирование текст на CPU 0,15 мс / 0,1%
Этапы измерялись отдельно, поэтому округленные доли не обязаны складываться ровно в 100%. Энкодер определяет почти все время распознавания.

Подготовка звука, выходной слой CTC и преобразование результата в текст вместе занимают слишком малую долю для большого общего ускорения. Основная вычислительная работа сосредоточена внутри 24 одинаковых блоков Conformer.

Время одного блока 5,49 мс, отдельный FP16-замер
3,04 мс 1,40 мс 0,94 мс
Параметры модели доля от 585,33 млн параметров
402,9 млн 100,8 млн 75,8 млн
  • FFN3,04 мс, 55,4% времени / 68,8% параметров
  • Механизм внимания1,40 мс, 25,5% времени / 17,2% параметров
  • Сверточный модуль0,94 мс, 17,1% времени / 12,9% параметров
  • Прочие операцииоколо 0,11 мс, 2,0% времени / 1,1% параметров
В отдельном FP16-замере полный блок занимает 5,49 мс. FFN означает полносвязный блок прямого распространения. В каждом блоке Conformer используются два FFN, вместе они занимают больше половины времени.

Профиль объясняет приоритет оптимизаций. Из 585,33 млн параметров около 402,90 млн находятся в FFN. Проекции механизма внимания занимают 17,2%, сверточные модули Conformer еще 12,9%.

Стандартное вычисление механизма внимания заменено встроенной операцией mx.fast.scaled_dot_product_attention. Полный проход ускорился на 3,8% в FP16 и на 4,4% в INT8. Механизм внимания занимает около четверти времени одного блока, поэтому ускорение только этой части дает несколько процентов на всю модель.

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

Кандидаты проверялись по одному в отдельных процессах. Опубликованный код и веса во время исследования оставались без изменений.

  1. Обработать 16 аудиофрагментов, по 8 одновременноFP16, каждый фрагмент по 20 секунд +10,9%
  2. Увеличить фрагмент до 40 секундFP16, пятиминутное аудио +8,2%
  3. Ускорить механизм внимания через SDPAFP16, полный проход +3,8%
  4. Включить mx.compile()INT8, полный проход +3,1%
  5. Включить mx.compile()FP16, полный проход +0,8%
Шкала заканчивается на 12%. Объединение проекций Q и K дало менее 1% для полного прохода.

В первом замере модель получила 16 фрагментов по 20 секунд. Они обрабатывались двумя группами, по восемь одновременно. Общее время сократилось с 1,91 до 1,72 секунды, поэтому за единицу времени модель обработала на 10,9% больше аудио. Время ожидания одного файла в этом тесте не оценивалось.

Эффекты нельзя складывать арифметически. Они используют часть одних и тех же ресурсов и меняют форму вычислительного графа.

Размер фрагмента приходится подбирать для каждого варианта весов. FP16 выиграл 8,2% при переходе с 20 до 40 секунд. INT8 на той же форме потерял 10,2%. Обработка восьми фрагментов одновременно ускорила FP16 на 10,9%, а INT8 замедлила на 1,9%. Одна общая настройка ухудшила бы вариант по умолчанию.

Проверка mx.compile() показала, что эффект зависит от размера входа. Компиляция дала +0,8% для FP16 и +3,1% для INT8. Режим с произвольными размерами входа (shapeless=True) остановился на техническом ограничении операции mx.as_strided в подготовке звука.

Почему нельзя просто вырезать часть модели

Временное отключение или замену части модели называют абляцией. Такой эксперимент показывает вклад этой части в скорость и качество. Например, более простая функция ReLU почти не ускорила полный полносвязный блок: 1,51 мс вместо 1,52 мс с SiLU. Основное время уходит на умножение больших матриц, поэтому замена одной небольшой операции почти ничего не меняет.

Затем были проведены диагностические абляции на 100 публичных примерах FLEURS без сохранения новых весов. WER исходной конфигурации на этом поднаборе составил 6,51%.

  1. Исходная конфигурация24 слоя 1,00×WER 6,51%
  2. SiLU заменена на ReLUкачество разрушено 1,00×WER 99,23%
  3. Удален первый FFNв каждом слое 1,26×WER 52,03%
  4. Удален сверточный модульпустые ответы 1,12×WER 100%
  5. Оставлены первые 20 слоев4 слоя удалены 1,11×WER 99,62%
  6. Оставлен каждый второй слой12 слоев 1,50×WER 147,20%
  7. Число кадров уменьшено до 8×требуется обучение 1,48×WER 46,36%
Положение точки показывает ускорение по общей шкале. Число справа показывает итоговый WER. Каждый ускоренный вариант провалил критерий качества.

WER может быть выше 100%, если модель добавляет много лишних слов. Здесь проверялись готовые веса после механического изменения модели. Все ускоренные варианты резко ухудшили распознавание.

Даже замена функции активации изменила сигналы, которые проходят между слоями. Удаление половины блоков ускорило вычисление в 1,50 раза, но распознавание перестало работать. После таких изменений модель нужно обучать заново или переносить знания большой модели в уменьшенную.

Где находится граница ускорения без обучения

Рабочие оптимизации

+4,4%встроенная SDPA, INT8
+8,2%фрагменты по 40 секунд, FP16
+10,9%по 8 фрагментов одновременно, FP16

Диагностические абляции

  1. 1,26×удален первый FFN, WER 52,03%
  2. 1,48×8-кратное сжатие времени, WER 46,36%
  3. 1,50×оставлен каждый второй слой, WER 147,20%
Рабочие оптимизации сохранили качество. Более сильное ускорение в абляциях сопровождалось резким ростом WER.

Оптимизации без обучения дали от +0,8% до +10,9% в зависимости от режима. Удаление частей модели показало до 1,50×, но качество распознавания резко упало. В итоговые результаты вошли только варианты с сохраненным качеством.

Порядок работы

Работа была разделена на три последовательных контура:

  1. Сохранено поведение Закреплены версия кода, предобработка и декодирование. Сравнены промежуточные тензоры. Подтверждена эквивалентность FP32 и FP16.
  2. Измерен результат Каждый вариант проверен на одном наборе качества. Раздельно измерены файл, загрузка, задержка, пиковый RSS и память Metal. Найден главный узкий участок.
  3. Проверено и опубликовано Оптимизации проверены на полном входе. Опубликованы списки примеров, версии, контрольные суммы, команды и ограничения.
Порядок работы связал реализацию, проверку качества, замеры и опубликованные артефакты.

Готовый результат доступен в GitHub, PyPI и Hugging Face Collection. INT8 g64 выбран вариантом по умолчанию. FP16 подходит для минимальной измеренной задержки, INT4 для минимального размера и потребления памяти.

Текст подготовил ИИ-агент Codex по материалам рабочей сессии.

Воспроизводимость

  1. Исходная GigaAMмодель и код
  2. GitHubMLX-реализация и команды
  3. PyPIустанавливаемый пакет
  4. Hugging Faceчетыре варианта весов
  5. Публичный бенчмарксписки примеров, версии и отчет
Каждое опубликованное число связано с кодом, конкретной версией весов и закрепленным набором входов.

Все опубликованные входы бенчмарка общедоступны. Приватные аудиозаписи, веса моделей, датасеты, кеши и большие сырые результаты в GitHub-репозитории не хранятся.