English translation is not available yet. Showing Russian content.

Профилировать GPU utilization падение

ТЕХНИЧЕСКОЕ ЗАДАНИЕ: Профилировать GPU utilization падение

1. Цель задачи

Научиться выявлять причины низкой утилизации GPU (ниже 50%) в процессе инференса или обучения модели с помощью профилировщиков NVIDIA Nsight Systems (nsys) и Nsight Compute (ncu). Найти коренную причину простоя GPU, разработать и применить исправление (например, увеличение batch size, оптимизация DataLoader, пересылка тензоров) и добиться роста средней утилизации GPU как минимум на 30% от исходного значения.

Ключевой результат Зафиксированная начальная утилизация GPU (через nvidia-smi или nsys), выявленный bottleneck (CPU-bound, memory-bound, kernel-launch overhead и т.д.), реализованный fix, повторное измерение с подтверждением прироста утилизации ≥ 30%.


2. Исходные данные

Что нужноОткуда взять
Рабочее окружение с доступом к GPU (NVIDIA)Локальный сервер / облачная VM (AWS p3/p4, GCP, Colab Pro)
Модель для инференса или обученияHugging Face модели (BERT, GPT, ResNet) или своя
Нагрузочный скрипт (вызов forward/backward)Написать самому (PyTorch / TensorFlow)
nsys и ncuУстановить NVIDIA Nsight Systems и Nsight Compute (можно через conda)
Логи nvidia-smi с метками времениnvidia-smi --query-gpu=utilization.gpu,memory.used --format=csv -l 1

Если нет реального инструмента — симулируем:

  1. Создайте Python-скрипт имитации низкой утилизации GPU:
    • Используйте маленький batch size (1–4) с частым копированием данных с CPU на GPU.
    • Добавьте искусственные задержки на CPU (например, time.sleep(0.01) внутри DataLoader).
    • Для инференса — запускайте модель на очень маленьких тензорах, вызывая много мелких ядер.
  2. Запустите nsys profile и ncu --set full на этом скрипте, чтобы получить характерные профили низкой утилизации.
  3. Зафиксируйте baseline: средняя utilization.gpu за 1 минуту (команда nvidia-smi каждые 0.5 секунды).

3. Технологический стек

КомпонентИнструментыНазначение
Профилирование GPUNVIDIA Nsight Systems (nsys), Nsight Compute (ncu)Захват трассировки, идентификация узких мест в kernel и потоках
Мониторинг GPUnvidia-smi, watch -n 0.5 nvidia-smiОнлайн-измерение утилизации, памяти, температуры
МодельPyTorch / TensorFlow + предобученная модельГенерация нагрузки на GPU
Анализ данныхPython (pandas, matplotlib), Jupyter NotebookОбработка логов, построение графиков утилизации
Оптимизацияtorch.compile, DataLoader(num_workers=...), torch.cuda.ampПрименение типичных fix'ов для повышения occupancy

4. Этапы выполнения

Этап 1: Baseline и трассировка с nsys (1 час)

Действия

  1. Напишите минимальный нагрузочный скрипт (infer_bad.py), который:
    • Загружает модель (например, bert-base-uncased) на GPU.
    • В цикле из 1000 шагов передаёт на GPU батчи размером 1 (данные – случайные тензоры).
    • Между батчами имитирует CPU-задержку (time.sleep(0.02)).
  2. Запустите nvidia-smi --query-gpu=utilization.gpu,memory.used --format=csv -l 0.5 > baseline.csv в фоне на 5 минут.
    Рассчитайте среднюю утилизацию: awk -F',' '{sum+=$1} END {print sum/NR}' baseline.csv (удалите заголовки).
  3. Выполните профилирование с nsys
    nsys profile --trace-fork-before-exec=true -o profile_infer.qdsh python infer_bad.py
    
    Откройте .qdsh в Nsight Systems GUI (или используйте nsys stats).
  4. С помощью GUI определите процент времени, когда GPU простаивал (idle), а CPU был занят; время на передачу данных CPUGPU; частоту запуска kernel.

