Spec-Zone.ru › PyTorch 1

Пакет multiprocessing - torch.multiprocessing

torch.multiprocessing является обёрткой вокруг модуля multiprocessing. Он регистрирует пользовательские редукторы, которые используют общую память для предоставления общих представлений об одних и тех же данных в разных процессах. После перемещения тензора/хранилища в shared_memory (см. share_memory_()), его можно будет отправлять в другие процессы без создания копий.

API полностью совместим с исходным модулем — достаточно изменить import multiprocessing на import torch.multiprocessing для того, чтобы все тензоры, отправляемые через очереди или используемые через другие механизмы, перемещались в общую память.

Из-за сходства API мы не документируем большую часть содержимого этого пакета и рекомендуем обратиться к отличной документации исходного модуля.

Предупреждение

Если главный процесс завершается внезапно (например, из-за входящего сигнала), функция multiprocessing иногда не удаляет свои дочерние процессы. Это известный недостаток, поэтому, если вы обнаруживаете утечку ресурсов после прерывания интерпретатора, скорее всего, это произошло с вами.

Управление стратегиями

torch.multiprocessing.get_all_sharing_strategies() [source]

Возвращает набор стратегий совместного использования, поддерживаемых на текущей системе.

torch.multiprocessing.get_sharing_strategy() [source]

Возвращает текущую стратегию для совместного использования CPU-тензоров.

torch.multiprocessing.set_sharing_strategy(new_strategy) [source]

Устанавливает стратегию для совместного использования CPU-тензоров.

Параметры:

new_strategy (str) — Имя выбранной стратегии. Должно быть одним из значений, возвращённых get_all_sharing_strategies().

Совместное использование CUDA-тензоров

Совместное использование CUDA-тензоров между процессами поддерживается только в Python 3, используя методы запуска spawn или forkserver.

В отличие от CPU-тензоров, процесс-отправитель должен хранить исходный тензор до тех пор, пока процесс-получатель сохраняет копию тензора. Управление ссылочным подсчётом реализовано внутри, но пользователи должны следовать рекомендациям по наилучшим практикам.

Предупреждение

Если процесс-получатель аварийно завершается из-за фатального сигнала, общий тензор может оставаться в памяти до тех пор, пока процесс-отправитель работает.

  1. Освободите память как можно быстрее в процессе-получателе.
## Good
x = queue.get()
# do somethings with x
del x
## Bad
x = queue.get()
# do somethings with x
# do everything else (producer have to keep x in memory)

2. Поддерживайте работу процесса-отправителя до тех пор, пока все процессы-получатели не завершат работу. Это предотвратит ситуацию, когда процесс-отправитель освобождает память, которая всё ещё используется процессом-получателем.

## producer
# send tensors, do something
event.wait()
## consumer
# receive tensors and use them
event.set()
  1. Не передавайте полученные тензоры.
# not going to work
x = queue.get()
queue_2.put(x)
# you need to create a process-local copy
x = queue.get()
x_clone = x.clone()
queue_2.put(x_clone)
# putting and getting from the same queue in the same process will likely end up with segfault
queue.put(tensor)
x = queue.get()

Стратегии совместного использования

Этот раздел даёт краткий обзор того, как работают разные стратегии совместного использования. Обратите внимание, что это относится только к CPU-тензорам — CUDA-тензоры всегда используют API CUDA, так как это единственный способ их совместного использования.

Файловый дескриптор - file_descriptor

Примечание

Это стратегия по умолчанию (за исключением macOS и OS X, где она не поддерживается).

Эта стратегия использует файловые дескрипторы как дескрипторы общей памяти. Всякий раз, когда хранилище перемещается в общую память, файловый дескриптор, полученный из shm_open , кешируется с объектом, а при отправке в другие процессы файловый дескриптор передаётся (например, через сокеты UNIX). Получатель также кеширует файловый дескриптор и mmap его для получения общего представления данных хранилища.

Обратите внимание, что если будет много тензоров, эта стратегия большую часть времени будет держать открытым большое количество файловых дескрипторов. Если на вашей системе низкий лимит на открытые файловые дескрипторы, и вы не можете его увеличить, используйте стратегию file_system.

