GPU для исследований в ML · Криптооплата без KYC
IteraGPU
Метод 01 · От оценки к измерению

Почему пик памяти превышает вашу оценку?

Формула весов описывает хранение параметров; пик описывает выполнение с его входными данными и временными аллокациями. Чтобы объяснить расхождение, сохраняйте одни и те же единицы, измеряйте каждую фазу и разделяйте выделенную память, зарезервированную память и занятость карты. Комплект IteraGPU Lab v1 предоставляет воспроизводимый расчёт и небольшое инструментированное упражнение. Приведённые ниже иллюстративные числа — это расчёты, а не опубликованные измерения GPU.

01 /

Определить нагрузку до выбора счётчика

«Модель 7B» не уточняет ни представление весов, ни выполняемую работу. Зафиксируйте её ревизию, фреймворк, версии расширений, реально загружаемый формат и операцию: обучение, адаптацию или генерацию. Для текста отметьте длины входа и выхода; для зрения — разрешение и число изображений. Мультимодальная модель требует сохранения обоих этих измерений.

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

Также зафиксируйте то, что одновременно остаётся в памяти: одна последовательность, микробатч, несколько запросов или оценка, запущенная после обучения. Ваш вопрос становится проверяемым: помещается ли эта полная нагрузка на каждое используемое устройство, в том числе на самом требовательном её этапе?

  • Идентичность испытания: модель или код, ревизия, набор входных данных и зерно, когда это уместно.
  • Размерности: batch, контекст, сгенерированные токены, разрешение или число одновременных запросов.
  • Среда: выбранный GPU, драйвер, Python, PyTorch, backend CUDA или HIP/ROCm и настройки аллокатора.
  • Область измерения: загрузка, вычисления, передача, оценка, экспорт; первый проход или проход после прогрева.
02 /

Считайте вес, не смешивая 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 = параметры × бит на параметр ÷ 8 ÷ 1 073 741 824
Иллюстративный расчёт для 7 000 000 000 параметров; не результат выполнения.
Гипотеза храненияВычисленные байтыПримерно GiB
32 бита однородно28 000 000 00026,08
16 бит однородно14 000 000 00013,04
4 бита компактно, без метаданных3 500 000 0003,26

Технические источники: NIST — двоичные приставки и сравнение GB/GiB · Hugging Face — форматы и квантованные модули с bitsandbytes

03 /

При обучении измеряйте полный шаг

Веса сосуществуют с другими объектами: градиентами, состояниями оптимизатора, активациями, необходимыми для обратного прохода, и временными тензорами. Их размеры зависят от цикла, точности и размеров нагрузки. Универсальная константа в байтах на параметр скрыла бы, в частности, влияние микробатча и входных данных.

Инструментируйте прямой проход, вычисление потерь, обратное распространение и обновление. Чтобы увидеть состояния, реально создаваемые вашим оптимизатором, не останавливайтесь на загрузке модели. Сохраняйте также измерение первого полного шага: успешный прогрев мог уже выполнить инициализацию, которую вы должны иметь возможность оплатить памятью при запуске.

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

Технические источники: Hugging Face — категории памяти во время обучения

04 /

При инференсе следите за контекстом и параллелизмом

В авторегрессивной генерации с вниманием KV-кэш хранит состояния, связанные с токенами. Для однородного плотного кэша его размер зависит от слоёв, KV-голов, их размерности, сохраняемых токенов и одновременно присутствующих последовательностей. Используйте KV-головы модели, а не автоматически её головы запросов.

Арифметический пример: 32 слоя, 8 KV-голов, размерность 128, 8 192 токена, два байта на значение и одна последовательность дают 1 073 741 824 байта, то есть 1 GiB для K и V вместе. Четыре одинаковые последовательности дают 4 GiB только на эту статью. Этот расчёт не измеряет ни пропускную способность, ни полную загрузку GPU.

Адаптируйте формулу к реально используемому кэшу. Скользящее окно не обязательно сохраняет всю историю; статический кэш может предварительно выделять свою максимальную ёмкость. Квантованные и вынесенные кэши также меняют задачу. Измеряйте отдельно начальную обработку входа и генерацию, не приписывая автоматически всё их расхождение кэшу.

Плотный KV в байтах ≈ 2 × слои × KV-головы × размерность головы × сохраняемые токены × последовательности × байт на значение

Технические источники: Hugging Face — стратегии кэширования, статическое выделение и окна

05 /

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 вне его аллокатора

06 /

Почему разница между двумя пиками не измеряет кэш

Рассмотрим только два вымышленных момента из таблицы. Пик allocated равен 8 Gio, а пик reserved — 12 Gio. Их разница, 4 Gio, не равна разнице, наблюдаемой ни в один из этих двух моментов: там она составляет соответственно 2 и 6 Gio. Два максимума не обязательно описывают одно и то же состояние.

Чтобы изучить их расхождение в конкретный момент, снимите allocated и reserved в одной и той же контрольной точке, после синхронизации и без новых намеренных операций между чтениями. Вы получите разницу счётчиков в этот момент, а не измерение KV-кэша модели и не гарантию, что вся эта разница способна удовлетворить следующую аллокацию.

Также сохраняйте в отчёте бэкенд аллокатора. Документация PyTorch 2.14 уточняет, что при cudaMallocAsync max_memory_reserved может объединять наивысшие уровни двух пулов и давать верхнюю границу одновременного пика. Это усиливает необходимость сохранять имя и область действия счётчика.

