# 多进程包 - torch.multiprocessing > 译者:[hijkzzz](https://github.com/hijkzzz) torch.multiprocessing 是一个本地 [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing "(in Python v3.7)") 模块的包装. 它注册了自定义的reducers, 并使用共享内存为不同的进程在同一份数据上提供共享的视图. 一旦 tensor/storage 被移动到共享内存 (见 [`share_memory_()`](tensors.html#torch.Tensor.share_memory_ "torch.Tensor.share_memory_")), 将其发送到任何进程不会造成拷贝开销. 此 API 100% 兼容原生模块 - 所以足以将 `import multiprocessing` 改成 `import torch.multiprocessing` 使得所有的 tensors 通过队列发送或者使用其它共享机制, 移动到共享内存. 因为 APIs 的相似性, 我们没有为此包提供足够的文档, 所以推荐参考非常优秀的原生进程模块文档. 警告 如果主进程意外退出 (比如 因为一个信号的到来), Python’s `multiprocessing` 有时候会无法请理它的子进程. 这是一个众所周知的警告, 因此,如果你在中断解释器后发现任何资源泄漏,这可能意味着你刚刚发生了这种情况. ## 策略管理 ```py torch.multiprocessing.get_all_sharing_strategies() ``` 返回当前系统支持的共享策略的集合. ```py torch.multiprocessing.get_sharing_strategy() ``` 返回当前的 CPU tensors 共享策略. ```py torch.multiprocessing.set_sharing_strategy(new_strategy) ``` 设置一个新的 CPU tensors 共享策略. | 参数: | **new_strategy** ([_str_](https://docs.python.org/3/library/stdtypes.html#str "(in Python v3.7)")) – 选定策略的名字. 必须是 [`get_all_sharing_strategies()`](#torch.multiprocessing.get_all_sharing_strategies "torch.multiprocessing.get_all_sharing_strategies") 的返回值中的一个. | | --- | --- | ## 共享 CUDA tensors 在进程间共享 CUDA tensors 仅仅在 Python 3 中被支持, 使用 `spawn` 或者 `forkserver` 启动方法. [`multiprocessing`](https://docs.python.org/3/library/multiprocessing.html#module-multiprocessing "(in Python v3.7)") 在 Python 2 中只能使用 `fork` 创建新进程, 然而 CUDA 运行时不支持它. 警告 CUDA API要求导出到其他进程的分配只要被其他进程使用就保持有效. 您应该小心,并确保共享的CUDA tensor在必要时不会超出范围. 共享模型参数不应该是一个问题,但是传递其他类型的数据应该小心。注意,此限制不适用于共享CPU内存. ## 共享策略 本节简要概述不同的共享策略是如何工作的。注意,它只适用于CPU tensor——CUDA tensor总是使用CUDA API,因为这是它们可以共享的唯一方式。 ### 文件描述符 - `file_descriptor` 注意 这是默认策略(macOS和OS X因为不支持除外) 该策略将使用文件描述符作为共享内存句柄。每当一个存储被移动到共享内存时,从`shm open`获得的文件描述符就会被对象缓存,当它被发送到其他进程时,文件描述符就会被传输(例如通过UNIX套接字)到它。接收者还将缓存文件描述符并`mmap`它,以获得存储数据上的共享视图。 请注意,如果共享了很多tensor,那么这种策略将在大多数情况下打开大量的文件描述符。如果您的系统对打开的文件描述符的数量限制很低,并且您不能提高它们的数量,那么您应该使用`file_system`策略。 ### 文件系统 - `file_system` 该策略将使用指定给`shm open`的文件名来标识共享内存区域。这样做的好处是不需要实现缓存从中获得的文件描述符,但同时容易导致共享内存泄漏。文件不能在创建之后立即删除,因为其他进程需要访问它来打开它们的视图。如果进程致命地崩溃或被杀死,并且不调用存储析构函数,那么文件将保留在系统中。这是非常严重的,因为它们会一直使用内存,直到系统重新启动,或者重新手动释放。 为了解决共享内存文件泄漏的问题,`torch.multiprocessing`将生成一个名为`torch_shm_manager`的守护进程,它将自己与当前进程组隔离,并跟踪所有共享内存分配。连接到它的所有进程退出后,它将等待一段时间以确保没有新的连接,并将遍历组分配的所有共享内存文件。如果它发现其中任何一个仍然存在,就会解除它们的分配。我们对这种方法进行了测试,证明它对各种故障都具有鲁棒性。 不过,如果您的系统有足够高的限制,并且`file_descriptor`是受支持的策略,我们不建议切换到这个策略。 ## Spawning 子线程 注意 仅支持 Python >= 3.4. 依赖于 `spawn` 启动方法(在 Python 的 `multiprocessing` 包中)。 通过创建`进程`实例并调用join来等待它们完成,可以生成大量子进程来执行某些功能。这种方法在处理单个子进程时工作得很好,但在处理多个进程时可能会出现问题。 也就是说,顺序连接进程意味着它们将顺序终止。如果没有,并且第一个进程没有终止,那么进程终止将不被注意。 此外,没有用于错误传播的本地工具. 下面的`spawn`函数解决了这些问题,并负责错误传播、无序终止,并在检测到其中一个错误时主动终止进程. ```py torch.multiprocessing.spawn(fn, args=(), nprocs=1, join=True, daemon=False) ``` Spawns `nprocs` 进程运行 `fn` 使用参数 `args`. 如果其中一个进程以非零退出状态退出,则会杀死其余进程,并引发异常,导致终止。在子进程中捕获异常的情况下,将转发该异常,并将其跟踪包含在父进程中引发的异常中。 参数: * **fn** (_function_) – 函数被称为派生进程的入口点。必须在模块的顶层定义此函数,以便对其进行pickle和派生。这是多进程强加的要求。 该函数称为`fn(i, *args)`,其中`i`是进程索引,`args`是传递的参数元组。 * **args** ([_tuple_](https://docs.python.org/3/library/stdtypes.html#tuple "(in Python v3.7)")) – 传递给 `fn` 的参数. * **nprocs** ([_int_](https://docs.python.org/3/library/functions.html#int "(in Python v3.7)")) – 派生的进程数. * **join** ([_bool_](https://docs.python.org/3/library/functions.html#bool "(in Python v3.7)")) – 执行一个阻塞的join对于所有进程. * **daemon** ([_bool_](https://docs.python.org/3/library/functions.html#bool "(in Python v3.7)")) – 派生进程守护进程标志。如果设置为True,将创建守护进程. | 返回值: | None 如果 `join` 是 `True`, [`SpawnContext`](#torch.multiprocessing.SpawnContext "torch.multiprocessing.SpawnContext") 如果 `join` 是 `False` | | --- | --- | ```py class torch.multiprocessing.SpawnContext ``` 由 [`spawn()`](#torch.multiprocessing.spawn "torch.multiprocessing.spawn") 返回, 当 `join=False`. ```py join(timeout=None) ``` 尝试连接此派生上下文中的一个或多个进程。如果其中一个进程以非零退出状态退出,则此函数将杀死其余进程,并引发异常,导致第一个进程退出。 返回 `True`如果所有进程正常退出, `False` 如果有更多的进程需要 join. | Parameters: | **timeout** ([_float_](https://docs.python.org/3/library/functions.html#float "(in Python v3.7)")) – 放弃等待的最长时间. | | --- | --- |