Перейти к содержимому
Статья

Почему модель 70B не помещается в видеокарту на 24 ГБ: как считать память для локального ИИ

Название 70B означает около 70 млрд параметров, а не размер файла в гигабайтах. В FP16 одни веса такой модели требуют примерно 140 ГБ памяти, при 8-битном хранении около 70 ГБ, а идеальные 4 бита дают около 35 ГБ еще до KV-кеша и служебных буферов. Поэтому объем VRAM для локальной LLM нельзя выбирать только по размеру GGUF: длинный контекст способен занять еще десятки гигабайт.

BadMadSam
Почему модель 70B не помещается в видеокарту на 24 ГБ: как считать память для локального ИИ

Автор: Изображение создано с помощью ChatGPT

Откуда берутся 140 ГБ у модели с обозначением 70B

Число 7B, 8B, 32B, 70B или 405B в названии языковой модели обычно относится к количеству ее параметров. Параметры можно грубо представить как числовые коэффициенты нейросети, полученные во время обучения. Для запуска уже обученной модели их необходимо хранить в памяти и постоянно читать при вычислениях. Поэтому первый расчет требований к памяти начинается не с длины контекста и даже не с видеокарты, а с количества параметров и формата, в котором записан каждый из них.

Если один параметр хранится в FP32, на него требуется 32 бита, или 4 байта. Модель с 70 млрд параметров в таком представлении потребовала бы приблизительно 280 ГБ только для весов. FP16 и BF16 уменьшают величину примерно вдвое: 70 млрд × 2 байта дают около 140 ГБ. Восьмибитное представление в идеальном случае уменьшает объем до 70 ГБ, четырехбитное до 35 ГБ. Это десятичные оценки. В программах, которые выводят GiB, цифры будут меньше, поскольку 1 GiB равен 1 073 741 824 байтам.

Именно поэтому фраза «у меня видеокарта на 24 ГБ, значит 70B в 4 битах должна поместиться» не сходится уже на первом расчете. Даже если представить идеальное четырехбитное хранение без единого дополнительного байта, 35 ГБ больше 24 ГБ. Реальные форматы квантования дополнительно используют масштабы, метаданные, блоки и иногда веса другой точности, поэтому размер файла обычно не равен простому произведению числа параметров на четыре бита.

современная видеокарта GeForce RTX, установленная внутри настольного компьютера
современная видеокарта GeForce RTX, установленная внутри настольного компьютера

Фото: Matheus Bertelli

Для конкретного примера удобно использовать Llama 3.1 70B. Meta выпустила семейство Llama 3.1 в вариантах 8B, 70B и 405B с контекстом до 128K токенов. В карточке Llama 3.1 70B также указано использование Grouped-Query Attention, или GQA, что существенно для дальнейшего расчета памяти под контекст. Модель плотная: при обработке токена работают все ее основные параметры, в отличие от архитектур Mixture-of-Experts, где общее и активное число параметров могут сильно различаться.

С современными MoE-моделями надпись вроде 100B или 200B требует дополнительной проверки. У модели может быть очень большое суммарное количество параметров, но для каждого токена маршрутизатор активирует только часть экспертов. Это снижает объем вычислений на токен, однако не означает, что все остальные веса автоматически перестают занимать память. Если вся модель загружается в GPU, хранить приходится и неактивные в данный момент эксперты. Поэтому при выборе локальной модели нужно различать total parameters, active parameters и фактический размер конкретного файла весов.

С обучением арифметика еще тяжелее. Во время inference нужны веса, промежуточные активации, кеш и рабочие буферы. При обучении появляются градиенты и состояния оптимизатора. Hugging Face в разборе потребления памяти приводит для mixed-precision обучения с AdamW оценку порядка 18 байт на параметр плюс память активаций. Поэтому возможность запустить квантованную 32B-модель на домашней видеокарте ничего не говорит о возможности полноценно обучать такую модель на той же GPU.

Почему Q4 не означает ровно четыре бита на каждый параметр

Квантование уменьшает точность представления весов. Вместо 16-битного числа можно использовать 8, 6, 5, 4 и даже меньше бит. На первый взгляд результат должен масштабироваться линейно: модель в Q4 должна занимать четверть пространства относительно FP16. В реальном файле появляются дополнительные данные, необходимые для восстановления приближенных значений при вычислениях.

