MAATRIX / Блог / Сколько RAM нужно для Whisper: по моделям

Сколько RAM нужно для Whisper: по моделям

Сколько RAM нужно для Whisper: по моделям

MAATRIX

Вопрос «сколько RAM нужно для Whisper» обычно встаёт не заранее, а после того, как процесс молча умер со словом Killed, — притом что в таблице требований стояло «~2 ГБ». Таблица не врёт: она про видеопамять эталонной реализации на GPU, а вы считаете на процессоре, где арифметика другая. Дальше — требования Whisper к памяти по каждой модели: сколько занимают веса, что съедает RAM сверх них, как выглядит нехватка в логах и какой объём брать под свою задачу.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Главная путаница: таблица требований — про видеопамять

Все ориентируются на таблицу из README openai/whisper с колонкой «Required VRAM» — она честная, но отвечает на другой вопрос: сколько видеопамяти займёт эталонная реализация на PyTorch на GPU в режиме float16.

МодельПараметровRequired VRAM (GPU)Веса на CPU: int8 — float32
tiny39M~1 ГБ39–156 МБ
base74M~1 ГБ74–296 МБ
small244M~2 ГБ0,24–0,98 ГБ
medium769M~5 ГБ0,77–3,1 ГБ
large-v31550M~10 ГБ1,55–6,2 ГБ
large-v3-turbo809M~6 ГБ0,81–3,2 ГБ

Три вывода, которые ломают привычное чтение таблицы.

  • Видеопамять и RAM — разные правила. В гигабайты на карте входят буферы cuDNN с запасом, поэтому для tiny заявлен «~1 ГБ» при весах в 39 МБ. На CPU такого резерва нет, зато есть расход, которого не бывает на GPU, — декодированное аудио целиком в памяти.
  • CPU считает в float32, не в float16 — ограничение PyTorch: он печатает FP16 is not supported on CPU; using FP32 instead. Веса удваиваются: large-v3 — 1550 млн параметров по четыре байта, 6,2 ГБ до единого сэмпла.
  • Таблица — про openai-whisper, не faster-whisper. CTranslate2 хранит веса в int8, байт на параметр вместо четырёх — разница четырёхкратная, она и превращает large-v3 из «нужно 16 ГБ» в «уместится в 8». Различия сборок — в разборе faster-whisper против whisper.cpp.

Отдельно про turbo: энкодер идентичен large-v3 — 32 слоя, размерность 1280, — декодер урезан с 32 слоёв до 4. Параметров вдвое меньше, но расход на активации энкодера почти не падает, поэтому в README у turbo ~6 ГБ, а не ~5, как у вдвое более лёгкого medium.

Из чего складывается расход: веса, рантайм, аудиобуфер

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

Веса. Число параметров × байты: 1 для int8, 2 для float16, 4 для float32. small — это 244, 488 и 976 МБ. У faster-whisper файл model.bin на Hugging Face лежит в float16 (large-v3 — 3,09 ГБ), а в int8 CTranslate2 квантует его при загрузке — расход в момент старта кратковременно выше установившегося.

Рантайм — то, что занято до WhisperModel(...). У openai-whisper внутри PyTorch, и один импорт поднимает RSS на сотни мегабайт. Снимите своё число:

/opt/whisper/venv/bin/python - <<'EOF'
import resource
def mb(): return resource.getrusage(resource.RUSAGE_SELF).ru_maxrss // 1024
print("пустой интерпретатор:", mb(), "МБ")
import faster_whisper
print("после импорта:", mb(), "МБ")
m = faster_whisper.WhisperModel("small", device="cpu", compute_type="int8")
print("после загрузки модели:", mb(), "МБ")
EOF

Аудиобуфер — самое недооценённое слагаемое. faster-whisper через PyAV декодирует файл целиком в float32 моно 16 кГц: 16 000 сэмплов/сек × 4 байта — 64 КБ/сек, около 3,8 МБ на минуту, около 230 МБ на час. Трёхчасовая планёрка добавляет почти 700 МБ поверх остального.

