Руководство по распределенному обучению с поддержкой GPU (пакет SDK версии 1)
ОБЛАСТЬ ПРИМЕНЕНИЯ: Пакет SDK для Python версии 1
Узнайте больше об использовании кода распределенного обучения с поддержкой GPU в Машинном обучении Azure (ML). Эта статья не поможет вам изучить распределенное обучение. Она поможет вам запустить существующий код распределенного обучения в Машинном обучении Azure. В ней представлены советы и примеры для каждой из платформ:
- Интерфейс передачи сообщений (MPI)
- Horovod
- DeepSpeed
- Переменные среды из Open MPI
- PyTorch
- инициализация группы процессов;
- параметры запуска;
- DistributedDataParallel (per-process-launcher);
- использование
torch.distributed.launch
(per-node-launcher); - PyTorch Lightning;
- библиотека Transformers в Hugging Face.
- TensorFlow
- переменные среды для TensorFlow (TF_CONFIG).
- Ускорение обучения с поддержкой GPU с помощью InfiniBand.
Необходимые компоненты
Ознакомьтесь с основными принципами распределенного обучения с поддержкой GPU, например с параллельной обработкой данных, параллельной обработкой распределенных данных и параллельной обработкой моделей.
Совет
Если неизвестно, какой тип параллельной обработки нужно использовать, то более 90 % времени следует использовать параллельную обработку распределенных данных.
MPI
Машинное обучение Azure предлагает Задание MPI для запуска заданного количества процессов в каждом узле. Этот подход можно использовать для выполнения распределенного обучения в режиме per-process-launcher или per-node-launcher в зависимости от того, задано ли для параметра process_count_per_node
значение 1 (по умолчанию) для per-node-launcher или для него задано число устройств и GPU для per-process-launcher. Машинное обучение Azure создает полную команду запуска MPI (mpirun
) за кулисами. Вы не можете предоставить собственные полные команды head-node-launcher, такие как mpirun
или DeepSpeed launcher
.
Совет
В базовом образе Docker, используемом заданием MPI Машинного обучения Azure, должна быть установлена библиотека MPI. Открытие MPI включается во все базовые образы gpu Машинное обучение Azure. При использовании пользовательского образа Docker вы несете ответственность за то, чтобы он включал в себя библиотеку MPI. Рекомендуется использовать Open MPI, но вы можете также использовать другую реализацию MPI, например Intel MPI. Машинное обучение Azure также предоставляет курируемые среды для популярных платформ.
Чтобы выполнить распределенное обучение с помощью MPI, сделайте следующее.
- Используйте среду Машинное обучение Azure с предпочтительной платформой глубокого обучения и MPI. Машинное обучение Azure предоставляет курированную среду для популярных платформ.
- Определите
MpiConfiguration
сprocess_count_per_node
иnode_count
. Значениеprocess_count_per_node
должно равняться количеству GPU на узел для режима per-process-launcher или равняться 1 (по умолчанию) для режима per-node-launcher, если пользовательский сценарий будет отвечать за запуск процессов на каждом узле. - Передайте объект
MpiConfiguration
в параметрdistributed_job_config
конфигурацииScriptRunConfig
.
from azureml.core import Workspace, ScriptRunConfig, Environment, Experiment
from azureml.core.runconfig import MpiConfiguration
curated_env_name = 'AzureML-PyTorch-1.6-GPU'
pytorch_env = Environment.get(workspace=ws, name=curated_env_name)
distr_config = MpiConfiguration(process_count_per_node=4, node_count=2)
run_config = ScriptRunConfig(
source_directory= './src',
script='train.py',
compute_target=compute_target,
environment=pytorch_env,
distributed_job_config=distr_config,
)
# submit the run configuration to start the job
run = Experiment(ws, "experiment_name").submit(run_config)
Horovod
Используйте конфигурацию задания MPI для распределенного обучения с помощью платформы глубокого обучения Horovod.
Убедитесь, что в вашем коде применены следующие советы.
- Код обучения правильно инструментирован с Horovod перед добавлением Машинное обучение Azure частей
- Среда Машинное обучение Azure содержит Horovod и MPI. Курированные среды с поддержкой GPU PyTorch и TensorFlow предварительно настроены с помощью Horovod и соответствующих зависимостей.
- Создайте
MpiConfiguration
с требуемым распределением.
Пример Horovod
DeepSpeed
Не используйте пользовательский средство запуска DeepSpeed для выполнения распределенного обучения с библиотекой DeepSpeed на Машинное обучение Azure. Вместо этого настройте задание MPI для запуска задания обучения с помощью MPI.
Убедитесь, что в вашем коде применены следующие советы.
- Среда Машинное обучение Azure содержит DeepSpeed и его зависимости, Open MPI и mpi4py.
- Создайте
MpiConfiguration
с требуемым распределением.
Пример DeepSpeed
Переменные среды из Open MPI
При выполнении заданий MPI с образами Open MPI для каждого запущенного процесса используются следующие переменные среды:
-
OMPI_COMM_WORLD_RANK
— ранг процесса; -
OMPI_COMM_WORLD_SIZE
— размер пакета; -
AZ_BATCH_MASTER_NODE
— основной адрес с портом,MASTER_ADDR:MASTER_PORT
; -
OMPI_COMM_WORLD_LOCAL_RANK
— локальный ранг процесса на узле; -
OMPI_COMM_WORLD_LOCAL_SIZE
— количество процессов на узле.
Совет
Несмотря на имя, переменная среды не OMPI_COMM_WORLD_NODE_RANK
соответствует NODE_RANK
. Чтобы использовать режим per-node-launcher, задайте process_count_per_node=1
и используйте OMPI_COMM_WORLD_RANK
в качестве NODE_RANK
.
PyTorch
Машинное обучение Azure поддерживает выполнение распределенных заданий с помощью собственных возможностей распределенного обучения PyTorch (torch.distributed
).
Совет
Для параллельной обработки данных в официальном руководстве по PyTorch предписывается использовать DistributedDataParallel (DDP) и DataParallel для распределенного обучения как с одним узлом, так и с несколькими узлами. PyTorch также рекомендует использовать DistributedDataParallel в пакете многопроцессной обработки. Поэтому документация и примеры для Машинного обучения Azure будут сосредоточены на обучении DistributedDataParallel.
инициализация группы процессов;
Основа любого распределенного обучения — это группа процессов, которые связаны и могут взаимодействовать друг с другом, используя внутренний сервер. Для PyTorch группа процессов создается путем вызова torch.distributed.init_process_group во всех распределенных процессах для формирования группы процессов.
torch.distributed.init_process_group(backend='nccl', init_method='env://', ...)
Наиболее распространенные внутренние серверы подключений: mpi
, nccl
и gloo
. Для обучения с поддержкой GPU рекомендуется использовать nccl
, чтобы обеспечить оптимальную производительность, когда это возможно.
init_method
указывает, как процессы могут обнаружить друг друга, как они инициализируются и проверяют группу процессов, используя внутренний сервер подключений. По умолчанию, если параметр init_method
не указан, PyTorch будет использовать метод инициализации переменной среды (env://
).
init_method
— рекомендуемый метод инициализации для использования в коде обучения для запуска распределенного PyTorch на Машинное обучение Azure. PyTorch будет искать следующие переменные среды для инициализации:
-
MASTER_ADDR
— IP-адрес компьютера, на котором будет размещен процесс с рангом 0. -
MASTER_PORT
— свободный порт компьютера, на котором будет размещен процесс с рангом 0. -
WORLD_SIZE
— общее количество процессов. Оно должно быть равно общему количеству устройств (GPU), используемых для распределенного обучения. -
RANK
— ранг (глобальный) текущего процесса. Возможные значения: от 0 до (world_size — 1).
Дополнительные сведения об инициализации группы процессов см. в документации по PyTorch.
Помимо этого, многим приложениям также потребуются следующие переменные среды:
-
LOCAL_RANK
— локальный (относительный) ранг процесса в пределах узла. Возможные значения: от 0 до (число процессов на узле — 1). Эта информация полезна, так как многие операции, такие как подготовка данных, должны выполняться один раз для каждого узла (обычно для local_rank = 0). -
NODE_RANK
— ранг узла для обучения с несколькими узлами. Возможные значения: от 0 до (общее число узлов — 1).
Параметры запуска PyTorch
Задание pyTorch Машинное обучение Azure поддерживает два типа вариантов запуска распределенного обучения:
- Режим per-process-launcher. Система запустит все распределенные процессы со всеми соответствующими сведениями (например, переменными среды) в группе процессов.
-
Средство запуска для каждого узла: вы предоставляете Машинное обучение Azure с помощью средства запуска служебной программы, который будет выполняться на каждом узле. Эта служебная программа запуска будет обрабатывать запуск каждого процесса на заданном узле. Средство запуска локально на каждом узле настраивает
RANK
иLOCAL_RANK
. Служебная программа torch.distributed.launch и PyTorch Lightning относятся к этой категории.
Между этими режимами запуска нет фундаментальных отличий. В основном выбор зависит от предпочтений пользователя или соглашений о платформах и библиотеках, созданных на основе обыкновенного PyTorch (такого как Lightning или Hugging Face).
В следующих разделах подробно описано, как настроить Машинное обучение Azure задания PyTorch для каждого из вариантов запуска.
DistributedDataParallel (per-process-launcher);
Не нужно использовать служебную программу запуска, например torch.distributed.launch
. Чтобы отправить распределенное задание PyTorch, сделайте следующее.
- Укажите сценарий обучения и аргументы.
- Создайте
PyTorchConfiguration
, затем укажитеprocess_count
иnode_count
.process_count
соответствует общему количеству процессов, которые вы хотите выполнить для задания. Обычно значениеprocess_count
равно# GPUs per node x # nodes
. Еслиprocess_count
не указано, Машинное обучение Azure по умолчанию запускает один процесс на узел.
Машинное обучение Azure задает MASTER_ADDR
переменные среды и MASTER_PORT
NODE_RANK
WORLD_SIZE
переменные среды на каждом узле и задает переменные уровня процесса RANK
и LOCAL_RANK
среды.
Чтобы использовать этот параметр для обучения с несколькими процессами на узел, используйте пакет SDK >= 1.22.0
для Python Машинное обучение Azure. Параметр process_count был введен в версии 1.22.0.
from azureml.core import ScriptRunConfig, Environment, Experiment
from azureml.core.runconfig import PyTorchConfiguration
curated_env_name = 'AzureML-PyTorch-1.6-GPU'
pytorch_env = Environment.get(workspace=ws, name=curated_env_name)
distr_config = PyTorchConfiguration(process_count=8, node_count=2)
run_config = ScriptRunConfig(
source_directory='./src',
script='train.py',
arguments=['--epochs', 50],
compute_target=compute_target,
environment=pytorch_env,
distributed_job_config=distr_config,
)
run = Experiment(ws, 'experiment_name').submit(run_config)
Совет
Если ваш сценарий обучения передает такие сведения, как ранг или локальный ранг, в качестве аргументов сценария, вы можете ссылаться в аргументах на переменные среды:
arguments=['--epochs', 50, '--local_rank', $LOCAL_RANK]
Пример запуска pyTorch для каждого процесса
Использование torch.distributed.launch (per-node-launch)
PyTorch предоставляет в torch.distributed.launch служебную программу запуска, которую можно использовать для запуска нескольких процессов на каждом узле. Модуль torch.distributed.launch
порождает несколько процессов обучения на каждом из узлов.
Ниже показано, как настроить задание PyTorch с помощью средства запуска для каждого узла на Машинное обучение Azure. Задание достигает эквивалента выполнения следующей команды:
python -m torch.distributed.launch --nproc_per_node <num processes per node> \
--nnodes <num nodes> --node_rank $NODE_RANK --master_addr $MASTER_ADDR \
--master_port $MASTER_PORT --use_env \
<your training script> <your script arguments>
- Укажите команду
torch.distributed.launch
в параметреcommand
конструктораScriptRunConfig
. Машинное обучение Azure выполняет эту команду на каждом узле учебного кластера. Значение--nproc_per_node
должно быть меньше или равно количеству GPU, доступных на каждом узле. MASTER_ADDR, MASTER_PORT и NODE_RANK задаются Машинное обучение Azure, поэтому можно просто ссылаться на переменные среды в команде. Машинное обучение Azure задает значение MASTER_PORT6105
, но при желании можно передать другое значение--master_port
в аргумент команды torch.distributed.launch. (Служебная программа запуска выполнит сброс переменных среды.) - Создайте
PyTorchConfiguration
и укажитеnode_count
.
from azureml.core import ScriptRunConfig, Environment, Experiment
from azureml.core.runconfig import PyTorchConfiguration
curated_env_name = 'AzureML-PyTorch-1.6-GPU'
pytorch_env = Environment.get(workspace=ws, name=curated_env_name)
distr_config = PyTorchConfiguration(node_count=2)
launch_cmd = "python -m torch.distributed.launch --nproc_per_node 4 --nnodes 2 --node_rank $NODE_RANK --master_addr $MASTER_ADDR --master_port $MASTER_PORT --use_env train.py --epochs 50".split()
run_config = ScriptRunConfig(
source_directory='./src',
command=launch_cmd,
compute_target=compute_target,
environment=pytorch_env,
distributed_job_config=distr_config,
)
run = Experiment(ws, 'experiment_name').submit(run_config)
Совет
Обучение на одном узле с несколькими GPU. Если вы используете служебную программу запуска для выполнения задания обучения PyTorch на одном узле с несколькими GPU, вам не нужно указывать параметр distributed_job_config
для ScriptRunConfig.
launch_cmd = "python -m torch.distributed.launch --nproc_per_node 4 --use_env train.py --epochs 50".split()
run_config = ScriptRunConfig(
source_directory='./src',
command=launch_cmd,
compute_target=compute_target,
environment=pytorch_env,
)
Пример PyTorch для режима per-node-launcher
PyTorch Lightning;
PyTorch Lightning — это упрощенная библиотека с открытым кодом, которая предоставляет высокоуровневый интерфейс для PyTorch. Lightning абстрагируется от многих низкоуровневых конфигураций распределенного обучения, необходимых для обыкновенного PyTorch. Lightning позволяет запускать сценарии обучения на одном GPU, на одном узле с несколькими GPU и на нескольких узлах с несколькими GPU. В фоновом режиме Lightning запускает несколько процессов, как и torch.distributed.launch
.
Для обучения с одним узлом (включая один узел с несколькими GPU), можно запустить код на Машинное обучение Azure без необходимости указыватьdistributed_job_config
.
Существует 2 варианта запуска эксперимента с использованием нескольких узлов с несколькими графическими процессорами:
Использование конфигурации PyTorch (рекомендуется): определите
PyTorchConfiguration
, укажитеcommunication_backend="Nccl"
,node_count
иprocess_count
(обратите внимание, что это общее количество процессов, т. еnum_nodes * process_count_per_node
). В модуле Lightning Trainer укажите какnum_nodes
, так иgpus
, чтобы они соответствовалиPyTorchConfiguration
. Например,num_nodes = node_count
иgpus = process_count_per_node
.Использование конфигурации MPI:
Определите
MpiConfiguration
и укажите какnode_count
, так иprocess_count_per_node
. В модуле Lightning Trainer укажите, чтоnum_nodes
иgpus
должны быть соответственно такими же, какnode_count
иprocess_count_per_node
изMpiConfiguration
.Для обучения с несколькими узлами с помощью MPI для Lightning требуется, чтобы следующие переменные среды были установлены на каждом узле кластера обучения:
- MASTER_ADDR
- MASTER_PORT
- NODE_RANK
- LOCAL_RANK
Вручную задайте эти переменные среды, необходимые Lightning в основных сценариях обучения:
import os from argparse import ArgumentParser def set_environment_variables_for_mpi(num_nodes, gpus_per_node, master_port=54965): if num_nodes > 1: os.environ["MASTER_ADDR"], os.environ["MASTER_PORT"] = os.environ["AZ_BATCH_MASTER_NODE"].split(":") else: os.environ["MASTER_ADDR"] = os.environ["AZ_BATCHAI_MPI_MASTER_NODE"] os.environ["MASTER_PORT"] = str(master_port) try: os.environ["NODE_RANK"] = str(int(os.environ.get("OMPI_COMM_WORLD_RANK")) // gpus_per_node) # additional variables os.environ["MASTER_ADDRESS"] = os.environ["MASTER_ADDR"] os.environ["LOCAL_RANK"] = os.environ["OMPI_COMM_WORLD_LOCAL_RANK"] os.environ["WORLD_SIZE"] = os.environ["OMPI_COMM_WORLD_SIZE"] except: # fails when used with pytorch configuration instead of mpi pass if __name__ == "__main__": parser = ArgumentParser() parser.add_argument("--num_nodes", type=int, required=True) parser.add_argument("--gpus_per_node", type=int, required=True) args = parser.parse_args() set_environment_variables_for_mpi(args.num_nodes, args.gpus_per_node) trainer = Trainer( num_nodes=args.num_nodes, gpus=args.gpus_per_node )
Lightning обрабатывает размер пакета в соответствии с флагами инструктора
--gpus
и--num_nodes
.from azureml.core import ScriptRunConfig, Experiment from azureml.core.runconfig import MpiConfiguration nnodes = 2 gpus_per_node = 4 args = ['--max_epochs', 50, '--gpus_per_node', gpus_per_node, '--accelerator', 'ddp', '--num_nodes', nnodes] distr_config = MpiConfiguration(node_count=nnodes, process_count_per_node=gpus_per_node) run_config = ScriptRunConfig( source_directory='./src', script='train.py', arguments=args, compute_target=compute_target, environment=pytorch_env, distributed_job_config=distr_config, ) run = Experiment(ws, 'experiment_name').submit(run_config)
библиотека Transformers в Hugging Face.
Hugging Face предоставляет множество примеров использования собственной библиотеки Transformers с torch.distributed.launch
для распределенного обучения. Чтобы выполнить эти примеры и собственные пользовательские сценарии обучения с помощью API Transformers Trainer, следуйте указаниям в разделе Использование torch.distributed.launch
.
Пример кода конфигурации задания для точной настройки большой модели BERT в задаче классификации текста MNLI с использованием сценария run_glue.py
на одном узле с 8 GPU:
from azureml.core import ScriptRunConfig
from azureml.core.runconfig import PyTorchConfiguration
distr_config = PyTorchConfiguration() # node_count defaults to 1
launch_cmd = "python -m torch.distributed.launch --nproc_per_node 8 text-classification/run_glue.py --model_name_or_path bert-large-uncased-whole-word-masking --task_name mnli --do_train --do_eval --max_seq_length 128 --per_device_train_batch_size 8 --learning_rate 2e-5 --num_train_epochs 3.0 --output_dir /tmp/mnli_output".split()
run_config = ScriptRunConfig(
source_directory='./src',
command=launch_cmd,
compute_target=compute_target,
environment=pytorch_env,
distributed_job_config=distr_config,
)
Вы можете также использовать режим per-process-launcher, чтобы выполнить распределенное обучение без использования torch.distributed.launch
. Следует помнить, что при использовании этого метода преобразователи TrainingArguments ожидают передачи локального ранга в качестве аргумента (--local_rank
).
torch.distributed.launch
это --use_env=False
происходит, если вы используете для запуска для каждого процесса, необходимо явно передать локальный ранг в качестве аргумента в скрипт --local_rank=$LOCAL_RANK
обучения, так как Машинное обучение Azure только задает LOCAL_RANK
переменную среды.
TensorFlow
Если вы используете собственный распределенный TensorFlow в коде обучения, например API TensorFlow 2.xtf.distribute.Strategy
, вы можете запустить распределенное задание с помощью Машинное обучение Azure.TensorflowConfiguration
Для этого укажите объект TensorflowConfiguration
в параметре distributed_job_config
конструктора ScriptRunConfig
. Если вы используете tf.distribute.experimental.MultiWorkerMirroredStrategy
, укажите worker_count
в параметре TensorflowConfiguration
в соответствии с количеством узлов для вашего задания обучения.
from azureml.core import ScriptRunConfig, Environment, Experiment
from azureml.core.runconfig import TensorflowConfiguration
curated_env_name = 'AzureML-TensorFlow-2.3-GPU'
tf_env = Environment.get(workspace=ws, name=curated_env_name)
distr_config = TensorflowConfiguration(worker_count=2, parameter_server_count=0)
run_config = ScriptRunConfig(
source_directory='./src',
script='train.py',
compute_target=compute_target,
environment=tf_env,
distributed_job_config=distr_config,
)
# submit the run configuration to start the job
run = Experiment(ws, "experiment_name").submit(run_config)
Если сценарий обучения использует стратегию сервера параметров для распределенного обучения, например для устаревшего TensorFlow 1.x, вам также придется указать количество серверов параметров, которое будет использоваться в задании, например tf_config = TensorflowConfiguration(worker_count=2, parameter_server_count=1)
.
TF_CONFIG
В TensorFlow для обучения на нескольких компьютерах требуется переменная среды TF_CONFIG. Для заданий TensorFlow Машинное обучение Azure настраивает и задает переменную TF_CONFIG соответствующим образом для каждой рабочей роли перед выполнением скрипта обучения.
При необходимости вы можете обращаться к TF_CONFIG из сценария обучения: os.environ['TF_CONFIG']
.
Пример параметра TF_CONFIG, заданного на главном рабочем узле:
TF_CONFIG='{
"cluster": {
"worker": ["host0:2222", "host1:2222"]
},
"task": {"type": "worker", "index": 0},
"environment": "cloud"
}'
Пример TensorFlow
Ускорение распределенного обучения с поддержкой GPU с помощью InfiniBand
По мере увеличения количества виртуальных машин, обучающих модель, время, необходимое для обучения модели, должно уменьшаться. Уменьшение времени в идеальном случае должно быть пропорционально количеству обучающих виртуальных машин. Например, если обучение модели на одной виртуальной машине занимает 100 секунд, то при обучении той же модели на двух виртуальных машинах в идеале потребуется 50 секунд. Обучение модели на четырех виртуальных машинах займет 25 секунд и т. д.
InfiniBand может играть важную роль в обеспечении такого линейного масштабирования. InfiniBand обеспечивает связь на уровне GPU между узлами в кластере с низкой задержкой. Для работы с InfiniBand требуется специализированное оборудование. Некоторые серии виртуальных машин Azure, в частности серии NC, ND и H, теперь поддерживают виртуальные машины RDMA с поддержкой SR-IOV и InfiniBand. Эти виртуальные машины обмениваются данными по сети InfiniBand с низкой задержкой и высокой пропускной способностью, которая гораздо быстрее, чем сеть Ethernet. SR-IOV для InfiniBand обеспечивает производительность практически на уровне компьютера без операционной системы для любой библиотеки MPI (MPI используется многими платформами и инструментами для распределенного обучения, включая программное обеспечение NVIDIA NCCL). Эти номера SKU предназначены для удовлетворения потребностей ресурсоемких рабочих нагрузок машинного обучения с большим количеством вычислений и поддержкой GPU. Дополнительные сведения см. в разделе Accelerating Distributed Training in Azure Machine Learning with SR-IOV (Ускорение распределенного обучения в Машинном обучении Azure с помощью SR-IOV).
Как правило, номера SKU виртуальных машин, имена которых включают букву "r", имеют необходимое оборудование InfiniBand, а те номера SKU, имена которых не включают эту букву, не имеют такого оборудования. ("r" — это ссылка на сокращение "RDMA", которое означает "удаленный доступ к памяти".) Например, номер SKU виртуальной машины Standard_NC24rs_v3
поддерживает InfiniBand, а номер SKU Standard_NC24s_v3
— нет. За исключением возможностей InfiniBand характеристики этих двух номеров SKU в целом одинаковы — 24 ядра, 448 ГБ ОЗУ, 4 GPU с одним и тем же SKU и т. д.
Дополнительные сведения об RDMA и о номерах SKU виртуальных машин, поддерживающих InfiniBand.
Предупреждение
Номер SKU более старого поколения виртуальных машин Standard_NC24r
поддерживает RDMA, но не включает оборудование SR-IOV, необходимое для InfiniBand.
При создании кластера AmlCompute
на основе одного из таких размеров с поддержкой RDMA и InfiniBand образ ОС будет содержать драйвер Mellanox OFED, необходимый для включения предварительно установленного и настроенного компонента InfiniBand.