Интеграция распределённого обучения
Создано: 18 мая 2026 г. | Последнее обновление: 18 мая 2026 г.
Общие сведения
Распределённое обучение позволяет ускорителям масштабировать вычислительные нагрузки на несколько устройств и узлов, координируя коллективный обмен данными (например, allreduce, broadcast, allgather) через бэкенд ProcessGroup. PyTorch поставляется со встроенными бэкендами, такими как NCCL для CUDA и Gloo для CPU, однако фреймворк предоставляет механизм регистрации, позволяющий сторонним поставщикам ускорителей подключать собственную библиотеку коллективного обмена данными без изменения основного кода.
Интеграцию можно разделить на три уровня:
-
Реализация бэкенда на C++ – подкласс
c10d::Backend, реализующий операции коллективного обмена данными, обмена точка-точка и синхронизации. - Привязки Python – предоставляют класс бэкенда C++ в Python с помощью pybind11.
-
Регистрация бэкенда – регистрирует бэкенд в
torch.distributed.Backend.register_backend(), чтобыinit_process_groupмог обнаружить и создать его экземпляр.
Примечание
OpenReg (torch_openreg) — официальная эталонная реализация PyTorch для интеграции сторонних ускорителей. Она включает минимальный распределённый бэкенд под названием OCCL (OpenReg Collective Communications Library), демонстрирующий полную интеграцию ProcessGroup. Во всех примерах кода этой главы используется реализация OCCL.
Перед началом работы
Это руководство посвящено только интеграции бэкенда ProcessGroup — регистрации пользовательского бэкенда коллективного обмена данными в torch.distributed. В нём не рассматривается интеграция полного стека с высокоуровневыми API, такими как DDP, FSDP или другие стратегии распределённого обучения.
Перед тем как следовать этому руководству, убедитесь, что у вас есть:
-
Импортируемый пакет расширения
torch_xxx, регистрирующий ваше устройство с помощьюPrivateUse1. Сведения о регистрации устройств, операторах и хуках среды выполнения приведены в предыдущих главах этого руководства. -
Библиотека коллективного обмена данными (CCL) с реализациями базовых коллективных операций, таких как
allreduceиbroadcast, для вашего устройства. Библиотека CCL может предоставляться поставщиком (например, NCCL для NVIDIA, HCCL для Huawei) или быть пользовательской реализацией.
Проектирование
В этом разделе описаны интерфейсы и понятия, связанные с регистрацией бэкенда.
API регистрации
Основная точка входа для регистрации бэкенда OOT — Backend.register_backend():
Параметр | Тип | Описание |
|---|---|---|
|
| Имя бэкенда, например |
|
| Фабричная функция, создающая экземпляр бэкенда (см. сигнатуру ниже). |
|
| Если |
|
| Типы устройств, поддерживаемые этим бэкендом, например |
Если указано devices, бэкенд автоматически связывается с соответствующими типами устройств. Это позволяет init_process_group() выбрать подходящий бэкенд, когда пользователь передаёт аргумент device_id, не указывая имя бэкенда явно.
Сигнатура фабричной функции
В зависимости от extended_api фабричная функция получает разные аргументы:
Режим | Сигнатура |
|---|---|
Стандартный (по умолчанию) |
|
Расширенный API |
|
Стандартного режима достаточно для большинства бэкендов. Расширенный API предоставляет дополнительный контекст, например group_id и global_ranks_in_group.
Операции бэкенда
Базовый класс c10d::Backend определяет виртуальные методы для операций коллективного обмена данными, обмена точка-точка и синхронизации. Каждая операция возвращает объект c10::intrusive_ptr<Work>, представляющий асинхронную операцию. Для бэкендов с синхронными операциями объект Work можно сразу пометить как завершённый.
Минимальный набор обязательных операций
Чтобы создать работающий бэкенд с поддержкой базового распределённого обучения, реализуйте как минимум следующие операции:
Категория | Операции |
|---|---|
Коллективные |
|
Синхронизация |
|
Эти операции охватывают основные шаблоны обмена данными, используемые DDP и другими распространёнными распределёнными рабочими процессами.
Расширенный набор операций
Для более широкой совместимости с продвинутыми распределёнными стратегиями (например, FSDP, параллелизмом модели и конвейерным параллелизмом) реализуйте полный набор операций:
Категория | Операции |
|---|---|
Коллективные |
|
Точка-точка |
|
Backend.hpp.
Дополнительные возможности
Бэкенды могут объявлять о поддержке дополнительных возможностей, переопределяя следующие методы:
Метод | По умолчанию | Описание |
|---|---|---|
|
| Поддержка разделения группы процессов |
|
| Объединённые коллективные операции |
Реализация
В этом разделе описаны практические шаги по реализации и регистрации бэкенда на примере эталонной реализации OCCL. Реализация состоит из трёх шагов:
- Реализовать бэкенд на C++
- Создать привязки Python
- Зарегистрировать бэкенд в Python
Шаг 1: Реализация бэкенда на C++
Создайте класс, наследующий c10d::Backend, и реализуйте обязательные коллективные операции. В бэкенде также необходимо определить:
- Подкласс
Work, отслеживающий состояние асинхронной операции - Подкласс
Options(наследующийBackend::Options) для конфигурации, специфичной для бэкенда
Объект Work
Подкласс Work управляет жизненным циклом асинхронной коллективной операции. В минимальной (синхронной) реализации операцию можно завершить сразу в конструкторе объекта Work:
1 class DummyWork : public Work {
2 public:
3 DummyWork();
4
5 virtual ~DummyWork();
6 bool isCompleted() override;
7 bool isSuccess() const override;
8 bool wait(std::chrono::milliseconds timeout) override;
9 void synchronize() override;
10 void abort() override;
11 c10::intrusive_ptr<c10::ivalue::Future> getFuture() override;
12
13 protected:
14 friend class ProcessGroupOCCL;
15
16 private:
17 c10::intrusive_ptr<c10::ivalue::Future> future_;
18 };
В производственных бэкендах Work обычно оборачивает асинхронный дескриптор из библиотеки обмена данными поставщика (например, событие потока или дескриптор запроса), а wait() блокирует выполнение до завершения операции на устройстве.
Класс бэкенда
Класс бэкенда наследует c10d::Backend и переопределяет коллективные операции. Каждый метод должен проверять, что входные тензоры находятся на ожидаемом типе устройства (например, PrivateUse1), а затем передавать выполнение библиотеке обмена данными поставщика. Основные особенности реализации:
-
getBackendName()должен возвращать ту же строку, которая используется при регистрации в Python (например,"occl"). -
Проверка входных данных – каждая коллективная операция должна проверять типы устройств тензоров. В эталонной реализации OCCL для этого используются макросы
CHECK_TENSORиCHECK_TENSOR_LIST. -
Возвращаемое значение – все коллективные операции возвращают
c10::intrusive_ptr<Work>.
Полную эталонную реализацию см. в файлах ProcessGroupOCCL.hpp и ProcessGroupOCCL.cpp.
Шаг 2: Привязки Python
Предоставьте класс бэкенда в Python с помощью pybind11. В эталонной реализации OCCL привязки размещены в отдельном файле init.cpp, отдельно от основного модуля расширения; из точки входа модуля вызывается initProcessGroupBindings():
1void initProcessGroupBindings(py::module& m) {
2 py::class_<c10d::ProcessGroupOCCL, c10d::Backend, c10::intrusive_ptr<c10d::ProcessGroupOCCL>>(m, "ProcessGroupOCCL")
3 .def(
4 py::init([](const c10::intrusive_ptr<::c10d::Store>& /*store*/,
5 int rank,
6 int size,
7 std::chrono::milliseconds /*timeout*/) {
8 return c10::make_intrusive<::c10d::ProcessGroupOCCL>(rank, size);
9 }),
10 py::arg("store"),
11 py::arg("rank"),
12 py::arg("size"),
13 py::arg("timeout") = std::chrono::milliseconds(30 * 60 * 1000));
14}
Важные замечания:
- В шаблоне
py::class_необходимо указатьc10d::Backendв качестве базового класса и использоватьc10::intrusive_ptrв качестве держателя, чтобы PyTorch распознал бэкенд во внутреннем реестре. - Конструктор предоставляется напрямую через
py::initс лямбда-функцией, которая вызывает конструктор C++. Это избавляет от необходимости создавать отдельную фабричную функцию. - Оберните привязки в
#if USE_DISTRIBUTED, чтобы обработать сборки, в которых поддержка распределённых вычислений отключена.
Шаг 3: Регистрация бэкенда в Python
Зарегистрируйте бэкенд в файле __init__.py пакета расширения с помощью torch.distributed:
1if torch.distributed.is_available():
2 try:
3 from torch_openreg._C import ProcessGroupOCCL
4
5 def _create_occl_backend(store, rank, size, timeout):
6 return ProcessGroupOCCL(store, rank, size, timeout)
7
8 torch.distributed.Backend.register_backend(
9 "occl", _create_occl_backend, devices=["openreg"]
10 )
11 except Exception as e:
12 raise RuntimeError("Failed to register 'occl' process group backend.") from e
В Python импортируется предоставленный через pybind11 класс ProcessGroupOCCL, который оборачивается в простую фабричную функцию с сигнатурой, ожидаемой register_backend(). Вызов Backend.register_backend() выполняет следующие действия:
- Добавляет
"occl"вBackend.backend_list, регистрируя это имя бэкенда. - Сопоставляет тип устройства
"openreg"с бэкендом"occl"вBackend.default_device_backend_map. - Сохраняет фабричную функцию, чтобы
init_process_group()мог вызвать её, когда указанbackend="occl".
Использование
После регистрации бэкенд без проблем интегрируется с torch.distributed:
import torch
import torch.distributed as dist
# Import triggers autoload, which registers the "occl" backend
import torch_openreg
# Initialize process group – OCCL is auto-selected for openreg devices
dist.init_process_group(
backend="occl",
init_method="env://",
world_size=2,
rank=0,
)
# Use standard distributed APIs
tensor = torch.randn(4, device="openreg")
dist.all_reduce(tensor)
dist.destroy_process_group()
Кроме того, имя бэкенда можно не указывать, если задан device_id: PyTorch выберет бэкенд по сопоставлению устройств и бэкендов:
dist.init_process_group(
device_id=torch.device("openreg:0"),
init_method="env://",
world_size=2,
rank=0,
)
Строки бэкенда для нескольких устройств
PyTorch позволяет указать разные бэкенды для разных типов устройств в одной группе процессов, используя формат "device:backend":
dist.init_process_group(
backend="cpu:gloo,openreg:occl",
init_method="env://",
world_size=2,
rank=0,
)
Тестирование
Основные моменты тестирования:
- Убедитесь, что после импорта бэкенд появляется в
dist.Backend.backend_list. - Проверьте, что
init_process_group/destroy_process_groupвыполняется успешно. - Убедитесь, что коллективные операции принимают тензоры на зарегистрированном устройстве и возвращают завершённые объекты
Work. - Для выполнения тестов в нескольких процессах используйте
MultiProcessTestCaseизtorch.testing._internal.common_distributed.
Пример эталонной реализации см. в наборе тестов OCCL.
© 2026, PyTorch Contributors
PyTorch has a BSD-style license, as found in the LICENSE file.
https://docs.pytorch.org/docs/2.14/accelerator/distributed.html