У openai-whisper добавляется преобразование Фурье по всему файлу разом: n_fft=400, шаг 160 сэмплов (зашито в whisper/audio.py) — 201 частотная корзина на каждый из 100 кадров в секунду, по 8 байт на комплексное число, около 157 КБ/сек, порядка 550 МБ на час.

Активации и KV-кэш не растут с длиной файла — окно 30 секунд (1500 кадров энкодера), контекст декодера 448 токенов. Умножается на beam_size (5 в faster-whisper, 1 в openai-whisper) и размер батча.

Вывод: длина записи бьёт не по модели, а по аудиобуферу. Не хватает памяти на длинном файле — режьте файл:

ffmpeg -i long.m4a -vn -ac 1 -ar 16000 -c:a pcm_s16le \
  -f segment -segment_time 900 part_%03d.wav

Пятнадцатиминутный кусок — около 58 МБ в памяти вместо 690 МБ у трёхчасового исходника; расплата — швы на границах, режьте по паузам.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Whisper

Сколько RAM нужно по моделям: расчёт

Колонки «в памяти» — арифметика «параметры × байты», а не снятый замер; правая колонка — с рантаймом, аудио и запасом на пик загрузки.

МодельФайл CTranslate2В памяти int8В памяти float32Минимум RAM на машине
tiny0,08 ГБ~40 МБ~156 МБ1–2 ГБ
base0,15 ГБ~74 МБ~296 МБ2 ГБ
small0,48 ГБ~244 МБ~976 МБ4 ГБ
medium1,53 ГБ~0,77 ГБ~3,1 ГБ4–8 ГБ
large-v3-turbo1,62 ГБ~0,81 ГБ~3,2 ГБ8 ГБ
large-v33,09 ГБ~1,55 ГБ~6,2 ГБ8–16 ГБ

Правило для последней колонки: RAM ≈ веса + 0,5 ГБ на Python и библиотеки + 0,23 ГБ на каждый час аудио + 1 ГБ на систему и запас. Пример: large-v3 в int8 на двухчасовой записи — 1,55 + 0,5 + 0,46 + 1 ≈ 3,5 ГБ, то есть достаточно тарифа на 8 ГБ, а не 16, как подсказывает колонка VRAM.

Сверить расчёт можно по замеру из README faster-whisper: small в int8 с beam_size=5 на записи 13 минут занимала у разработчиков около 1477 МБ, в float32 — около 2257 МБ (веса — 244 и 976 МБ). Разница — интерпретатор, буферы CTranslate2, аудио, активации; замер снят на Core i7-12700K, на vCPU виртуалки дословно не переносится, но пропорция «веса — меньше половины расхода» верна и там.

Если памяти совсем мало — whisper.cpp: в README колонка «Mem» рядом с размером файла — около 273 МБ для tiny, 388 МБ для base, 852 МБ для small, 2,1 ГБ для medium, 3,9 ГБ для large. Плюс квантование: q5_0 — около 5,5 бита на вес вместо шестнадцати, large-v3-turbo из 1,62 ГБ превращается в ~0,56 ГБ ценой урезанного входа (WAV 16 кГц моно) и потери точности.

Что умножает память: воркеры, батчи и словесные тайм-коды

Расчёт выше — для одного процесса на одном файле. Дальше — множители, которые превращают комфортные 8 ГБ в OOM.

  • Параллелизм. И uvicorn app:app --workers 4 (четыре процесса, у каждого своя копия модели), и num_workers у WhisperModel умножают память на число потоков, а скорость почти не растёт — ядра те же. Правильная схема для Whisper — один воркер и очередь.
  • Пакетный режим. BatchedInferencePipeline с batch_size=8 в замерах README поднял расход на small с 1477 МБ до 3608 МБ — почти в два с половиной раза. Инструмент для машин от 8 ГБ; на четырёх — Killed на первом длинном файле.
  • Диаризация и словесные тайм-коды. WhisperX и pyannote — отдельный стек с PyTorch (плюс 2–3 ГБ, pyannote требует токена Hugging Face); word_timestamps=True считает выравнивание по весам кросс-внимания — лишние тензоры, для субтитров по фразам не нужен.
  • float32 вместо int8. Проверка: python -c "import ctranslate2; print(ctranslate2.get_supported_compute_types('cpu'))" — вернёт множество вроде {'int8', 'int8_float32', 'int16', 'float32'}.
  • Загрузка в tmpfs. findmnt /tmp с tmpfs в выводе значит, что каждый загруженный файл целиком лежит в RAM. Пишите загрузки на диск и чистите по крону.