Один из распространенных подходов состоит в том, что веса разбиваются на блоки. Значения внутри блока кодируются числами низкой разрядности, но вместе с ними хранится scale и другая информация, позволяющая сопоставить маленькое целое число с исходным диапазоном весов. Служебные значения могут храниться в большей точности. Поэтому фактическое число бит на один вес оказывается выше номинальных четырех.

В экосистеме llama.cpp это особенно хорошо видно по количеству форматов. Существуют Q4_0, Q4_1, Q4_K_S, Q4_K_M, Q5_K_M, Q6_K, Q8_0 и другие варианты. Буква Q4 сообщает лишь общий класс. K-кванты используют блочную структуру, а варианты S, M и L различаются тем, как распределяется точность между тензорами. Документация llama.cpp прямо указывает, что квантование уменьшает размер и способно ускорять inference, но может вносить потерю точности, которую оценивают, например, через perplexity или KL divergence.

графическая плата с открытой печатной платой, видны GPU, память и силовые компоненты
графическая плата с открытой печатной платой, видны GPU, память и силовые компоненты

Фото: Ödeldödel

Из этого следует практическая причина, по которой две версии одной модели с надписью Q4 могут иметь разный размер. В одном варианте почти все подходящие тензоры действительно переведены в четыре бита, в другом наиболее чувствительные части оставлены в большей точности. Добавляются словарь, служебные тензоры и метаданные GGUF. Номинальные четыре бита превращаются, например, в эффективные 4,5-5 бит на вес. Точное значение зависит от конкретного алгоритма и архитектуры.

Для 70B эта небольшая разница превращается в гигабайты. Дополнительный один бит на каждый из 70 млрд параметров означает примерно 8,75 ГБ данных в десятичном представлении. Поэтому переход с одной разновидности Q4 на Q5 у большой модели нельзя считать мелким изменением. На 7B разница еще может помещаться в запас VRAM, а на 70B она способна потребовать еще одну видеокарту или перенос значительной части слоев в системную память.

Hugging Face реализует другой популярный вариант через bitsandbytes. В документации Transformers прямо указано, что загрузка в 8 бит примерно вдвое уменьшает расход памяти относительно 16-битного варианта, а 4-битное квантование сжимает модель еще сильнее. При этом вычисления и хранение весов не обязаны использовать одну и ту же точность. Квантованный вес может храниться компактно, а операция с ним выполняться в FP16, BF16 или другом формате.

Отсюда появляется еще одна ошибка при выборе локальной модели: размер файла на SSD принимают за необходимую VRAM. Для GGUF, который исполняется через llama.cpp и частично остается в RAM, размер файла действительно дает полезную начальную оценку. Для других движков модель может преобразовываться при загрузке, создавать дополнительные структуры и резервировать рабочую память. Если файл занимает 21 ГБ, это не гарантирует запуск на GPU с 24 ГБ без остатка.

Куда исчезает VRAM после загрузки весов

После загрузки модели свободная память нужна движку inference. Один из крупнейших потребителей при длинных диалогах называется KV cache, или кеш ключей и значений механизма attention. Без него при генерации каждого нового токена трансформеру пришлось бы заново вычислять ключи и значения для всех предыдущих токенов. Кеш сохраняет результаты предыдущих шагов и резко уменьшает повторную работу, но растет вместе с контекстом.

Размер KV-кеша определяется архитектурой. Для обычного Multi-Head Attention ключи и значения приходится хранить для каждого KV-head каждого слоя. Grouped-Query Attention уменьшает количество KV-head относительно числа query-head и тем самым заметно сокращает кеш. Именно поэтому GQA стал особенно полезен с ростом контекстных окон до десятков и сотен тысяч токенов.

У Llama 3.1 70B используются 80 трансформерных слоев, 64 query-head, но только 8 KV-head; размер head равен 128. Если кеш хранится в FP16 или BF16, для одного токена получается:

2 × 80 × 8 × 128 × 2 байта = 327 680 байт.