Ожидаемый результат этапа

  • Численное значение средней утилизации GPU (baseline).
  • Таблица/визуализация, показывающая, что GPU занят менее 40% времени.
  • Выявленные «узкие места» (например, длинные паузы между kernels из-за sleep или медленного DataLoader).

Этап 2: Deep dive с ncu (1 час)

Действия

  1. Выполните профилирование ядер с ncu
    ncu --set full -o kernel_report python infer_bad.py
    
  2. Откройте отчёт в Nsight Compute
    Обратите внимание на метрики:
    • Occupancy (% активных warp на SM).
    • Memory bandwidth utilization.
    • Compute utilization (в частности, SM Busy).
    • Launch statistics (количество мелких ядер, частота запуска).
  3. Идентифицируйте основной bottleneck
    • Если Occupancy < 50% – скорее всего, неэффективное использование регистров/размер блоков.
    • Если высокая доля времени на memory stalls – неоптимальный доступ к памяти.
    • Если много очень коротких kernel (выполнение < 5 µs) – overhead запуска велик.
  4. Сравните с эталонными значениями (для вашей модели, GPU). Запишите выводы.

Ожидаемый результат этапа

  • Список причин низкой утилизации (например: «60% времени GPU простаивает из-за ожидания данных от CPU», «Occupancy ядра attention составляет 25%»).
  • Скриншоты/заметки из Nsight Compute.

Этап 3: Разработка и применение fix (1–2 часа)

Действия

  1. Исходя из результатов этапов 1-2, выберите одно или несколько исправлений:
    • Увеличить batch size (например, с 1 до 64), если это позволяет память.
    • Убрать time.sleep и использовать асинхронную загрузку (DataLoader с num_workers>0 и pin_memory=True).
    • Упаковать мелкие тензоры в один большой батч или использовать torch.bmm.
    • Включить torch.cuda.amp (automatic mixed precision) для повышения пропускной способности.
    • Использовать torch.compile (если PyTorch 2.x) или @torch.jit.script для сокращения kernel launch overhead.
  2. Модифицируйте скрипт (infer_good.py), применив fix. Задокументируйте изменения в комментариях.
  3. Проведите повторное профилирование
    • Запустите nvidia-smi ещё на 5 минут для новых условий → good.csv.
    • Запустите nsys profile и ncu для нового скрипта.
  4. Сравните метрики
    • Рассчитайте новую среднюю утилизацию. Вычислите прирост:
      (new_util - baseline_util) / baseline_util * 100.
    • Убедитесь, что прирост ≥ 30%.

Ожидаемый результат этапа

  • Рабочий скрипт infer_good.py с применёнными оптимизациями.
  • Файл good.csv с показателями утилизации.
  • Прирост утилизации GPU не менее 30%.

Этап 4: Документирование и анализ (1 час)

Действия

  1. Составьте отчёт в формате Jupyter Notebook (или Markdown) с разделами:
    • Постановка задачи (цель, оборудование).
    • Методика измерений (команды, скрипты).
    • Baseline график утилизации GPU по времени, среднее значение, вывод.
    • Результаты профилирования ключевые показатели из nsys и ncu.
    • Выявленные проблемы (например, «из-за batch size=1 и CPU-задержки средняя утилизация была 18%»).
    • Применённый fix описание изменений, почему они должны помочь.
    • Результаты после фикса новый график, средняя утилизация 85% (прирост +370%).
    • Выводы и рекомендации (например, «всегда использовать num_workers >= 4 для загрузки данных»).
  2. Приложите все исходные данные (csv, log, профили) в отдельную папку.

Ожидаемый результат этапа

  • Отчётный документ (.ipynb или .md) с анализом и визуализациями.
  • Подтверждение, что fix дал прирост ≥ 30%.

