torch.distributed
支持三個(gè)后端,每個(gè)后端具有不同的功能。 下表顯示了可用于 CPU / CUDA 張量的功能。 MPI 僅在用于構(gòu)建 PyTorch 的實(shí)現(xiàn)支持 CUDA 的情況下才支持 CUDA。
|
后端
|
gloo
|
mpi
|
nccl
| | --- | --- | --- | --- | |
設(shè)備
|
中央處理器
|
顯卡
|
CPU
|
GPU
|
CPU
|
GPU
| | --- | --- | --- | --- | --- | --- | --- | | 發(fā)送 | ? | ? | ? | ? | ? | ? | | 收錄 | ? | ? | ? | ? | ? | ? | | 廣播 | ? | ? | ? | ? | ? | ? | | all_reduce | ? | ? | ? | ? | ? | ? | | 降低 | ? | ? | ? | ? | ? | ? | | all_gather | ? | ? | ? | ? | ? | ? | | 收集 | ? | ? | ? | ? | ? | ? | | 分散 | ? | ? | ? | ? | ? | ? | | 屏障 | ? | ? | ? | ? | ? | ? |
當(dāng)前分發(fā)的 PyTorch 僅支持 Linux。 默認(rèn)情況下,會(huì)構(gòu)建 Gloo 和 NCCL 后端并將其包含在 PyTorch 分布式中(僅在使用 CUDA 進(jìn)行構(gòu)建時(shí)才為 NCCL)。 MPI 是可選的后端,僅當(dāng)您從源代碼構(gòu)建 PyTorch 時(shí),才可以包含它。 (例如,在安裝了 MPI 的主機(jī)上構(gòu)建 PyTorch。)
在過去,我們經(jīng)常被問到:“我應(yīng)該使用哪個(gè)后端?”。
默認(rèn)情況下,NCCL 和 Gloo 后端都將嘗試找到要使用的正確網(wǎng)絡(luò)接口。 如果自動(dòng)檢測(cè)到的接口不正確,則可以使用以下環(huán)境變量(適用于各自的后端)覆蓋它:
export NCCL_SOCKET_IFNAME=eth0
export GLOO_SOCKET_IFNAME=eth0
如果您使用的是 Gloo 后端,則可以用逗號(hào)分隔多個(gè)接口,例如:export GLOO_SOCKET_IFNAME=eth0,eth1,eth2,eth3
。 后端將以循環(huán)方式在這些接口之間調(diào)度操作。 至關(guān)重要的是,所有進(jìn)程都必須在此變量中指定相同數(shù)量的接口。
NCCL 還提供了許多環(huán)境變量以進(jìn)行微調(diào)。
常用的調(diào)試工具包括以下內(nèi)容:
export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=ALL
<cite>torch分布式</cite>程序包提供 PyTorch 支持和通信原語,以實(shí)現(xiàn)在一臺(tái)或多臺(tái)機(jī)器上運(yùn)行的多個(gè)計(jì)算節(jié)點(diǎn)之間的多進(jìn)程并行性。 類 torch.nn.parallel.DistributedDataParallel()
建立在此功能之上,以提供同步的分布式訓(xùn)練,作為圍繞任何 PyTorch 模型的包裝。 這與 Multiprocessing 程序包提供的并行性不同– Torch.multiprocessing 和 torch.nn.DataParallel()
支持多個(gè)聯(lián)網(wǎng)的機(jī)器,并且用戶必須明確啟動(dòng)一個(gè)單獨(dú)的 每個(gè)過程的主要訓(xùn)練腳本的副本。
在單機(jī)同步情況下,<cite>torch分布式</cite>或 torch.nn.parallel.Dist ributedDataParallel()
包裝器可能仍比其他數(shù)據(jù)并行方法(包括 torch.nn.DataParallel()
)具有優(yōu)勢(shì) ]:
在調(diào)用任何其他方法之前,需要使用 torch.distributed.init_process_group()
函數(shù)初始化該程序包。 這將阻塞,直到所有進(jìn)程都已加入。
torch.distributed.init_process_group(backend, init_method=None, timeout=datetime.timedelta(0, 1800), world_size=-1, rank=-1, store=None, group_name='')?
初始化默認(rèn)的分布式進(jìn)程組,這還將初始化分布式程序包。
There are 2 main ways to initialize a process group:
store
,rank
和world_size
。init_method
(URL 字符串),它指示在何處/如何發(fā)現(xiàn)對(duì)等方。 (可選)指定rank
和world_size
,或在 URL 中編碼所有必需的參數(shù)并忽略它們。
如果兩者均未指定,則將init_method
假定為“ env://”。
參數(shù)
mpi
,gloo
和nccl
。 該字段應(yīng)以小寫字符串(例如"gloo"
)形式給出,也可以通過 Backe nd
屬性(例如Backend.GLOO
)進(jìn)行訪問。 如果每臺(tái)具有nccl
后端的計(jì)算機(jī)使用多個(gè)進(jìn)程,則每個(gè)進(jìn)程必須對(duì)其使用的每個(gè) GPU 都具有獨(dú)占訪問權(quán)限,因?yàn)樵谶M(jìn)程之間共享 GPU 可能會(huì)導(dǎo)致死鎖。init_method
或store
,則默認(rèn)值為“ env://”。 與store
互斥。store
,則為必需。store
,則為必需。init_method
互斥。gloo
后端。 對(duì)于nccl
,僅在環(huán)境變量NCCL_BLOCKING_WAIT
設(shè)置為 1 時(shí)適用。
要啟用backend == Backend.MPI
,PyTorch 需要從支持 MPI 的系統(tǒng)上的源代碼構(gòu)建。 NCCL 同樣適用。
class torch.distributed.Backend?
類似于枚舉的可用后端類:GLOO,NCCL 和 MPI。
此類的值是小寫字符串,例如"gloo"
。 可以將它們作為屬性來訪問,例如Backend.NCCL
。
可以直接調(diào)用此類來解析字符串,例如Backend(backend_str)
將檢查backend_str
是否有效,如果有效,則返回已解析的小寫字符串。 它還接受大寫字符串,例如Backend("GLOO")
返回"gloo"
。
注意
條目Backend.UNDEFINED
存在,但僅用作某些字段的初始值。 用戶既不應(yīng)直接使用它,也不應(yīng)該假定它的存在。
torch.distributed.get_backend(group=<object object>)?
返回給定進(jìn)程組的后端。
Parameters
組 (ProcessGroup , 可選)–要處理的過程組。 默認(rèn)值為常規(guī)主流程組。 如果指定了另一個(gè)特定組,則調(diào)用過程必須是group
的一部分。
退貨
給定進(jìn)程組的后端,為小寫字符串。
torch.distributed.get_rank(group=<object object>)?
返回當(dāng)前進(jìn)程組的等級(jí)
等級(jí)是分配給分布式過程組中每個(gè)過程的唯一標(biāo)識(shí)符。 它們始終是從 0 到world_size
的連續(xù)整數(shù)。
Parameters
組 (ProcessGroup , 可選)–要處理的進(jìn)程組
Returns
進(jìn)程組-1(如果不屬于組)的等級(jí)
torch.distributed.get_world_size(group=<object object>)?
返回當(dāng)前進(jìn)程組中的進(jìn)程數(shù)
Parameters
group (ProcessGroup__, optional) – The process group to work on
Returns
進(jìn)程組-1 的世界大小,如果不是該組的一部分
torch.distributed.is_initialized()?
檢查默認(rèn)進(jìn)程組是否已初始化
torch.distributed.is_mpi_available()?
檢查 MPI 后端是否可用。
torch.distributed.is_nccl_available()?
檢查 NCCL 后端是否可用。
當(dāng)前支持三種初始化方法:
有兩種使用 TCP 進(jìn)行初始化的方式,兩種方式都需要所有進(jìn)程都可以訪問的網(wǎng)絡(luò)地址以及所需的world_size
。 第一種方法要求指定一個(gè)地址,該地址屬于等級(jí) 0 進(jìn)程。 此初始化方法要求所有進(jìn)程都具有手動(dòng)指定的等級(jí)。
請(qǐng)注意,最新的分布式程序包中不再支持多播地址。 group_name
也已棄用。
import torch.distributed as dist
## Use address of one of the machines
dist.init_process_group(backend, init_method='tcp://10.1.1.20:23456',
rank=args.rank, world_size=4)
另一種初始化方法利用了文件系統(tǒng)以及所需的world_size
,該文件系統(tǒng)可從組中的所有計(jì)算機(jī)共享并可見。 該 URL 應(yīng)該以file://
開頭,并包含一個(gè)指向共享文件系統(tǒng)上不存在的文件(在現(xiàn)有目錄中)的路徑。 如果文件系統(tǒng)初始化不存在,則會(huì)自動(dòng)創(chuàng)建該文件,但不會(huì)刪除該文件。 因此,您有責(zé)任確保在相同文件路徑/名稱的下一個(gè) init_process_group()
調(diào)用之前清除文件。
請(qǐng)注意,最新的分布式軟件包不再支持自動(dòng)等級(jí)分配,并且group_name
也已棄用。
警告
此方法假定文件系統(tǒng)支持使用fcntl
進(jìn)行鎖定-大多數(shù)本地系統(tǒng)和 NFS 都支持它。
Warning
此方法將始終創(chuàng)建文件,并盡力在程序末尾清理并刪除文件。 換句話說,使用文件 init 方法進(jìn)行的每次初始化都需要一個(gè)全新的空文件,以使初始化成功。 如果再次使用先前初始化使用的同一文件(碰巧不會(huì)被清除),則這是意外行為,通常會(huì)導(dǎo)致死鎖和失敗。 因此,即使此方法將盡最大努力清除文件,但如果自動(dòng)刪除碰巧失敗,您有責(zé)任確保在訓(xùn)練結(jié)束時(shí)將文件刪除,以防止同一文件被刪除。 在下一次再次使用。 如果您計(jì)劃在同一文件名上多次調(diào)用 init_process_group()
,這尤其重要。 換句話說,如果未刪除/清除文件,然后對(duì)該文件再次調(diào)用 init_process_group()
,則可能會(huì)失敗。 經(jīng)驗(yàn)法則是,每次調(diào)用 init_process_group()
時(shí),請(qǐng)確保文件不存在或?yàn)榭铡?/p>
import torch.distributed as dist
## rank should always be specified
dist.init_process_group(backend, init_method='file:///mnt/nfs/sharedfile',
world_size=4, rank=args.rank)
該方法將從環(huán)境變量中讀取配置,從而可以完全自定義如何獲取信息。 要設(shè)置的變量是:
MASTER_PORT
-必填; 必須是等級(jí)為 0 的計(jì)算機(jī)上的空閑端口MASTER_ADDR
-必填(0 級(jí)除外); 等級(jí) 0 節(jié)點(diǎn)的地址WORLD_SIZE
-必填; 可以在此處或在調(diào)用 init 函數(shù)時(shí)進(jìn)行設(shè)置RANK
-必填; 可以在此處或在調(diào)用 init 函數(shù)時(shí)進(jìn)行設(shè)置等級(jí)為 0 的計(jì)算機(jī)將用于建立所有連接。
這是默認(rèn)方法,這意味著不必指定init_method
(也可以是env://
)。
默認(rèn)情況下,集合體在默認(rèn)組(也稱為世界)上運(yùn)行,并要求所有進(jìn)程進(jìn)入分布式函數(shù)調(diào)用。 但是,某些工作負(fù)載可以從更細(xì)粒度的通信中受益。 這是分布式組起作用的地方。 new_group()
功能可用于創(chuàng)建帶有所有進(jìn)程的任意子集的新組。 它返回一個(gè)不透明的組句柄,該句柄可以作為group
參數(shù)提供給所有集合(集合是分布式函數(shù),用于以某些眾所周知的編程模式交換信息)。
torch.distributed.new_group(ranks=None, timeout=datetime.timedelta(0, 1800), backend=None)?
創(chuàng)建一個(gè)新的分布式組。
此功能要求主組中的所有進(jìn)程(即,屬于分布式作業(yè)的所有進(jìn)程)都必須輸入此功能,即使它們不會(huì)成為該組的成員也是如此。 此外,應(yīng)在所有過程中以相同順序創(chuàng)建組。
Parameters
gloo
后端。gloo
和nccl
。 默認(rèn)情況下,使用與全局組相同的后端。 此字段應(yīng)以小寫字符串(例如"gloo"
)形式給出,也可以通過 Backend
屬性(例如Backend.GLOO
)進(jìn)行訪問。Returns
可以分配給集體呼叫的分布式組的句柄。
torch.distributed.send(tensor, dst, group=<object object>, tag=0)?
同步發(fā)送張量。
Parameters
torch.distributed.recv(tensor, src=None, group=<object object>, tag=0)?
同步接收張量。
Parameters
Returns
發(fā)件人等級(jí)-1,如果不屬于該組
isend()
和 irecv()
在使用時(shí)返回分布式請(qǐng)求對(duì)象。 通常,此對(duì)象的類型是不確定的,因?yàn)樗鼈冇肋h(yuǎn)不應(yīng)該手動(dòng)創(chuàng)建,但是可以保證它們支持兩種方法:
is_completed()
-如果操作完成,則返回 Truewait()
-將阻止該過程,直到操作完成。 保證is_completed()
一旦返回就返回 True。torch.distributed.isend(tensor, dst, group=<object object>, tag=0)?
異步發(fā)送張量。
Parameters
Returns
分布式請(qǐng)求對(duì)象。 無,如果不是該組的一部分
torch.distributed.irecv(tensor, src, group=<object object>, tag=0)?
異步接收張量。
Parameters
Returns
A distributed request object. None, if not part of the group
每個(gè)集體操作功能都支持以下兩種操作:
同步操作-async_op
設(shè)置為 False 時(shí)的默認(rèn)模式。 當(dāng)函數(shù)返回時(shí),可以確保執(zhí)行了集合操作(如果它是 CUDA op,則不一定要完成,因?yàn)樗?CUDA ops 都是異步的),并且可以根據(jù)集合操作的數(shù)據(jù)調(diào)用任何進(jìn)一步的函數(shù)。 在同步模式下,集合函數(shù)不返回任何內(nèi)容
異步操作-當(dāng)async_op
設(shè)置為 True 時(shí)。 集合操作函數(shù)返回一個(gè)分布式請(qǐng)求對(duì)象。 通常,您不需要手動(dòng)創(chuàng)建它,并且可以支持兩種方法:
is_completed()
- returns True if the operation has finishedwait()
-將阻止該過程,直到操作完成。torch.distributed.broadcast(tensor, src, group=<object object>, async_op=False)?
向整個(gè)組廣播張量。
tensor
在參與集合的所有進(jìn)程中必須具有相同數(shù)量的元素。
Parameters
src
是當(dāng)前進(jìn)程的等級(jí),則發(fā)送數(shù)據(jù),否則使用張量保存接收到的數(shù)據(jù)。Returns
異步工作句柄(如果 async_op 設(shè)置為 True)。 無,如果不是 async_op 或不是該組的一部分
torch.distributed.all_reduce(tensor, op=ReduceOp.SUM, group=<object object>, async_op=False)?
減少所有機(jī)器上的張量數(shù)據(jù),以使所有機(jī)器都能得到最終結(jié)果。
調(diào)用之后,tensor
將在所有進(jìn)程中按位相同。
Parameters
torch.distributed.ReduceOp
枚舉的值之一。 指定用于逐元素精簡(jiǎn)的操作。Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
torch.distributed.reduce(tensor, dst, op=ReduceOp.SUM, group=<object object>, async_op=False)?
減少所有機(jī)器上的張量數(shù)據(jù)。
只有等級(jí)為dst
的進(jìn)程才能收到最終結(jié)果。
Parameters
torch.distributed.ReduceOp
enum. Specifies an operation used for element-wise reductions.Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
torch.distributed.all_gather(tensor_list, tensor, group=<object object>, async_op=False)?
在列表中收集整個(gè)組的張量。
Parameters
Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
torch.distributed.gather(tensor, gather_list=None, dst=0, group=<object object>, async_op=False)?
在單個(gè)過程中收集張量列表。
Parameters
Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
torch.distributed.scatter(tensor, scatter_list=None, src=0, group=<object object>, async_op=False)?
將張量列表分散到組中的所有進(jìn)程。
每個(gè)進(jìn)程將僅接收一個(gè)張量并將其數(shù)據(jù)存儲(chǔ)在tensor
參數(shù)中。
Parameters
Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
torch.distributed.barrier(group=<object object>, async_op=False)?
同步所有進(jìn)程。
如果 async_op 為 False,或者在 wait()上調(diào)用了異步工作句柄,則該集合將阻塞進(jìn)程,直到整個(gè)組都進(jìn)入該函數(shù)。
Parameters
Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
class torch.distributed.ReduceOp?
可用還原操作的類枚舉類:SUM
,PRODUCT
,MIN
,MAX
,BAND
,BOR
和BXOR
。
此類的值可以作為屬性訪問,例如ReduceOp.SUM
。 它們用于指定減少集合體的策略,例如 reduce()
, all_reduce_multigpu()
等。
成員:
和
產(chǎn)品
最小
最大值
帶
BOR
異或
class torch.distributed.reduce_op?
減少操作的不推薦枚舉類:SUM
,PRODUCT
,MIN
和MAX
。
建議改用 ReduceOp
。
如果每個(gè)節(jié)點(diǎn)上有多個(gè) GPU,則在使用 NCCL 和 Gloo 后端時(shí), broadcast_multigpu()
all_reduce_multigpu()
reduce_multigpu()
和 all_gather_multigpu()
支持在每個(gè)節(jié)點(diǎn)內(nèi)的多個(gè) GPU 之間進(jìn)行分布式集體操作。 這些功能可以潛在地改善整體分布式訓(xùn)練性能,并且可以通過傳遞張量列表輕松使用。 傳遞的張量列表中的每個(gè)張量必須位于調(diào)用該函數(shù)的主機(jī)的單獨(dú) GPU 設(shè)備上。 請(qǐng)注意,在所有分布式過程中,張量列表的長(zhǎng)度必須相同。 另請(qǐng)注意,當(dāng)前只有 NCCL 后端支持多 GPU 集合功能。
例如,如果我們用于分布式訓(xùn)練的系統(tǒng)有 2 個(gè)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)都有 8 個(gè) GPU。 在 16 個(gè) GPU 的每個(gè) GPU 上,都有一個(gè)我們想全部減少的張量。 以下代碼可以作為參考:
在節(jié)點(diǎn) 0 上運(yùn)行的代碼
import torch
import torch.distributed as dist
dist.init_process_group(backend="nccl",
init_method="file:///distributed_test",
world_size=2,
rank=0)
tensor_list = []
for dev_idx in range(torch.cuda.device_count()):
tensor_list.append(torch.FloatTensor([1]).cuda(dev_idx))
dist.all_reduce_multigpu(tensor_list)
在節(jié)點(diǎn) 1 上運(yùn)行的代碼
import torch
import torch.distributed as dist
dist.init_process_group(backend="nccl",
init_method="file:///distributed_test",
world_size=2,
rank=1)
tensor_list = []
for dev_idx in range(torch.cuda.device_count()):
tensor_list.append(torch.FloatTensor([1]).cuda(dev_idx))
dist.all_reduce_multigpu(tensor_list)
調(diào)用之后,兩個(gè)節(jié)點(diǎn)上的所有 16 張量將具有全部約簡(jiǎn)值 16
torch.distributed.broadcast_multigpu(tensor_list, src, group=<object object>, async_op=False, src_tensor=0)?
將張量廣播到整個(gè)組,每個(gè)節(jié)點(diǎn)具有多個(gè) GPU 張量。
tensor
在參與集合的所有進(jìn)程的所有 GPU 中必須具有相同數(shù)量的元素。 列表中的每個(gè)張量必須在不同的 GPU 上
當(dāng)前僅支持 nccl 和 gloo 后端張量應(yīng)僅是 GPU 張量
Parameters
src
是等級(jí),則tensor_list
(tensor_list[src_tensor]
)的指定src_tensor
元素將在 src 進(jìn)程中廣播給所有其他張量(在不同 GPU 上),而在其他非張量中tensor_list
的所有張量 -src 進(jìn)程。 您還需要確保所有調(diào)用此函數(shù)的分布式進(jìn)程的len(tensor_list)
相同。tensor_list
內(nèi)的源張量等級(jí)Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
torch.distributed.all_reduce_multigpu(tensor_list, op=ReduceOp.SUM, group=<object object>, async_op=False)?
減少所有機(jī)器上的張量數(shù)據(jù),以使所有機(jī)器都能得到最終結(jié)果。 此功能可減少每個(gè)節(jié)點(diǎn)上的張量數(shù)量,而每個(gè)張量位于不同的 GPU 上。 因此,張量列表中的輸入張量必須是 GPU 張量。 同樣,張量列表中的每個(gè)張量都需要駐留在不同的 GPU 上。
調(diào)用之后,tensor_list
中的所有tensor
在所有進(jìn)程中都將按位相同。
當(dāng)前僅支持 nccl 和 gloo 后端張量應(yīng)僅是 GPU 張量
Parameters
len(tensor_list)
相同。torch.distributed.ReduceOp
enum. Specifies an operation used for element-wise reductions.Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
torch.distributed.reduce_multigpu(tensor_list, dst, op=ReduceOp.SUM, group=<object object>, async_op=False, dst_tensor=0)?
減少所有計(jì)算機(jī)上多個(gè) GPU 上的張量數(shù)據(jù)。 tensor_list
中的每個(gè)張量應(yīng)駐留在單獨(dú)的 GPU 上
排名為dst
的進(jìn)程中只有tensor_list[dst_tensor]
的 GPU 會(huì)收到最終結(jié)果。
當(dāng)前僅支持 nccl 后端張量應(yīng)僅是 GPU 張量
Parameters
len(tensor_list)
相同。torch.distributed.ReduceOp
enum. Specifies an operation used for element-wise reductions.tensor_list
中的目標(biāo)張量等級(jí)Returns
異步工作句柄(如果 async_op 設(shè)置為 True)。 無,否則
torch.distributed.all_gather_multigpu(output_tensor_lists, input_tensor_list, group=<object object>, async_op=False)?
在列表中收集整個(gè)組的張量。 tensor_list
中的每個(gè)張量應(yīng)駐留在單獨(dú)的 GPU 上
Only nccl backend is currently supported tensors should only be GPU tensors
Parameters
輸出列表。 它應(yīng)該在每個(gè) GPU 上包含正確大小的張量,以用于集合的輸出,例如 output_tensor_lists[i]
包含位于input_tensor_list[i]
的 GPU 上的 all_gather 結(jié)果。
請(qǐng)注意,output_tensor_lists
的每個(gè)元素的大小均為world_size * len(input_tensor_list)
,因?yàn)樵摵瘮?shù)都從組中的每個(gè) GPU 收集結(jié)果。 要解釋output_tensor_lists[i]
的每個(gè)元素,請(qǐng)注意,排名為 k 的input_tensor_list[j]
將出現(xiàn)在output_tensor_lists[i][k * world_size + j]
中
還要注意,對(duì)于所有調(diào)用此函數(shù)的分布式進(jìn)程,len(output_tensor_lists)
和output_tensor_lists
中每個(gè)元素的大小(每個(gè)元素是一個(gè)列表,因此len(output_tensor_lists[i])
)必須相同。
len(input_tensor_list)
必須相同。Returns
Async work handle, if async_op is set to True. None, if not async_op or if not part of the group
<cite>torch.distributed</cite> 程序包還在 <cite>torch.distributed.launch</cite> 中提供了啟動(dòng)實(shí)用程序。 此幫助程序?qū)嵱贸绦蚩捎糜跒槊總€(gè)節(jié)點(diǎn)啟動(dòng)多個(gè)進(jìn)程以進(jìn)行分布式訓(xùn)練。 該實(shí)用程序還支持 python2 和 python3。
Multiprocessing 軟件包-Torch.multiprocessing 軟件包還在 torch.multiprocessing.spawn()
中提供了spawn
功能。 此輔助函數(shù)可用于產(chǎn)生多個(gè)進(jìn)程。 它通過傳入要運(yùn)行的函數(shù)并產(chǎn)生 N 個(gè)進(jìn)程來運(yùn)行它而起作用。 這也可以用于多進(jìn)程分布式訓(xùn)練。
請(qǐng)注意,此功能需要 Python 3.4 或更高版本。
更多建議: