Определить нагрузку до выбора счётчика
«Модель 7B» не уточняет ни представление весов, ни выполняемую работу. Зафиксируйте её ревизию, фреймворк, версии расширений, реально загружаемый формат и операцию: обучение, адаптацию или генерацию. Для текста отметьте длины входа и выхода; для зрения — разрешение и число изображений. Мультимодальная модель требует сохранения обоих этих измерений.
Подготовьте обычный вход, длинный, но ожидаемый, и близкий к вашему функциональному пределу. Сохраняйте их во время сравнений. Проверяйте формы после токенизации, padding, группировки или изменения размера: значение, указанное в конфигурации, не доказывает реально обрабатываемую форму.
Также зафиксируйте то, что одновременно остаётся в памяти: одна последовательность, микробатч, несколько запросов или оценка, запущенная после обучения. Ваш вопрос становится проверяемым: помещается ли эта полная нагрузка на каждое используемое устройство, в том числе на самом требовательном её этапе?
- Идентичность испытания: модель или код, ревизия, набор входных данных и зерно, когда это уместно.
- Размерности: batch, контекст, сгенерированные токены, разрешение или число одновременных запросов.
- Среда: выбранный GPU, драйвер, Python, PyTorch, backend CUDA или HIP/ROCm и настройки аллокатора.
- Область измерения: загрузка, вычисления, передача, оценка, экспорт; первый проход или проход после прогрева.
Считайте вес, не смешивая GB и GiB
Один GB — это 1 000 000 000 байт; один GiB — 1 073 741 824 байта. Счётчики PyTorch, используемые здесь, возвращают байты. Сохраняйте это исходное значение в файле результатов, а затем применяйте единственное преобразование для сравнения строк. Коммерческое обозначение карты не заменяет ёмкость, фактически заявленную устройством.
Для плотного набора из семи миллиардов параметров, хранимых по два байта каждый, веса составляют 14 000 000 000 байт: 14 GB, или примерно 13,04 GiB. Эта операция не включает ни активации, ни градиенты, ни KV-кэш, ни состояния оптимизатора. Добавление резерва в 4 GiB даёт примерно 17,04 GiB как гипотезу для подготовки; это не доказывает, что нагрузка уместится в эту оболочку.
Теоретическое деление на четыре бита предполагает компактное однородное хранение. Реальная квантованная загрузка может добавлять масштабы и прочую информацию, а также сохранять некоторые модули в другой точности. Поэтому формат хранения весов и формат вычислений должны указываться в вашей карточке отдельно.
| Гипотеза хранения | Вычисленные байты | Примерно GiB |
|---|---|---|
| 32 бита однородно | 28 000 000 000 | 26,08 |
| 16 бит однородно | 14 000 000 000 | 13,04 |
| 4 бита компактно, без метаданных | 3 500 000 000 | 3,26 |
Технические источники: NIST — двоичные приставки и сравнение GB/GiB · Hugging Face — форматы и квантованные модули с bitsandbytes
При обучении измеряйте полный шаг
Веса сосуществуют с другими объектами: градиентами, состояниями оптимизатора, активациями, необходимыми для обратного прохода, и временными тензорами. Их размеры зависят от цикла, точности и размеров нагрузки. Универсальная константа в байтах на параметр скрыла бы, в частности, влияние микробатча и входных данных.
Инструментируйте прямой проход, вычисление потерь, обратное распространение и обновление. Чтобы увидеть состояния, реально создаваемые вашим оптимизатором, не останавливайтесь на загрузке модели. Сохраняйте также измерение первого полного шага: успешный прогрев мог уже выполнить инициализацию, которую вы должны иметь возможность оплатить памятью при запуске.
Добавьте оценку и экспорт, необходимые вашему проекту. Если сбой происходит во время оценки, уменьшение только обучающего батча не исправляет эту фазу. Адаптация, обучающая мало параметров, всё ещё может хранить базовую модель и объёмные активации.
Технические источники: Hugging Face — категории памяти во время обучения
При инференсе следите за контекстом и параллелизмом
В авторегрессивной генерации с вниманием KV-кэш хранит состояния, связанные с токенами. Для однородного плотного кэша его размер зависит от слоёв, KV-голов, их размерности, сохраняемых токенов и одновременно присутствующих последовательностей. Используйте KV-головы модели, а не автоматически её головы запросов.
Арифметический пример: 32 слоя, 8 KV-голов, размерность 128, 8 192 токена, два байта на значение и одна последовательность дают 1 073 741 824 байта, то есть 1 GiB для K и V вместе. Четыре одинаковые последовательности дают 4 GiB только на эту статью. Этот расчёт не измеряет ни пропускную способность, ни полную загрузку GPU.
Адаптируйте формулу к реально используемому кэшу. Скользящее окно не обязательно сохраняет всю историю; статический кэш может предварительно выделять свою максимальную ёмкость. Квантованные и вынесенные кэши также меняют задачу. Измеряйте отдельно начальную обработку входа и генерацию, не приписывая автоматически всё их расхождение кэшу.
Технические источники: Hugging Face — стратегии кэширования, статическое выделение и окна
Allocated и reserved: два показания, которые не складываются
memory_allocated описывает байты, занятые тензорами, отслеживаемыми PyTorch на устройстве. memory_reserved описывает память, управляемую его аллокатором с кэшем, включая ту, что уже используется этими тензорами. Сложение обоих значений дважды учитывает часть памяти. Храните их в двух отдельных столбцах.
Их максимумы фиксируют пик с начала наблюдения или с момента последнего сброса. Это абсолютные пики за период, которые включают и аллокации, уже существовавшие в начале. Результат не отражает автоматически только те объекты, что были созданы в ходе фазы.
Системное измерение может охватывать более широкую область. Аллокации, выполненные напрямую библиотекой CUDA, например некоторые коммуникации NCCL, не все видны в аллокаторе PyTorch. Поэтому расхождение с системным инструментом само по себе не доказывает утечку.
| Счётчик | Вопрос, на который он отвечает | Ошибка, которой следует избегать |
|---|---|---|
| memory_allocated | Сколько занимают тензоры в этот момент чтения? | Принимать это за всю занятую память карты. |
| memory_reserved | Сколько памяти обслуживает аллокатор в этот момент чтения? | Прибавлять это к allocated. |
| max_memory_allocated | Какой пик тензоров отслеживался за период? | Путать его со значением в конце фазы. |
| max_memory_reserved | Какой пик резервирования сообщает аллокатор? | Полагать, что он наступает в тот же момент, что и другой пик. |
Технические источники: PyTorch — memory_allocated · PyTorch — memory_reserved · PyTorch — max_memory_allocated · PyTorch — allocations вне его аллокатора
Почему разница между двумя пиками не измеряет кэш
Рассмотрим только два вымышленных момента из таблицы. Пик allocated равен 8 Gio, а пик reserved — 12 Gio. Их разница, 4 Gio, не равна разнице, наблюдаемой ни в один из этих двух моментов: там она составляет соответственно 2 и 6 Gio. Два максимума не обязательно описывают одно и то же состояние.
Чтобы изучить их расхождение в конкретный момент, снимите allocated и reserved в одной и той же контрольной точке, после синхронизации и без новых намеренных операций между чтениями. Вы получите разницу счётчиков в этот момент, а не измерение KV-кэша модели и не гарантию, что вся эта разница способна удовлетворить следующую аллокацию.
Также сохраняйте в отчёте бэкенд аллокатора. Документация PyTorch 2.14 уточняет, что при cudaMallocAsync max_memory_reserved может объединять наивысшие уровни двух пулов и давать верхнюю границу одновременного пика. Это усиливает необходимость сохранять имя и область действия счётчика.
| Иллюстративный момент | Allocated | Reserved | Reserved − allocated в этот момент |
|---|---|---|---|
| A | 8 Gio | 10 Gio | 2 Gio |
| B | 6 Gio | 12 Gio | 6 Gio |
Технические источники: PyTorch — определение и предел max_memory_reserved
Ограничьте каждую фазу, прежде чем снимать её пик
Операции GPU могут вставать в очередь до своего завершения. Для измерения по фазам завершите предыдущие работы, прежде чем сбрасывать пики, затем дождитесь окончания фазы перед чтением. torch.cuda.synchronize ожидает ядра всех потоков выбранного устройства; этот выбор задаёт явную границу для данного протокола.
reset_peak_memory_stats сбрасывает отслеживание пиков от текущего состояния; он не освобождает тензоры программы. Сначала снимите начальные уровни. В конце сохраните оба абсолютных пика и оба текущих уровня. Не представляйте вычитание начального уровня как точный объём всех временных тензоров: во время фазы могли освободиться и более ранние объекты.
Эта инструментация может изменить обычное перекрытие фаз. Используйте её, чтобы локализовать проблему, затем проверьте и полный цикл с его реальным порядком выполнения. При нескольких картах повторяйте чтения для каждого устройства; измерение на cuda:0 не описывает другие GPU.
- 1. Дайте фазе имя и запишите её точные входные данные.
- 2. Синхронизируйте устройство, затем снимите начальные allocated и reserved.
- 3. Вызовите reset_peak_memory_stats на этом же устройстве.
- 4. Выполните заданную фазу, сохранив выходные данные, необходимые для продолжения.
- 5. Синхронизируйте, снимите пики и конечные уровни, затем зафиксируйте успех или ошибку.
- 6. Сохраняйте необработанный результат, размерности и конфигурацию; не заполняйте отсутствующие измерения нулями.
Технические источники: PyTorch — синхронизация устройства · PyTorch — сброс статистики пиков
Различайте первый проход и проходы после прогрева
Первый прогон и уже подготовленный цикл отвечают на разные вопросы. Сохраните след загрузки и первого прохода, затем задокументируйте число итераций прогрева перед повторениями. Не удаляйте неудачную инициализацию на том основании, что последующие проходы якобы оказались легче.
Скрипт IteraGPU различает model_load, inputs, cold_forward, warmup и warm_forward. Его cold_forward — это первый проход небольшой модели после инициализации устройства. Он не измеряет весь запуск сервера, драйвера или службы. Повторения warm_forward остаются в том же процессе и используют его существующее состояние.
Для вашей модели начинайте новую серию в новом процессе, когда вы меняете условие, способное оставить прежние объекты или резервирования. Записывайте порядок прогонов и политику прогрева. Пять раз перезапустить один и тот же цикл и запустить пять процессов — это не один и тот же протокол.
Использование ноутбука и скрипта IteraGPU Lab v1
Начните с README, затем скачайте автономный ноутбук или скрипт Python. Вычисление estimate использует стандартную библиотеку. Измерение требует установленного PyTorch с совместимым GPU-бэкендом и доступным устройством; оно не скачивает ни модель, ни пакет. Ноутбук требует среды, способной читать файлы ipynb.
Упражнение по измерению использует небольшую оригинальную плотную сеть и синтетические входные данные. Параметры batch, context и width описывают её тензоры; context здесь — это не длина настоящей LLM с кэшем KV. Этот материал служит для изучения метода измерения и варьирования одного измерения. Он не демонстрирует возможности видеокарты для вашей исследовательской модели.
Выполните приведённые ниже команды из папки, содержащей скрипт. Сначала ознакомьтесь с отчётом environment. Если PyTorch или GPU отсутствует, measure должен явно остановиться с кодом 2; никакой результат на CPU не должен интерпретироваться как измерение на GPU. Выходной JSON успешного измерения создаётся в вашей среде. Выбирайте новое имя файла для каждой серии: скрипт отказывается перезаписывать существующий результат.
Первая команда заново выполняет расчёт весов и гипотетического резерва в 4 ГиБ. Для последующих используйте устройство, которое вам разрешено нагружать, и поначалу держите скромные размеры. Зафиксируйте фактически используемую версию PyTorch: технические справочные материалы на этой странице описывают, в частности, версию 2.14, не требуя, чтобы она была установлена у вас.
Работа скрипта была проверена на небольшом случае: локальная RTX 5070 вне каталога, драйвер 610.62, Python 3.14.6 и PyTorch 2.11.0+cu128. В прогоне использовались batch 1, контекст 16, ширина 64, float32, один прогрев и два повторения. Он подтверждает этот путь выполнения, не характеризуя ни LLM, ни обучение, ни предлагаемые в аренду GPU. Ноутбук поставляется без выходных данных, а таблица сравнения — без результатов; проверка отсутствия PyTorch также была проведена в отдельной среде.
python mesure_memoire.py estimate --parameters 7000000000 --bits 16 --reserve-gib 4
python mesure_memoire.py environment --device cuda:0
python mesure_memoire.py measure --device cuda:0 --batch 2 --context 128 --width 1024 --dtype float32 --warmup 3 --repeats 5 --output mesures.json- Ноутбук для расчёта и измерения
Автономный ноутбук, который можно открыть, изучить и выполнить в вашей среде.
- Скрипт mesure_memoire.py
Расчёт без внешних зависимостей, проверка среды и явное измерение на GPU.
- Инструкция по работе с папкой
Предварительные требования, команды, охват этапов и ограничения интерпретации.
- Архив IteraGPU Lab v1
Версионированные ресурсы в одном месте, с инструкцией и лицензией.
- Лицензия ресурсов
Условия повторного использования предоставленных файлов.
Как интерпретировать сбой, прежде чем менять видеокарту
Незавершённый прогон остаётся полезным наблюдением. Сохраните этап, запрошенные размеры, сообщение об ошибке и последние доступные значения. Частичный пик перед насыщением не является потребностью в памяти для полного выполнения. Уменьшите только одно измерение, чтобы построить случай, который завершается успешно, затем ищите границу между успехом и неудачей.
empty_cache освобождает неиспользуемые блоки из кэша аллокатора, не освобождая ещё живые тензоры. Это не универсальное исправление при слишком большой нагрузке. Вызов между каждой итерацией меняет условия: задокументируйте этот выбор, вместо того чтобы смешивать такие запуски с теми, где кэш сохраняется.
Если простые счётчики не объясняют ситуацию, трассировка памяти может помочь выявить аллокации во времени. Её охват ограничен аллокациями, видимыми PyTorch. Поэтому низкий пик allocated не исключает внешнюю аллокацию или другого пользователя карты.
| Наблюдение | Полезная проверка | Следующая попытка |
|---|---|---|
| Сбой во время загрузки | Формат загрузки, размещение весов и уже занятая память. | Воспроизвести загрузку отдельно в новом процессе. |
| Загрузка прошла, обратный проход невозможен | Микробатч, входы, сохранённые активации и состояние цикла. | Уменьшить одно измерение, затем выполнить полный шаг заново. |
| Сбой только на этапе оценки | Батч оценки, сохраняемые выходы и контекст вычислений. | Измерять оценку с её собственными ограничениями. |
| Allocated растёт от итерации к итерации | Ссылки, сохраняемые в списках, прикладных кэшах или графах. | Проверить их время жизни, прежде чем винить аллокатор. |
| Reserved остаётся высоким после вычислений | Ещё живые тензоры и политика кэширования. | Сравнивать текущие значения, не складывая счётчики. |
| Системный инструмент показывает больше | Охват инструмента, контекст GPU, другие процессы и библиотеки. | Изолировать нагрузку и сопоставить показания, снятые в один момент. |
Технические источники: PyTorch — что освобождает empty_cache · PyTorch — трассировки и границы видимости памяти
Построение запаса на основе сопоставимых нагрузок
Избегайте процента запаса, подаваемого как универсальный. Запас должен покрывать выявленные вариации: более длинный вход, разрешённый батч, оценку, экспорт, версию библиотеки или иную занятость карты. Проверьте ожидаемые граничные случаи, затем зафиксируйте то, что остаётся за пределами охвата. Успешный запуск на одном небольшом входе не подтверждает максимальную нагрузку.
Меняйте по одной переменной за раз: батч 1, затем 2 при постоянном контексте, либо контексты 2 048, затем 4 096 при постоянном батче. Сохраняйте одинаковое содержимое и одни и те же правила подготовки. Усечение, удаляющее необходимую информацию, делает задачу другой, даже если оно снижает пик.
Если доминируют веса, изучите другой формат, контролируя качество. Если доминируют активации, микробатч или checkpointing активаций могут быть вариантами. Последний обменивает память на пересчёт: измеряйте также длительность и проверяйте результаты. Если доминирует KV-кэш, рассмотрите контекст, параллелизм и стратегию кэширования. Сравнительный материал дополняет этот подход единым правилом качества.
Технические источники: PyTorch — checkpointing активаций и пересчёт
От трассировки к решению о конфигурации
Ваш ожидаемый результат — короткая карточка: оценка весов, максимальная проверенная нагрузка, успешные или неудавшиеся фазы, четыре счётчика с единицами измерения, окружение и выбранный вариант. Приложите к этой карточке необработанный результат. Отделяйте то, что вы рассчитали, то, что вы наблюдали, и то, что вы пока предполагаете.
Затем сопоставьте потребность с ёмкостью каждой карты, сохраняя программные ограничения. Несколько GPU требуют распределения работы и данных; их наличие не создаёт автоматически единый резервуар памяти для приложения. Сбой на одной карте может сохраняться, несмотря на свободную память на другой.
Протокол PyTorch использует интерфейс torch.cuda; сборка PyTorch на HIP/ROCm переиспользует это имя. Определите реально установленный бэкенд, прежде чем сравнивать два семейства оборудования. Использование одной и той же функции Python не доказывает, что ядра, точности или результаты эквивалентны.
Калькулятор размеров позволяет вернуться к исходной гипотезе; карточки GPU позволяют сравнивать ёмкости. Затем вернитесь к тому же рабочему случаю, чтобы проверить выбор. Небольшая сеть из загрузки остаётся упражнением по инструментированию: только выполнение вашей нагрузки, в её задокументированном окружении, может подтвердить ваш собственный запас.
Технические источники: NVIDIA — распределение работы на несколько GPU · PyTorch — интерфейс torch.cuda в сборках HIP/ROCm