Как выглядит нехватка памяти в логах

Симптомы разные, и по ним видно, кто вас убил.

Голое Killed в консоли — без стектрейса, процесс не падал, его прибило ядро:

journalctl -k --since '30 min ago' | grep -iE 'out of memory|killed process'
Out of memory: Killed process 2317 (python3) total-vm:5482720kB,
anon-rss:3218364kB, file-rss:2560kB, shmem-rss:0kB, UID:998
pgtables:7160kB oom_score_adj:0

systemd. В systemctl status whisperMain process exited, code=killed, status=9/KILL и Failed with result 'oom-kill'. Кто поставил предел, покажет systemctl show whisper.service -p MemoryMax --value: infinity значит, памяти не хватило по-настоящему.

Docker. Выход по памяти даёт код 137, который легко принять за обычное падение: docker inspect -f '{{.State.OOMKilled}} {{.State.ExitCode}}' whisper. Ответ true 137 — это лимит --memory, не баг приложения.

Аллокация не прошла, убийства не было. Под лимитом cgroup ошибка идёт изнутри процесса. От CTranslate2 — terminate called after throwing an instance of 'std::bad_alloc'. От numpy — numpy._core._exceptions._ArrayMemoryError: Unable to allocate 1.03 GiB for an array with shape (276480000,) and data type float32: это почти пять часов записи при 16 кГц.

Видеокарта. Текст другой: torch.OutOfMemoryError: CUDA out of memory. Tried to allocate 2.00 GiB. Лечится меньшей моделью или batch_size, не докупкой RAM.

Памяти хватает, а всё стоит. vmstat 1 5, колонки si/so: ненулевые значения — веса уехали в swap, каждый шаг декодера ждёт диска. Формально не OOM, практически хуже — сервис отвечает по таймауту. Остальные сбои faster-whisper — в статье частые ошибки на сервере.

Как измерить свой расход и удержать его в рамках

Чужие таблицы дают порядок величины, ваша задача — цифру.

Пик за один прогон. Утилита time ставится отдельным пакетом, иначе bash: /usr/bin/time: No such file or directory:

apt install -y time
/usr/bin/time -v /opt/whisper/venv/bin/python /opt/whisper/run.py 2>&1 \
  | grep -E 'Maximum resident|Elapsed'

Строка Maximum resident set size (kbytes): 1512340 — это 1,44 ГБ пика на самом длинном из типовых файлов.

Пик у работающего сервиса. В Ubuntu 24.04 (systemd 255) есть готовое свойство юнита; в Debian 12 (systemd 252) MemoryPeak ещё нет — читайте cgroup напрямую:

systemctl show whisper.service -p MemoryPeak --value
cat /sys/fs/cgroup/system.slice/whisper.service/memory.peak

Проверка «влезет ли в тариф» без покупки тарифа. Расшифровка во временном срезе с жёстким лимитом и без подкачки — умерла, значит, в такую машину не поместится:

systemd-run --scope -p MemoryMax=2G -p MemorySwapMax=0 \
  /opt/whisper/venv/bin/python /opt/whisper/run.py