Файловая система - file_system

Эта стратегия использует имена файлов, предоставленные shm_open , для идентификации областей общей памяти. Это выгодно тем, что реализация не требует кеширования файловых дескрипторов, полученных из него, но при этом подвержено утечкам общей памяти. Файл нельзя удалить сразу после его создания, так как другие процессы должны получить к нему доступ для открытия своих представлений. Если процессы аварийно завершаются или убиваются и не вызывают деструкторы хранилища, файлы остаются в системе. Это очень серьезно, так как они продолжают использовать память до перезагрузки системы или их ручного освобождения.

Для решения проблемы утечки файлов общей памяти, torch.multiprocessing запускает демона под именем torch_shm_manager , который изолируется от текущей группы процессов и отслеживает все выделения общей памяти. После завершения всех процессов, подключённых к нему, он ждёт некоторое время, чтобы убедиться в отсутствии новых подключений, и перебирает все файлы общей памяти, выделенные группой. Если он обнаруживает, что какой-либо из них всё ещё существует, он освобождает их. Мы протестировали этот метод и он оказался устойчивым к различным сбоям. Однако, если у вашей системы достаточно высокие лимиты, и file_descriptor поддерживается, мы не рекомендуем переключаться на него.

Запуск дочерних процессов

Примечание

Доступно для Python >= 3.4.

Это зависит от метода запуска spawn в пакете Python multiprocessing.

Запуск нескольких дочерних процессов для выполнения некоторой функции может быть выполнен путём создания экземпляров Process и вызова join для ожидания их завершения. Этот подход хорошо работает при работе с одним дочерним процессом, но представляет потенциальные проблемы при работе с несколькими процессами.

Именно, последовательное присоединение процессов подразумевает их последовательное завершение. Если это не так, и первый процесс не завершается, завершение процесса останется незамеченным. Также нет встроенных средств для распространения ошибок.

Функция spawn ниже устраняет эти проблемы и обрабатывает распространение ошибок, завершение в произвольном порядке и активно завершает процессы при обнаружении ошибки в одном из них.

torch.multiprocessing.spawn(fn, args=(), nprocs=1, join=True, daemon=False, start_method='spawn') [source]

Запускает nprocs процессов, которые выполняют fn с args.

Если один из процессов завершается с ненулевым кодом возврата, оставшиеся процессы убиваются, и генерируется исключение с причиной завершения. В случае, если исключение было перехвачено в дочернем процессе, оно передаётся, а его трассировка включена в исключение, генерируемое в родительском процессе.

Параметры:
  • fn (функция) –

    Функция вызывается в качестве точки входа запущенного процесса. Эта функция должна быть определена на верхнем уровне модуля, чтобы её можно было сериализовать и запустить. Это требование, налагаемое многопроцессорностью.

    Функция вызывается как fn(i, *args), где i — индекс процесса, а args — переданная кортеж аргументов.

  • args (кортеж) – Аргументы, передаваемые в fn.
  • nprocs (целое число) – Количество процессов для запуска.
  • join (булево значение) – Выполнить блокирующее присоединение ко всем процессам.
  • daemon (булево значение) – Флаг демонического процесса запущенных процессов. Если установлено в True, будут созданы демонические процессы.
  • start_method (строка) – (устарело) этот метод всегда будет использовать spawn в качестве метода запуска. Чтобы использовать другой метод запуска, используйте start_processes().
Возвращает:

None, если join равен True, ProcessContext, если join равен False

class torch.multiprocessing.SpawnContext [source]

Возвращается spawn(), когда вызывается с join=False.

join(timeout=None)

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

Возвращает True если все процессы успешно присоединились, False если есть больше процессов, которые нужно присоединить.

Параметры:

timeout (число с плавающей запятой) – Подождать столько времени, прежде чем сдаться.

© 2024, PyTorch Contributors
PyTorch has a BSD-style license, as found in the LICENSE file.
https://pytorch.org/docs/1.13/multiprocessing.html

Spec-Zone.ru

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