Spec-Zone.ru › PyTorch 2.14

Управление устройствами

Создано: 14 нояб. 2025 | Последнее обновление: 9 дек. 2025

Общие сведения

Управление устройствами включает основные операции, такие как получение сведений о количестве доступных устройств и переключение между ними. Бэкенды ускорителей оборачивают API среды выполнения устройств и предоставляют их PyTorch.

Проектирование

Поставщикам ускорителей следует реализовать следующие основные функции:

Имя функции

Описание

Сценарии использования

device_count()

Получение общего количества доступных устройств в системе

- Инициализация приложения
- Распределение нагрузки между несколькими устройствами
- Проверка индексов устройств перед использованием

current_device()

Получение активного устройства для вызывающего потока

- Отладка и ведение журналов
- Определение размещения тензоров
- Реализации защитных объектов

set_device()

Изменение активного устройства для последующих операций

- Переключение контекста между устройствами
- Инициализация ресурсов конкретного устройства
- Циклы обучения на нескольких GPU

exchange_device()

Атомарная замена устройства с возвратом предыдущего устройства

- Реализация защитных объектов устройств
- Временное переключение контекста устройства
- Управление устройствами на основе RAII

maybe_exchange_device()

Условная замена устройства, только если индекс допустим (разрешено значение −1)

- Безопасное переключение устройств с необязательными индексами
- Реализации защитных объектов с допускающими null значениями устройств

Эти функции являются строительными блоками для потоков, событий и управления памятью. Проверяйте входные данные и корректно обрабатывайте ошибки.

Реализация

В этом разделе на примере set_device показано управление устройствами. Для реализации необходимы:

  1. Обёртки C++ для среды выполнения устройства
  2. Привязки Python для предоставления функций C++
  3. Удобные для пользователя API Python

В качестве примера рассмотрим OpenReg (Open Registration) — пример интеграции с PyTorch, который устраняет пробел в интеграции внешних бэкендов ускорителей. Его реализация (OpenRegFunctions.h/cpp) показывает, как аккуратно обернуть стороннюю среду выполнения. Эти функции повторно используются во всём бэкенде — для потоков, событий, генераторов и привязок Python.

Часть на C++

Оберните API среды выполнения устройства и добавьте обработку ошибок. Функция SetDevice демонстрирует этот подход:

1orError_t SetDevice(DeviceIndex device) {
2  int cur_device = -1;
3  OPENREG_CHECK(orGetDevice(&cur_device));
4  if (device == cur_device) {
5    return orSuccess;
6  }
7  return orSetDevice(device);
8}
1OPENREG_EXPORT void set_device(DeviceIndex device) {
2  check_device_index(device);
3  OPENREG_CHECK(SetDevice(device));
4}

Привязки

Предоставьте функции C++ в Python с помощью pybind11:

 1PyObject* _setDevice(PyObject* self, PyObject* arg) {
 2  HANDLE_TH_ERRORS
 3  TORCH_CHECK(THPUtils_checkLong(arg), "invalid argument to setDevice");
 4  auto device = THPUtils_unpackDeviceIndex(arg);
 5  torch::utils::device_lazy_init(at::kPrivateUse1);
 6  c10::openreg::set_device(device);
 7
 8  Py_RETURN_NONE;
 9  END_HANDLE_TH_ERRORS
10}
1static PyMethodDef methods[] = {
2    {"_init", _initExtension, METH_NOARGS, nullptr},
3    {"_isInBadFork", _isInBadFork, METH_NOARGS, nullptr},
4    {"_get_default_generator", _getDefaultGenerator, METH_O, nullptr},
5    {"_get_device", _getDevice, METH_NOARGS, nullptr},
6    {"_set_device", _setDevice, METH_O, nullptr},
7    {"_exchangeDevice", _exchangeDevice, METH_O, nullptr},
8    {"_get_device_count", _getDeviceCount, METH_NOARGS, nullptr},
9    {nullptr, nullptr, 0, nullptr}};

Часть на Python

Оберните привязки C++ удобными для пользователя функциями Python:

1def set_device(device) -> None:
2    if device >= 0:
3        torch_openreg._C._set_device(device)
4
5

Ниже приведено полное соответствие функций C++ и Python:

Функция привязки C++

API привязки C++ (pybind11)

Пользовательский API Python

Описание

_getDeviceCount

torch_openreg._C._get_device_count()

torch.openreg.device_count()

Возвращает общее количество устройств

_getDevice

torch_openreg._C._get_device()

torch.openreg.current_device()

Возвращает индекс текущего активного устройства

_setDevice

torch_openreg._C._set_device(idx)

torch.openreg.set_device(idx)

Задаёт активное устройство

_exchangeDevice

torch_openreg._C._exchange_device(idx)

Не применимо (только для внутреннего использования)

Атомарно заменяет устройство и возвращает предыдущее

Защитный объект устройства

Защитные объекты устройств автоматически переключают устройства с безопасной обработкой исключений. Они похожи на блокировки C++: переключают устройства при создании и восстанавливают исходное состояние при уничтожении.

Реализуйте DeviceGuardImplInterface для интеграции с системой защитных объектов PyTorch:

 1  /**
 2   * Return the type of device managed by this guard implementation.
 3   */
 4  DeviceType type() const override {
 5    return static_type;
 6  }
 7  /**
 8   * Set the current device to device d, and return the previous Device.
 9   */
10  // LITERALINCLUDE START: OPENREG GUARD DEVICE MANAGEMENT
11  Device exchangeDevice(Device d) const override {
12    TORCH_CHECK(d.is_privateuseone(), "Expected a PrivateUse1 device, but got ", d);
13
14    auto old_device_index = ExchangeDevice(d.index());
15    return Device(static_type, old_device_index);
16  }
17  // LITERALINCLUDE END: OPENREG GUARD DEVICE MANAGEMENT
18
19  /**
20   * Get the current device.
21   */
22  Device getDevice() const override {
23    int device_index = current_device();
24    return c10::Device(static_type, device_index);
25  }
26
27  /**
28   * Get the device capability for a given device.
29   * By default, OpenReg has 2 same devices with the same capability.
30   */
31  DeviceCapability getDeviceCapability(Device /*unused*/) const override {
32    return DeviceCapability();
33  }
34
35  /**
36   * Set the current device to c10::Device.
37   */
38  void setDevice(Device d) const override {
39    TORCH_CHECK(d.is_privateuseone(), "Expected a PrivateUse1 device, but got ", d);
40
41    set_device(d.index());
42  }
43
44  /**
45   * Set the current device to device d, without checking for errors
46   * (so, e.g., this can be called from a destructor).
47   */
48  void uncheckedSetDevice(Device d) const noexcept override {
49    set_device(d.index());
50  }
51
52  /**
53   * Get the number of devices.
54   *
55   * WARNING: This is REQUIRED to not raise an exception.
56   * If there is some sort of problem, e.g., driver error,
57   * you should report that there are zero available devices.
58   */
59  DeviceIndex deviceCount() const noexcept override {
60    return device_count();
61  }
62
63  /**
64   * Wait (by blocking the calling thread) until all the work has
65   * completed running on the device.
66   */
67  void synchronizeDevice(const DeviceIndex device_index) const override {
68    OPENREG_CHECK(orDeviceSynchronize());
69  }

Это позволит использовать защитный объект в PyTorch для типа устройства PrivateUse1; после этого пользователи смогут применять стандартные защитные объекты устройств PyTorch с пользовательским бэкендом.

© 2026, PyTorch Contributors
PyTorch has a BSD-style license, as found in the LICENSE file.
https://docs.pytorch.org/docs/2.14/accelerator/device.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API