Вопрос или проблема
Я занимаюсь доказательством концепции (POC) генерации текста с помощью LLM. У меня есть один экземпляр AWS p3.8x, который имеет 4 GPU, каждая объемом 16 ГБ. Я довольно новичок в использовании LLM и GPU. Когда я пытаюсь загрузить предобученную модель LLM (WizardLM) на GPU, он говорит, что 16 ГБ недостаточно. Поэтому мой вопрос: как я могу загрузить модель, используя все 64 ГБ?
Использование нескольких GPU обычно означает, что вся модель копируется в память каждой из них. В Pytorch это достигается с помощью nn.DataParallel или nn.parallel.DistributedDataParallel. Однако это не то, что вам нужно.
Можно загрузить части модели на разные GPU и распределить вычисления между ними. Однако это требует специальной логики кода для распределения и координации различных частей. Невозможно автоматически распределить модель по частям между различными GPU.
Ваши варианты:
- Использовать более маленькую модель, которая помещается на 16 ГБ.
- Использовать GPU с достаточной памятью, чтобы вмещать вашу текущую модель.
- Использовать квантизированную версию вашей модели, которая достаточно мала.
- Выполнить вывод на процессоре (CPU). Это может быть очень медленно. Вы можете проверить, есть ли реализация на C++ для вашей модели, использующая параллельные наборы инструкций CPU для ускорения вывода; например, для Llama можно использовать llama.cpp.
В ответ на noe: как вы учитываете тот факт, что 2xRTX3090 могут запустить модель Llama 70B q4 llm, а один RTX3090 не может? Источник: https://github.com/XiongjieDai/GPU-Benchmarks-on-LLM-Inference
Ответ или решение
Загрузка моделей машинного обучения на нескольких GPU — это задача, требующая детального понимания архитектуры модели и принципов работы GPU. В вашем случае, вы работаете с AWS p3.8x instance, который оснащен четырьмя графическими процессорами, каждый из которых имеет 16 ГБ видеопамяти. Задача состоит в том, чтобы загрузить модель (в вашем случае — WizardLM), объем которой превышает 16 ГБ, в общую память всех четырех GPU, то есть на 64 ГБ.
Теория
Прежде всего, необходимо понять, как происходит распределение модели в графической памяти. Обычно моделям машинного обучения требуется загружаться полностью в память одного устройства, что создает проблему, когда объем модели превышает доступную память одного GPU. В сфере глубинного обучения (Deep Learning) есть два распространенных подхода к работе с несколькими GPU: Data Parallelism (параллелизм данных) и Model Parallelism (параллелизм моделей).
Data Parallelism предполагает распределение данных по нескольким GPU. Каждая копия модели обучается на различных подмножествах данных, а затем результаты объединяются. Это эффективно для задач обучения, но не решает проблемы большого объема модели, так как каждая из копий модели должна помещаться на один GPU.
Model Parallelism предполагает распределение частей модели по нескольким GPU. Это позволяет обрабатывать модели, которые не помещаются на один GPU, разбивая их на части, каждая из которых помещается на отдельный GPU. Данный подход требует специфической архитектуры и кодовой логики для управления распределением и синхронизацией частей модели.
Пример
Рассмотрим пример, который демонстрирует использование параллелизма моделей в PyTorch. PyTorch предоставляет возможность управлять распределением модели по нескольким GPU, используя базовые средства для параллелизма. При распределении модели вручную, потребуется сосредоточиться на том, как переписывать механизм прямого и обратного прохода таким образом, чтобы разные слои находились на разных устройствах:
import torch
import torch.nn as nn
# Предположим, у вас есть простая модель с двумя слоями
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.layer1 = nn.Linear(10, 10)
self.layer2 = nn.Linear(10, 10)
def forward(self, x):
x = self.layer1(x.to('cuda:0'))
x = self.layer2(x.to('cuda:1'))
return x
# Инициализация модели
model = MyModel()
# Перемещение отдельных частей модели на разные GPU
model.layer1.to('cuda:0')
model.layer2.to('cuda:1')
# Создание входных данных и перемещение их на первый GPU
input_data = torch.randn(5, 10).to('cuda:0')
# Вызов forward pass
output = model(input_data)
print(output)
Это дает базовое представление о том, как можно разделить модель. На практике же крупные модели, такие как недавно обученные LLM, могут потребовать инструментальных средств более высокого уровня, таких как мегапакеты распределенной обработки, например PyTorch’s DistributedDataParallel или специализированные библиотеки, такие как Hugging Face Transformers, поддерживающие дальнейшую интеграцию для распределенной нагрузки моделей.
Применение
Применительно к вашей задаче, упаковка модели на нескольких GPU с использованием Model Parallelism может выглядеть следующим образом:
-
Сегментирование модели: Исследуйте архитектуру WizardLM, чтобы понять, какие конкретно части можно распределить по разным GPU. Получите модель в формате, который позволяет изменения на уровне кода, например, через Hugging Face Transformers, если это возможно.
-
Распределение задачи: Используйте Model Parallelism для ручного размещения слоев или других компонент модели на отдельных GPUs. Это может включать в себя разбивку модели на группы слоев и применение описанной выше методики.
-
Библиотеки и ресурсы: Исследуйте возможные внедрения решения с использованием библиотек, поддерживающих оптимизацию моделирования в распределенной среде, таких как DeepSpeed от Microsoft или Megatron-Triton.
-
Тестирование и валидация: Протестируйте корректность распределения и производительность модели в данной среде. Учтите, что работа с многопоточной средой может вызвать коллизии в плане памяти и синхронизации, которые важно решить для плавной обработки задач.
Если появляется вторая часть, касающаяся запусков, как у Llama с использованием двух RTX3090, причина заключается, возможно, в специфических архитектурных решениях этого фреймворка для деления модели: некоторые модели имеют встроенные механизмы или версии, которые поддерживают специфические формы квантизации или шардирования, эффективно использующие преимущества коммуникации между GPU.
Таким образом, грамотное использование Model Parallelism на основе специфики вашей модели и ожидаемой конфигурации вычислительных ресурсов позволит вам загрузить и использовать ваш языковой модуль, полностью применяя доступные вычислительные мощности AWS p3.8x instance.