При обучении больших моделей одно устройство часто не может удовлетворить требования к вычислительным ресурсам и хранению данных, поэтому необходима технология распределенного обучения. Среди них модель параллельная (Модель Parallelism, МП) является важным методом. Основная идея модели параллельнойиз состоит в том, чтобы разделить модель вычислить задачи на приезжать и выполнить их на разных устройствах. , для повышения эффективности обучения и работы с более масштабными моделями. Следующее внимание будет сосредоточено на модели параллельной и зтензорной. параллелизм。
тензорный параллелизм широко используется в технологии распределенного обучения. В предыдущем разделе объяснялось, как использовать данные параллельной реализации для обучения нейронной сети на нескольких отдельных устройствах; этот метод, как правило, один и тот же из модели Копировать. в Все устройства,Каждое отдельное устройство потребляет различную часть входных данных. Хотя это может существенно ускорить тренировочный процесс.,Но существуют в некоторых случаях модель слишком велика, чтобы уместиться в одном устройстве.,Этот подход не работает.
В этой статье показано, какпроходитьиспользоватьНаивный тензорный параллелизмрешить этоиндивидуальныйвопрос。иданныепараллельный Напротив,тензорный параллелизм расколет единую индивидуальную модель, которая будет жить на разных устройствах вместо того, чтобы существовать каждая в дивидуальное устройство копировать индивидуальную полную модель (в частности, при условии индивидуальной модели) m
Включать 6 Слои: при использовании параллелизма данных каждое устройство будет иметь этот уровень. 6 Слой из копии при использовании тензорного режима параллелизм существует два отдельных устройства, каждое индивидуальное устройство имеет только 3 слой).
Приходите и посмотритеиндивидуальный Простойизтензорный параллелизмизпример:
from torchvision.models.resnet import ResNet, Bottleneck
num_classes = 1000
class ModelParallelResNet50(ResNet):
def __init__(self, *args, **kwargs):
super(ModelParallelResNet50, self).__init__(
Bottleneck, [3, 4, 6, 3], num_classes=num_classes, *args, **kwargs)
self.seq1 = nn.Sequential(
self.conv1, self.bn1, self.relu,
self.maxpool, self.layer1,self.layer2
).to('npu:0')
self.seq2 = nn.Sequential(
self.layer3, self.layer4, self.avgpool,
).to('npu:1')
self.fc.to('npu:1')
def forward(self, x):
x = self.seq2(self.seq1(x).to('npu:1'))
return self.fc(x.view(x.size(0), -1))
Код выше показывает, как torchvision.models.resnet50()
Разбейте его на два устройства, поместите каждый блок на отдельное устройство и переместите входы и промежуточные выходы в соответствии с устройством слоя. Идея состоит в том, чтобы наследовать существующий ResNet
модуль и назначьте слои обоим устройствам во время построения. Затем перепишите forward
метод соединяет две подсети путем перемещения промежуточных выходов.
Наивный тензорный параллелизмвыполнить решает проблему, заключающуюся в том, что модель слишком велика, чтобы поместиться в одно индивидуальное устройство. Однако вы могли заметить, что приезжать, если модель способна поместиться в одно индивидуальное устройство, Наивный тензорный параллелизм будет работать медленнее, чем существование на одном индивидуальном устройстве. Это связано с тем, что в любой момент времени работает только одно индивидуальное устройство, а другое индивидуальное устройство простаивает. Когда необходимо получить промежуточный результат npu:0
Копировать в npu:1
, производительность еще больше ухудшится.
на самом деле Наивный тензорный параллелизмвыполнитьвремя выполнения медленнее, чем существующее из одного устройства. 7%
。поэтому,можно сделать вывод,Тензор межплатформенных копирований из накладных расходов составляет прибл. 7%. Есть еще возможности для улучшения, учитывая, что одно устройство простаивает во время выполнения. Один из вариантов — дальнейшее разделение каждого пакета на конвейерные сегменты, чтобы, когда один сегмент прибудет во вторую подсеть, следующий сегмент мог перейти в первую подсеть. Таким образом, два последовательных сегмента могут работать параллельно на обоих устройствах.
простой Наивный тензорный параллелизмизпреимуществосуществовать Ввыполнить相对Простой,Никаких сложных механизмов связи и синхронизации не требуется. Однако,этот методиз Недостатки также очевидны:Если вычислительная нагрузка каждой части модели несбалансирована, это может привести к низкой загрузке некоторого оборудования, что повлияет на общую эффективность обучения.также,Верно. В зависимости от сильной структуры модели простой из Наивный тензорный параллелизм также может быть трудным для выбора.
тензорный параллелизм(Tensor Параллелизм (TP) — это более детальный метод распараллеливания моделей, который разделяет параметры и задачи вычислений в пределах одного уровня на разные устройства для выполнения. Этот метод особенно подходит для крупномасштабных моделей с большим количеством параметров. изначально это было в Megatron-LM предложенная в статье, это эффективная технология распараллеливания моделей, которую можно использовать для обучения крупномасштабных Transformer Модель.
проходитьтензорный Благодаря параллелизму, вы можете разделить матрицу на строки и столбцы, вычислить такие операции, как умножение матриц, а затем существовать параллельно на разных устройствах вычислить, и, наконец, провести сбор коммуникационных операций для объединения результатов. тензорный параллелизм можно разделить на Мат Мул параллель、Трансформатор параллельный、Встраивание параллелей、Параллельная перекрестная потеря энтропии。
где последовательность параллельна (последовательность Параллельный, SP) тоже тензорный Вариант параллелизма, соответствующий размерности последовательности существования. nn.LayerNorm или RMSNorm Сегментация выполняется для дальнейшего сохранения памяти активации во время обучения. По мере того, как модели становятся больше, память активации становится узким местом, поэтому существует тензорный При обучении параллелизму последовательность параллельный обычно применяется к LayerNorm или RMSNorm слой.
тензорный параллелизм. Основная проблема существует в том, как разделить параметры и вычислить задачу.,Обеспечить последовательность вычислений и эффективность коммуникации. Например,существуют при выполнении матричного умножения,Необходимо гарантировать, что частичные результаты на каждом устройстве математически непротиворечивы. также,Накладные расходы на связь также являются важным фактором.,Необходимо найти баланс между общением,Добиться наилучших показателей проживания.
Умножение матриц (MatMul) — одна из наиболее распространенных операций глубокого обучения. существующийтензорный В параллелизме можно разбить матрицу по столбцам или строкам, а затем выполнить вычислить часть на разных устройствах. Умножить на матрицу A \times B = C Например, предположим, что матрица B Разбить на столбцы B_1 и B_2 , хранится отдельно в устройстве 1 èОборудование 2 начальство. В этом случае устройство 1 èОборудование 2 можно рассчитать отдельно B_1 \times A и B_2 \times A , окончательно полученный объединением результатов C 。
существовать Transformer Модель в основном включает в себя модули многослойного перцептрона (MLP) и самообслуживания (Self-Attention), которые по сути представляют собой матричные умножения. для MLP модуль, входная матрица может быть X и весовая матрица A Разделить по столбцу,Различные устройства являются частью продукта.,Затем объедините результаты. Для модуля самообслуживания,Матрицы запроса, ключей и значений можно разделить на столбцы.,Разные устройства имеют разные показатели внимания и взвешенные расчеты.,Наконец объедините результаты.
Для многослойного перцептрона (MLP), для A Используя резку колонны, для B Используя сокращение строк, существование первоначально использует функцию f копировать X, используйте функцию в конце g проходить All-Reduce Краткое содержание Z, причина такой конструкции в том, чтобы попытаться обеспечить независимость вычислений на каждом устройстве друг от друга и уменьшить объем связи. верно A Например, это нужно сделать один раз. GELU расчет, в то время как GELU Функция нелинейная,GeLU(X + Y) \not = GeLU(X) + GeLU(Y) ,верно A Используя резку столбцов, каждое устройство можно в дальнейшем рассчитывать независимо.
Для самовнимания (Self-Attention) три матрицы параметров Q K V, разрезанный колоннами. к линейному слою B,в соответствии с обрезкой рядов, резкой и з способом и MLP Слои в основном одинаковы.
Следует отметить, что из используется в существовании dropout Когда два устройства выполняют вычисления независимо, первое dropout существования необходимо использовать разные случайные начальные числа при инициализации, чтобы это было эквивалентно полному из dropout Выполните инициализацию перед резкой. последний dropout Для обеспечения согласованности необходимо использовать одно и то же случайное начальное число.
существовать Большой Transformer В моделях (таких как LLM) параллельная обработка вложений слов является эффективной технологией, которая может уменьшить нагрузку на память одного устройства и повысить эффективность вычислений. Обычно существует два основных способа сегментации: Табличная. разделить) и по столбцам split)。
Режим сегментации таблицы подходит для сценариев с множеством функций категорий, а таблица внедрения каждой функции категории небольшая. Режим разделения столбцов подходит для сценариев, в которых одна внедренная таблица имеет большой размер и каждая внедренная таблица имеет большое количество столбцов.
Параллельная перекрестная потеря энтропия экономит память и общение при использовании функции потерь существоватьвычислить, поскольку выходные данные модели обычно очень велики. существовать Параллельная перекрестная потеря энтропиисередина,Когда выходные данные модели существуют (обычно огромные) сегментируются по лексическому измерению.,Может эффективно вычислить потери перекрестной энтропии.,Вместо агрегирования всех результатов модели на каждом отдельном устройстве. Это не только значительно снижает потребление памяти,Также снижает накладные расходы на связь, а параллельное сегментирование повышает скорость обучения.
Параллельная перекрестная потеря энтропии Его можно разделить на следующие этапы:
Можетпроходить PyTorch DeviceMesh Реализуйте многомерный параллелизм.
PyTorch изтензорный интерфейс приложения параллелизм (PyTorch Tensor Parallel API) предоставляет набор примитивов на уровне модуля для настройки возможностей сегментирования для различных уровней модели. он использует PyTorch DTensor Инкапсулировать сегментированные тензоры, DeviceMesh Абстракция для управления устройствами и сегментирования. Они делятся на:
потому что Tensor Parallel Один тензор будет сегментирован по набору устройств, поэтому сначала необходимо настроить распределенную среду. Тензор Parallelism Алгоритм сегментирования одной программы с несколькими данными (SPMD), аналогичный PyTorch DDP/FSDP,обычно этосуществовать Работа внутри хоста。
Попробуйте инициализировать один ниже 8 NPU изтензорный параллелизм:
# run this via torchrun: torchrun --standalone --nproc_per_node=8 ./tp_tutorial.py
import torch.nn.functional as F
from torch.distributed.tensor.parallel import loss_parallel
from torch.distributed.device_mesh import init_device_mesh
from torch.distributed.tensor.parallel import (
parallelize_module,
ColwiseParallel,
RowwiseParallel,
PrepareModuleInput,
SequenceParallel,
)
tp_mesh = init_device_mesh("cuda", (8,))
layer_tp_plan = {
# Now the input and output of SequenceParallel has Shard(1) layouts,
# to represent the input/output tensors sharded on the sequence dimension
"attention_norm": SequenceParallel(),
"attention": PrepareModuleInput(
input_layouts=(Shard(1),),
desired_input_layouts=(Replicate(),),
),
"attention.wq": ColwiseParallel(),
"attention.wk": ColwiseParallel(),
"attention.wv": ColwiseParallel(),
"attention.wo": RowwiseParallel(output_layouts=Shard(1)),
"ffn_norm": SequenceParallel(),
"feed_forward": PrepareModuleInput(
input_layouts=(Shard(1),),
desired_input_layouts=(Replicate(),),
),
"feed_forward.w1": ColwiseParallel(),
"feed_forward.w2": RowwiseParallel(output_layouts=Shard(1)),
"feed_forward.w3": ColwiseParallel(),
}
model = parallelize_module(
model,
tp_mesh,
{
"tok_embeddings": RowwiseParallel(
input_layouts=Replicate(),
output_layouts=Shard(1),
),
"norm": SequenceParallel(),
"output": ColwiseParallel(
input_layouts=Shard(1),
# use DTensor as the output
use_local_output=False,
),
},
)
pred = model(input_ids)
with loss_parallel():
# assuming pred and labels are of the shape [batch, seq, vocab]
loss = F.cross_entropy(pred.flatten(0, 1), labels.flatten(0, 1))
loss.backward()
используется здесь init_device_mesh
Функция инициализирует сетку устройства tp_mesh
。этотиндивидуальный网格指定了将использовать 8 индивидуальный NPU Выполните параллельные вычисления.
Определение 1индивидуальный layer_tp_plan
Словарь определяет стратегию изпараллелизации для каждого слоя модели. действовать parallelize_module
Функция, которая может распараллелить модель, указав tok_embeddings
Слой является параллельным, на входе установлено копирование, а на выходе — сегментированный макет (нелокальный вывод); norm
уровень для распараллеливания последовательностей.
существуют В процессе прямого распространения прогнозируемое значение pred
。существовать loss_parallel
контекст, выполнять тензорный параллелизм, вычислить перекрестную потерю энтропии и выполнить обратное распространение ошибки, чтобы вычислить градиент.