Первая двойка относится к Key и Value, последняя к двум байтам 16-битного значения. Получается 320 KiB на токен. При 4096 токенах это около 1,25 GiB, при 8192 около 2,5 GiB, при 32 768 около 10 GiB. Теоретическое заполнение всего контекста в 131 072 токена потребует примерно 40 GiB KV-кеша для одной последовательности при таком представлении. Эта оценка относится именно к указанной архитектуре и 16-битному кешу, а не ко всем LLM.

серверные стойки, в которых подобные модели могут распределяться между несколькими ускорителями
серверные стойки, в которых подобные модели могут распределяться между несколькими ускорителями

Фото: Tyler

Получается ситуация, которая сначала выглядит нелогично. Квантованная модель уже загружена, программа показывает несколько свободных гигабайт VRAM, короткий запрос работает, но при увеличении context length сервер сообщает об отсутствии памяти. Веса модели не изменились. Увеличился резерв или фактическое использование KV-кеша.

По этой же причине заявленные 128K или 256K контекста нельзя читать как обещание, что максимальная длина будет доступна на любой видеокарте, способной загрузить веса. Архитектура модели может поддерживать такое окно, но локальная система должна еще выделить память под него. При серверной работе проблема увеличивается: одновременно обрабатывается несколько последовательностей, и кеш требуется для каждой из них.

Современные inference-движки пытаются уменьшить расход. vLLM поддерживает хранение KV-кеша в FP8. В актуальной документации vLLM указано, что переход к FP8 существенно сокращает память кеша и позволяет хранить больше токенов. При переходе с 16 на 8 бит теоретическая емкость при том же объеме памяти примерно удваивается, хотя конкретная реализация добавляет масштабы и имеет собственные требования к точности.

KV cache также объясняет, почему две программы для запуска одной модели могут показать разный максимальный контекст на одной видеокарте. Они по-разному резервируют GPU-память, используют разные attention kernels, форматы кеша и служебные буферы. Поэтому вопрос «поместится ли модель» имеет смысл только вместе с названием backend, форматом квантования и требуемым контекстом.

Можно ли запустить 70B на 24 ГБ через оперативную память

Можно, если движок поддерживает CPU offload или изначально рассчитан на совместную работу RAM и VRAM. llama.cpp умеет размещать часть слоев на GPU, оставляя остальное в системной памяти. Поэтому компьютер с 24 ГБ VRAM и 64-128 ГБ обычной RAM способен запускать модели, полный набор весов которых не помещается в видеокарту.

Это не делает 64 ГБ DDR5 эквивалентом 64 ГБ VRAM. Разница находится прежде всего в пропускной способности и пути данных. Современная видеопамять обеспечивает сотни гигабайт в секунду, а у старших ускорителей показатель переходит за терабайт в секунду. Двухканальная DDR5 настольного компьютера работает на другом уровне пропускной способности. Для генерации LLM это критично, поскольку веса приходится постоянно читать при расчете следующего токена.

В плотной модели 70B каждый сгенерированный токен требует обращения к огромному массиву весов. Если значительная его часть находится в RAM, скорость начинает зависеть от пропускной способности системной памяти. Процессор может иметь много ядер, но дополнительные ядра не создают дополнительную полосу памяти. Поэтому локальный LLM inference часто оказывается memory-bound задолго до полной загрузки вычислительных блоков.

PCI Express добавляет еще одно ограничение, когда данные приходится передавать между RAM и VRAM. Самый плохой вариант возникает, если рабочий набор постоянно мигрирует через PCIe во время генерации. Хорошо организованный offload старается распределить слои так, чтобы минимизировать такие перемещения, но полностью устранить различие между локальной памятью GPU и системной RAM невозможно.

крупный план печатной платы компьютера с микросхемами и системой охлаждения
крупный план печатной платы компьютера с микросхемами и системой охлаждения

Фото: Lenharth Systems

Из этого следует полезное различие между «модель запускается» и «модель комфортно работает». 70B-квант может технически открыться на компьютере с одной 24-гигабайтной видеокартой и большим объемом RAM. Если основная часть весов остается в системной памяти, генерация может оказаться намного медленнее полностью GPU-резидентного варианта. Для интерактивного чата скорость в несколько токенов в секунду воспринимается иначе, чем 20-40 токенов в секунду, хотя обе конфигурации формально успешно запускают модель.