Как удержать расход:

  • Ставьте предел осознанно. MemoryHigh=6G включает давление на реклейм раньше, чем MemoryMax=7G убивает процесс — иначе ядро само выберет жертву, и это может быть база на той же машине.
  • Не полагайтесь на swap. Спасает только момент загрузки весов; модель, живущая в подкачке дальше, считает бесконечно долго. 2–4 ГБ как страховка и vm.swappiness=10 — но покупайте память.
  • Одна модель на процесс, очередь снаружи. Веса грузятся раз при старте, задачи идут по одной через семафор.
  • Спускайтесь по моделям осознанно. large-v3turbo экономит около 0,74 ГБ в int8 при близком качестве; дальше вниз просядет узнаваемость имён и терминов. Что теряется по скорости — в разборе Whisper медленно распознаёт речь.

Какой сервер под Whisper брать в MAATRIX

Whisper есть в каталоге apps.maatrix.io: ставится автоматически при заказе сервера, работает на Ubuntu и Debian, вручную ставить не нужно. Адрес и ключи — в личном кабинете, в разделе «Доступ». Дальше — сколько памяти заказать.

Честный минимум: 2 vCPU, 4 ГБ RAM, 40 ГБ NVMe. small в int8 — 0,24 ГБ весов, около 0,5 ГБ рантайма, 0,23 ГБ на час аудио: укладывается с запасом на страничный кэш. Ограничения: батчи нельзя, второй запрос отберёт память у первого, large-v3 не поместится. Тариф на 2 ГБ технически тянет tiny и base, но это конфигурация для проверки идеи — первый часовой файл через tmpfs приведёт в journalctl -k.

Комфортный вариант: 4 vCPU, 8 ГБ RAM, 80 ГБ NVMe. Помещается large-v3-turbo или medium в int8 со всем обвесом: очередь задач, Nginx, кэш моделей на 10–20 ГБ, запас на длинные записи без нарезки. Появляется смысл в пакетном режиме и cpu_threads по числу реальных ядер. Для large-v3 в float32, диаризации или нескольких моделей разом берите 16 ГБ; при потоке от нескольких часов в день разумнее видеокарта — по документации turbo нужно ~6 ГБ VRAM, large-v3 — ~10 ГБ.

Локация — Великобритания, Лондон. Веса едут с huggingface.co, а с российских адресов он отвечает через раз — первый же WhisperModel("large-v3") зависает на скачивании трёх гигабайт. С лондонской площадки модели тянутся напрямую, плюс низкий пинг до Европы и понятный режим обработки персональных данных. Для записей, обязанных по 152-ФЗ храниться в России, — RU-локация с заранее прогретым кэшем: после загрузки весов Whisper работает офлайн. Путь развёртывания — в статье Whisper локально на своём сервере.

Оплата — картой российского банка, по СБП, криптовалютой или токеном MAAT: иностранная карта для сервера в Лондоне не нужна. Память на большинстве тарифов наращивается без переустановки.

Развернуть за пару минут

Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Развернуть Whisper

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Частые вопросы

Хватит ли 2 ГБ RAM для Whisper?

Для tiny и base в int8 да: веса 39 и 74 МБ, рантайм около полугигабайта. Для small впритык — любой множитель (батч, второй воркер, часовая запись в tmpfs) кончается строкой Out of memory: Killed process в journalctl -k. Для medium, turbo и large-v3 двух гигабайт не хватит нигде, кроме квантованного whisper.cpp.

Влияет ли длина записи на память?

На модель почти нет: окно фиксировано 30 секундами, KV-кэш не растёт с файлом. Растёт аудиобуфер: PyAV декодирует запись целиком в float32 моно 16 кГц — около 230 МБ на час. Трёхчасовой файл добавляет почти 700 МБ; лечится нарезкой через ffmpeg -f segment -segment_time 900, а не сменой модели.

Спасёт ли swap, если памяти не хватает?

Только от аварийного завершения при загрузке весов. Дальше — подкачка на каждом шаге декодера: сервис формально жив, расшифровка не двигается, в vmstat 1 видны ненулевые si/so. Держите 2–4 ГБ swap как страховку при старте, но рабочий объём модели должен помещаться в физическую память.

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.