5. Критерии приемки (Definition of Done)

  • Написан нагрузочный скрипт с искусственно низкой утилизацией GPU.
  • Снят baseline средней утилизации GPU (минимум 1 минута измерений).
  • Выполнено профилирование с nsys и ncu, сохранены отчёты.
  • Идентифицирована коренная причина низкой утилизации (bottleneck описан текстом).
  • Разработан и реализован хотя бы один оптимизирующий fix.
  • Проведены повторные замеры: средняя утилизация GPU повысилась на ≥ 30% относительно baseline.
  • Составлен отчётный документ (Jupyter Notebook или Markdown) с анализом и графиками.
  • Весь код (скрипты) и данные (csv, профили) загружены в git-репозиторий.

6. Ожидаемый результат

Основной артефакт

  • Файл report.md (или report.ipynb), содержащий:
    • baseline и новую утилизацию (число, график).
    • Скриншоты/выдержки из профилировщиков, показывающие bottleneck.
    • Описание fix.
    • Вычисленный прирост (в процентах).

Дополнительные артефакты

  • infer_bad.py, infer_good.py — скрипты до и после оптимизации.
  • baseline.csv, good.csv — логи nvidia-smi.
  • profile_infer.qdsh, kernel_report.ncu-rep — файлы профилей.

7. Возможные сложности и их решение

СложностьРешение
Нет доступа к реальной модели с заведомо низкой утилизациейСоздать синтетический скрипт с маленьким batch size и CPU-задержками (описано в п.2)
nsys или ncu не установлены / нет прав на установкуИспользовать Docker-образ NVIDIA nvcr.io/nvidia/nsight-systems:latest или nvidia/cuda
Профилирование занимает слишком много времени (1000 шагов)Уменьшить количество итераций до 100, усреднить по 5 прогонам
Высокая утилизация GPU уже на baseline (например, 70%)Усложнить задачу – добавить ещё больше CPU-нагрузки (много numpy на CPU) или уменьшить batch size до 1 и использовать большую модель (LLaMA, ViT)
Непонятно, как интерпретировать результаты nsys / ncuИспользовать встроенные рекомендации (Wizard в Nsight Compute) или документацию NVIDIA
Измерение утилизации через nvidia-smi даёт зашумлённый сигнал (кратковременные пики)Собирать данные раз в 0.5 с и усреднять за >1 минуты; использовать nvidia-smi dmon с агрегацией

8. Бюджет времени (оценка)

ЭтапВремя (часы)
Этап 1: Baseline + nsys1
Этап 2: Deep dive с ncu1
Этап 3: Разработка и применение fix1.5
Этап 4: Документирование1
Запас на настройку окружения0.5
Итого5 часов

Примечание: Для первого выполнения рекомендуется закладывать 6–7 часов, особенно если профилировщики используются впервые.


9. Связанные вопросы из базы знаний

ВопросТема
89Метрики GPU utilisation (SM Occupancy, Mem BW)
93Разница между nsys и ncu
94Профилирование PyTorch моделей
95DataLoader bottlenecks и CPU-GPU синхронизация
97Оптимизация batch size и памяти
123Mixed Precision Training (AMP)
201Kernel launch overhead (CPU side)
345Уменьшение времени передачи данных CPU→GPU
402Инструменты NVIDIA Nsight Systems
503Occupancy и регулирование числа потоков блока

10. Чек-лист самопроверки

  • Я убедился, что на моей системе установлены nsys, ncu и nvidia-smi.
  • Я создал репродуцируемый сценарий с низкой утилизацией GPU (батч 1 + CPU-задержка).
  • Я засёк baseline утилизации (не менее 1 минуты).
  • Я выполнил профилирование с nsys и ncu и сохранил отчёты.
  • Я идентифицировал хотя бы один bottleneck и записал его.
  • Я применил fix и подтвердил прирост утилизации ≥ 30% на тех же данных.
  • Я оформил результаты в виде отчёта со сравнением графиков «до» и «после».
  • Я загрузил всё (скрипты, csv, профили) в репозиторий или папку задания.