Два вымышленных состояния для пояснения расчёта; эта таблица не является трассировкой GPU.
Иллюстративный моментAllocatedReservedReserved − allocated в этот момент
A8 Gio10 Gio2 Gio
B6 Gio12 Gio6 Gio

Технические источники: PyTorch — определение и предел max_memory_reserved

07 /

Ограничьте каждую фазу, прежде чем снимать её пик

Операции 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 — сброс статистики пиков

08 /

Различайте первый проход и проходы после прогрева

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

Скрипт IteraGPU различает model_load, inputs, cold_forward, warmup и warm_forward. Его cold_forward — это первый проход небольшой модели после инициализации устройства. Он не измеряет весь запуск сервера, драйвера или службы. Повторения warm_forward остаются в том же процессе и используют его существующее состояние.

Для вашей модели начинайте новую серию в новом процессе, когда вы меняете условие, способное оставить прежние объекты или резервирования. Записывайте порядок прогонов и политику прогрева. Пять раз перезапустить один и тот же цикл и запустить пять процессов — это не один и тот же протокол.

09 /

Использование ноутбука и скрипта 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 также была проведена в отдельной среде.

shell
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
10 /

Как интерпретировать сбой, прежде чем менять видеокарту

Незавершённый прогон остаётся полезным наблюдением. Сохраните этап, запрошенные размеры, сообщение об ошибке и последние доступные значения. Частичный пик перед насыщением не является потребностью в памяти для полного выполнения. Уменьшите только одно измерение, чтобы построить случай, который завершается успешно, затем ищите границу между успехом и неудачей.

empty_cache освобождает неиспользуемые блоки из кэша аллокатора, не освобождая ещё живые тензоры. Это не универсальное исправление при слишком большой нагрузке. Вызов между каждой итерацией меняет условия: задокументируйте этот выбор, вместо того чтобы смешивать такие запуски с теми, где кэш сохраняется.

Если простые счётчики не объясняют ситуацию, трассировка памяти может помочь выявить аллокации во времени. Её охват ограничен аллокациями, видимыми PyTorch. Поэтому низкий пик allocated не исключает внешнюю аллокацию или другого пользователя карты.

Связать симптом со следующей проверкой, без автоматического диагноза.
НаблюдениеПолезная проверкаСледующая попытка
Сбой во время загрузкиФормат загрузки, размещение весов и уже занятая память.Воспроизвести загрузку отдельно в новом процессе.
Загрузка прошла, обратный проход невозможенМикробатч, входы, сохранённые активации и состояние цикла.Уменьшить одно измерение, затем выполнить полный шаг заново.
Сбой только на этапе оценкиБатч оценки, сохраняемые выходы и контекст вычислений.Измерять оценку с её собственными ограничениями.
Allocated растёт от итерации к итерацииСсылки, сохраняемые в списках, прикладных кэшах или графах.Проверить их время жизни, прежде чем винить аллокатор.
Reserved остаётся высоким после вычисленийЕщё живые тензоры и политика кэширования.Сравнивать текущие значения, не складывая счётчики.
Системный инструмент показывает большеОхват инструмента, контекст GPU, другие процессы и библиотеки.Изолировать нагрузку и сопоставить показания, снятые в один момент.

Технические источники: PyTorch — что освобождает empty_cache · PyTorch — трассировки и границы видимости памяти

11 /

Построение запаса на основе сопоставимых нагрузок

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

Меняйте по одной переменной за раз: батч 1, затем 2 при постоянном контексте, либо контексты 2 048, затем 4 096 при постоянном батче. Сохраняйте одинаковое содержимое и одни и те же правила подготовки. Усечение, удаляющее необходимую информацию, делает задачу другой, даже если оно снижает пик.

Если доминируют веса, изучите другой формат, контролируя качество. Если доминируют активации, микробатч или checkpointing активаций могут быть вариантами. Последний обменивает память на пересчёт: измеряйте также длительность и проверяйте результаты. Если доминирует KV-кэш, рассмотрите контекст, параллелизм и стратегию кэширования. Сравнительный материал дополняет этот подход единым правилом качества.

Технические источники: PyTorch — checkpointing активаций и пересчёт

12 /

От трассировки к решению о конфигурации

Ваш ожидаемый результат — короткая карточка: оценка весов, максимальная проверенная нагрузка, успешные или неудавшиеся фазы, четыре счётчика с единицами измерения, окружение и выбранный вариант. Приложите к этой карточке необработанный результат. Отделяйте то, что вы рассчитали, то, что вы наблюдали, и то, что вы пока предполагаете.

Затем сопоставьте потребность с ёмкостью каждой карты, сохраняя программные ограничения. Несколько GPU требуют распределения работы и данных; их наличие не создаёт автоматически единый резервуар памяти для приложения. Сбой на одной карте может сохраняться, несмотря на свободную память на другой.

Протокол PyTorch использует интерфейс torch.cuda; сборка PyTorch на HIP/ROCm переиспользует это имя. Определите реально установленный бэкенд, прежде чем сравнивать два семейства оборудования. Использование одной и той же функции Python не доказывает, что ядра, точности или результаты эквивалентны.

Калькулятор размеров позволяет вернуться к исходной гипотезе; карточки GPU позволяют сравнивать ёмкости. Затем вернитесь к тому же рабочему случаю, чтобы проверить выбор. Небольшая сеть из загрузки остаётся упражнением по инструментированию: только выполнение вашей нагрузки, в её задокументированном окружении, может подтвердить ваш собственный запас.

Технические источники: NVIDIA — распределение работы на несколько GPU · PyTorch — интерфейс torch.cuda в сборках HIP/ROCm