Как максимизировать использование графического процессора, найдя правильный размер пакета
Введение
Часто один из наиболее часто задаваемых вопросов новыми учеными по данным и инженерами ML заключается в том, оптимально ли работают их процессы обучения глубокому обучению. В этом руководстве мы узнаем, как диагностировать и устранять проблемы с производительностью глубокого обучения независимо от того, работаем ли мы на одной или нескольких машинах. Это поможет нам понять, как практично и эффективно использовать широкий спектр доступных облачных графических процессоров.
Мы начнем с понимания того, что такое загрузка графического процессора, и закончим обсуждением оптимального размера пакета для максимального использования графического процессора.
Примечание. В этом руководстве предполагается, что у нас есть базовые знания об операционной системе Linux и языке программирования Python. Последние дистрибутивы Linux поставляются с предустановленной Ubuntu, поэтому мы можем установить
pip
иconda
, поскольку мы будем использовать их здесь.
Предварительные условия
Чтобы следовать этой статье, вам понадобится опыт работы с кодом Python и начальное понимание глубокого обучения. Мы будем исходить из предположения, что все читатели имеют доступ к достаточно мощным машинам, чтобы они могли запускать предоставленный код.
Если у вас нет доступа к графическому процессору, мы предлагаем получить к нему доступ через облако. Существует множество облачных провайдеров, предлагающих графические процессоры. DigitalOcean GPU Droplets в настоящее время находится в ранней доступности. Узнайте больше и подпишитесь на интерес к GPU Droplets здесь.
Чтобы получить инструкции по началу работы с кодом Python, мы рекомендуем попробовать это руководство для начинающих, чтобы настроить систему и подготовиться к запуску руководств для начинающих.
Что такое использование графического процессора?
На занятиях по машинному и глубокому обучению использование графического процессора является наиболее важным аспектом, на который следует обратить внимание, и его можно получить с помощью известных сторонних и встроенных инструментов графического процессора.
Мы можем определить загрузку графического процессора как скорость, с которой одно или несколько ядер графического процессора работают за последнюю секунду, что соответствует скорости использования графического процессора программой глубокого обучения. Мы могли бы также сказать, что
Как понять, что вам нужно больше вычислений на графическом процессоре?
Давайте посмотрим на реальный сценарий:
В обычный день специалист по обработке данных получает два графических процессора, которые он/она может использовать – этих ресурсов «должно» быть достаточно. В большинстве дней во время сборки нет проблем с взаимодействием с короткими циклами графического процессора, и рабочий процесс проходит гладко. Затем начинается этап обучения, и внезапно рабочий процесс требует дополнительных вычислений на графическом процессоре, которых нет в наличии.
Это означает, что для выполнения любой существенной работы потребуется больше вычислительных ресурсов. Мы уделяем особое внимание следующим задачам, которые невозможны при выделении всей оперативной памяти:
- Проводите больше экспериментов
- Запустите обучение с использованием нескольких графических процессоров, чтобы ускорить обучение экспериментированию с партиями большего размера и добиться более высокой точности модели.
- Сосредоточьтесь на новой модели, пока модель обучения работает независимо.
Преимущества использования графического процессора
В целом эти обновления приводят к двукратному увеличению использования оборудования и 100 % увеличению скорости обучения модели.
- Использование графического процессора позволит нам более эффективно управлять распределением ресурсов и в конечном итоге сократить время простоя графического процессора и повысить загрузку кластера.
- С точки зрения специалиста по глубокому обучению, потребление большей вычислительной мощности графического процессора даст возможность проводить больше экспериментов, которые повысят нашу производительность и качество их моделей.
- Кроме того, ИТ-администраторы могут запускать модели распределенного обучения с использованием нескольких графических процессоров, например, многопроцессорные машины NVlink, предлагаемые DigitalOcean Droplets, что сокращает время обучения.
Оптимальный размер пакета для использования графического процессора
Общий опыт работы с размером пакета всегда сбивает с толку, поскольку не существует единого «лучшего» размера пакета для данного набора данных и архитектуры модели. Если мы решим выбрать больший размер пакета, он будет обучаться быстрее и потреблять больше памяти, но в конечном итоге может показать меньшую точность. Для начала давайте разберемся, что такое размер партии и зачем он вам нужен.
Что такое размер партии?
Важно указать размер пакета, когда речь идет об обучении модели, такой как нейронная сеть глубокого обучения. Проще говоря, размер партии — это количество образцов, которые будут переданы в сеть за один раз.
Размер партии в примере
Допустим, мы хотим научить нашу сеть распознавать разные породы кошек, используя 1000 фотографий кошек. Давайте теперь предположим, что мы выбрали размер пакета 10. Следовательно, это означает, что в какой-то момент сеть получит 10 фотографий кошек в виде группы или партии в нашем случае.
Отлично, теперь у нас есть представление о размере партии, но какой в этом смысл? Мы могли бы просто передавать в нашу модель каждый элемент данных по отдельности, а не помещать данные в пакеты. Мы объяснили, зачем они нам нужны, в разделе ниже.
Зачем использовать пакеты?
Ранее мы упоминали, что больший размер пакета поможет модели быстрее завершить каждую эпоху во время обучения. Это связано с тем, что машина может создавать гораздо больше одного символа за раз, в зависимости от доступных вычислительных ресурсов.
Однако даже если наша машина способна обрабатывать очень большие партии, конечный результат модели может ухудшиться, если мы установим большую партию, и в конечном итоге может ограничить возможность обобщения модели на новых данных.
Теперь мы можем согласиться с тем, что размер партии — это еще один гиперпараметр, который нам необходимо оценить и настроить в зависимости от того, как конкретная модель ведет себя во время сеансов обучения. Эту настройку также необходимо проверить, чтобы увидеть, насколько хорошо наша машина использует графический процессор при работе с пакетами разных размеров.
Например, если мы установим довольно большой размер пакета, скажем, 100, то вполне возможно, что нашей машине не хватит вычислительной мощности для одновременной обработки всех 100 изображений. Это будет означать, что нам необходимо уменьшить размер партии.
Теперь, когда мы поняли общее представление о том, что такое размер пакета, давайте посмотрим, как мы можем оптимизировать правильный размер пакета в коде с помощью PyTorch и Keras.
Найдите правильный размер пакета с помощью PyTorch
В этом разделе мы рассмотрим поиск правильного размера пакета для модели Resnet18
. Мы будем использовать профилировщик PyTorch для измерения производительности обучения и использования графического процессора модели Resnet18
.
Чтобы продемонстрировать более широкое использование PyTorch на TensorBoard для мониторинга производительности модели, мы будем использовать в этом коде профилировщик PyTorch, но включим дополнительные параметры.
Следуйте этой демонстрации
На вашем облачном компьютере с графическим процессором используйте wget, чтобы загрузить соответствующий блокнот. Затем запустите Jupyter Labs, чтобы открыть блокнот. Вы можете сделать это, вставив следующее и открыв ссылку на блокнот:
wget https://raw.githubusercontent.com/gradient-ai/batch-optimization-DL/refs/heads/main/notebook.ipynb
jupyter lab
Настройка и подготовка данных и модели
Введите следующую команду, чтобы установить torch, torchvision и Profiler.
pip3 install torch torchvision torch-tb-profiler
Следующий код получит наш набор данных из CIFAR10. Далее мы будем использовать трансферное обучение с предварительно обученной моделью resnet18
и обучить ее.
#import all the necessary libraries
import torch
import torch.nn
import torch.optim
import torch.profiler
import torch.utils.data
import torchvision.datasets
import torchvision.models
import torchvision.transforms as T
#prepare input data and transform it
transform = T.Compose(
[T.Resize(224),
T.ToTensor(),
T.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
train_set = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) use dataloader to launch each batch
train_loader = torch.utils.data.DataLoader(train_set, batch_size=1, shuffle=True, num_workers=4) Create a Resnet model, loss function, and optimizer objects. To run on GPU, move model and loss to a GPU device
device = torch.device("cuda:0")
model = torchvision.models.resnet18(pretrained=True).cuda(device)
criterion = torch.nn.CrossEntropyLoss().cuda(device)
optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)
model.train() define the training step for each batch of input data
def train(data):
inputs, labels = data[0].to(device=device), data[1].to(device=device)
outputs = model(inputs)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
Мы успешно настроили нашу базовую модель, теперь мы собираемся включить дополнительные функции профилировщика для записи дополнительной информации во время процесса обучения. Включим следующие параметры:
schedule
– этот параметр принимает одинstep(int)
и возвращает действие профилировщика, которое необходимо выполнить на каждом этапе.profile_memory
— используется для выделения памяти графического процессора, и установка значения true может стоить вам дополнительного времени.with_stack
— используется для записи исходной информации для всех трассировок.
Теперь, когда мы понимаем эти термины, мы можем вернуться к коду:
with torch.profiler.profile(
schedule=torch.profiler.schedule(wait=1, warmup=1, active=3, repeat=2),
on_trace_ready=torch.profiler.tensorboard_trace_handler('./log/resnet18_batchsize1'),
record_shapes=True,
profile_memory=True,
with_stack=True
) as prof:
for step, batch_data in enumerate(train_loader):
if step >= (1 + 1 + 3) * 2:
break
train(batch_data)
prof.step() # Need call this at the end of each step to notify profiler of steps' boundary.
Найдите правильный размер пакета с помощью Keras
В этом случае мы собираемся использовать произвольную последовательную модель;
model = Sequential([
Dense(units=16, input_shape=(1,), activation='relu'),
Dense(units=32, activation='relu', kernel_regularizer=regularizers.l2(0.01)),
Dense(units=2, activation='sigmoid')
])
Давайте сосредоточимся на том, где мы вызываем model.fit()
. Это функция, в которой искусственная нейронная сеть обучается и вызывает обучение нашей модели.
model.fit(
x=scaled_train_samples,
y=train_labels,
validation_data=valid_set,
batch_size=10,
epochs=20,
shuffle=True,
verbose=2
)
Функция fit()
, приведенная выше, принимает параметр batch_size
. Здесь мы присваиваем значение нашей переменной batch_size
. В этой модели мы только что установили значение 10
. Поэтому при обучении этой модели мы будем передавать символы 10
за раз, пока весь цикл не будет завершен. После этого мы можем начать процесс заново, чтобы завершить следующий цикл.
Важные вещи, на которые стоит обратить внимание
При выполнении обучения с несколькими графическими процессорами обращайте пристальное внимание на размер пакета, поскольку он может повлиять на скорость/память, сходимость вашей модели, а если мы не будем осторожны, веса нашей модели могут быть повреждены!
Скорость и память. Без сомнения, обучение и прогнозирование выполняются быстрее при использовании больших пакетов. Небольшие пакеты несут более высокие накладные расходы из-за накладных расходов, связанных с загрузкой и выгрузкой данных из графических процессоров, но некоторые исследования показывают, что обучение с небольшим размером пакета приведет к более высоким общим окончательным оценкам эффективности для таких моделей. С другой стороны, для больших пакетов вам потребуется дополнительная оперативная память графического процессора. Большой размер пакета может привести к проблемам с нехваткой памяти, поскольку входные данные для каждого слоя сохраняются в памяти, особенно во время обучения, когда они необходимы для этапа обратного распространения ошибки.
Сходимость. Если вы обучаете свою модель с помощью стохастического градиентного спуска (SGD) или одного из его вариантов, вы должны знать, что размер пакета может повлиять на то, насколько хорошо ваша сеть сходится и обобщает. Во многих задачах компьютерного зрения размеры пакетов обычно варьируются от 32 до 512 экземпляров.
Повреждение графических процессоров. Эта раздражающая техническая деталь может иметь катастрофические последствия. При выполнении обучения с несколькими графическими процессорами крайне важно предоставлять данные для каждого графического процессора. Последний пакет вашей эпохи может включать меньше данных, чем ожидалось (поскольку размер нашего набора данных нельзя точно разделить на размер нашего пакета).
В результате некоторые графические процессоры могут не получить никаких данных на последнем этапе. К сожалению, некоторые слои Keras — особенно слой пакетной нормализации — не могут справиться с этим, что приводит к появлению значений NaN в весах (текущее среднее и дисперсия в слое BN).
Что еще хуже, поскольку конкретный слой использует среднее значение/дисперсию пакета в оценках, проблема не будет заметна во время обучения (когда фаза обучения равна 1). Однако во время прогнозов используется текущее среднее/дисперсия (фаза обучения установлена на 0), что в нашем сценарии может стать наном, что приведет к некачественным результатам.
Поэтому при выполнении обучения с несколькими графическими процессорами мы всегда должны следить за тем, чтобы размер пакета был фиксированным. Отклонение пакетов, которые не соответствуют заранее заданному размеру, или повторение записей в пакете до тех пор, пока он не достигнет заданного размера, — два простых подхода к достижению этой цели. И последнее, но не менее важное: помните, что в конфигурации с несколькими графическими процессорами размер пакета должен превышать общее количество графических процессоров в вашей системе.
Заключение
В этой статье мы увидели, как использовать различные инструменты для максимизации использования графического процессора за счет выбора правильного размера пакета. Пока вы устанавливаете приемлемый размер пакета (16+) и сохраняете одинаковые итерации и эпохи, размер пакета мало влияет на производительность. Однако это повлияет на время обучения. Мы должны выбрать минимально возможный размер пакета для нескольких графических процессоров, чтобы каждый графический процессор мог тренироваться на полную мощность. 16 на графический процессор — хорошее число.