На Apple Silicon ситуация отличается архитектурно. CPU и GPU используют общую unified memory, поэтому нет отдельного пула VRAM того же типа, что у дискретной GeForce. Большой объем единой памяти позволяет загружать модели, для которых на обычном ПК потребовалось бы несколько GPU или offload в RAM. Это не отменяет требований к пропускной способности: разные поколения и конфигурации Apple Silicon имеют разную ширину памяти и поэтому разную скорость inference.

Несколько видеокарт тоже не всегда дают простую сумму памяти без последствий. Модель можно разделить между GPU, но между ускорителями появляется обмен данными. Его скорость зависит от PCIe, NVLink там, где он существует, используемого backend и способа разбиения. Две карты по 24 ГБ дают возможность разместить намного более крупную модель, но не превращаются автоматически в единую 48-гигабайтную GPU с такой же скоростью доступа ко всем данным.

Как посчитать подходящий размер модели до скачивания сотни гигабайт

Для первого приближения достаточно умножить количество параметров на число байтов одного веса. FP16 и BF16 дают примерно 2 байта на параметр, INT8 около одного, идеальное четырехбитное представление около половины байта. Для 8B получаются соответственно примерно 16, 8 и 4 ГБ. Для 32B около 64, 32 и 16 ГБ. Для 70B около 140, 70 и 35 ГБ. Это нижняя теоретическая оценка весов, а не обещание фактического расхода памяти.

После этого нужно посмотреть реальный размер выбранного файла. Для GGUF это особенно удобно: если Q4_K_M занимает, например, больше 40 ГБ, никакая арифметика с «70B × 0,5 байта» уже не нужна. Файл сам показывает, что целиком в 24 ГБ VRAM он не помещается. Дальше решается другой вопрос: сколько слоев можно выгрузить на GPU и устраивает ли скорость оставшейся CPU-части.

Затем добавляется контекст. Для короткого локального чата окно 4K или 8K требует намного меньше KV-памяти, чем 64K или 128K. Покупать память под максимальный контекст модели имеет смысл только тогда, когда он действительно нужен для длинных документов, больших кодовых баз или длительных сессий. Максимальное число в model card часто является архитектурным пределом, а не оптимальным режимом домашнего компьютера.

Нужно оставить запас и для runtime. Видеокарта одновременно используется драйвером, графическим интерфейсом Windows или Linux, рабочими буферами CUDA/ROCm и самим inference-движком. Если расчет весов дает 23,8 ГБ для карты на 24 ГБ, такая конфигурация практически не имеет пространства для нормальной работы. Даже если загрузка пройдет, увеличение контекста или другой backend может закончиться out of memory.

Для видеокарты на 8 ГБ разумный класс локальных моделей начинается с небольших 7B-8B-квантов. 12-16 ГБ позволяют использовать более тяжелые кванты небольших моделей и часть моделей среднего размера. 24 ГБ уже дают значительно больше свободы для 14B, 20B и многих 30B-классов в низкой точности, но плотная 70B остается больше этого объема даже при обычном четырехбитном квантовании. Точные границы зависят от архитектуры и формата, поэтому это диапазоны, а не таблица совместимости.

Еще один параметр, который нельзя выводить из числа B, это качество. 70B не гарантирует лучший ответ, чем любая 32B-модель. Архитектура, обучающие данные, post-training, специализация, контекст и конкретная задача могут оказаться важнее количества параметров. Для программирования специализированная меньшая модель способна быть полезнее крупной универсальной, а для русского языка результат зависит от того, насколько хорошо конкретная модель обучена и дообучена на нужном языке. Поэтому сначала имеет смысл определить минимальную модель, которая решает задачу, и только затем покупать память под следующий размер.

Главная ошибка при сборке ПК для локального ИИ состоит в попытке свести требования к одной цифре VRAM. Память расходуется минимум на веса, KV cache и рабочие данные inference-движка. Квантование резко уменьшает первый компонент, но не делает 70 млрд параметров маленькой моделью. Длинный контекст способен добавить гигабайты или десятки гигабайт кеша, CPU offload переносит проблему из объема VRAM в пропускную способность RAM, а несколько GPU добавляют обмен между ускорителями. Поэтому правильный расчет начинается с параметров и точности весов, продолжается реальным размером кванта и заканчивается контекстом, который действительно будет использоваться.

6 показов