Unverified Commit c448e61b authored by zhjwy9343's avatar zhjwy9343 Committed by GitHub
Browse files

[Doc] CN User Guide Chapter 7 (#2481)



* [Doc] Add Chapter 7

* [Doc] Add CN part 7, 7.1, 7.2, and 7.3

* [Doc] Add CN part 7, 7.1, 7.2, and 7.3

* [Doc] 1st round copyediting, 7, 7.1, 7.2, and 7.3, removing EN parts.

* [Doc] 2nd round copyediting.

* [Doc] 3rd round copyediting.

* [Doc] Copyedit with reviewers' comments.
Co-authored-by: default avatarMufei Li <mufeili1996@gmail.com>
parent 31f65f03
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
7.2 Distributed APIs 7.2 Distributed APIs
-------------------- --------------------
:ref:`(中文版) <guide_cn-distributed-apis>`
This section covers the distributed APIs used in the training script. DGL provides three distributed This section covers the distributed APIs used in the training script. DGL provides three distributed
data structures and various APIs for initialization, distributed sampling and workload split. data structures and various APIs for initialization, distributed sampling and workload split.
For distributed training/inference, DGL provides three distributed data structures: For distributed training/inference, DGL provides three distributed data structures:
...@@ -218,12 +220,6 @@ the sampler cannot run in Pytorch Dataloader with multiple worker processes. The ...@@ -218,12 +220,6 @@ the sampler cannot run in Pytorch Dataloader with multiple worker processes. The
Pytorch Dataloader creates new sampling worker processes in every epoch, which leads to creating and Pytorch Dataloader creates new sampling worker processes in every epoch, which leads to creating and
destroying :class:`~dgl.distributed.DistGraph` objects many times. destroying :class:`~dgl.distributed.DistGraph` objects many times.
The same high-level sampling APIs (:class:`~dgl.dataloading.pytorch.NodeDataloader` and
:class:`~dgl.dataloading.pytorch.EdgeDataloader` ) work for both :class:`~dgl.DGLGraph`
and :class:`~dgl.distributed.DistGraph`. When using :class:`~dgl.dataloading.pytorch.NodeDataloader`
and :class:`~dgl.dataloading.pytorch.EdgeDataloader`, the distributed sampling code is exactly
the same as single-process sampling.
When using the low-level API, the sampling code is similar to single-process sampling. The only When using the low-level API, the sampling code is similar to single-process sampling. The only
difference is that users need to use :func:`dgl.distributed.sample_neighbors` and difference is that users need to use :func:`dgl.distributed.sample_neighbors` and
:class:`~dgl.distributed.DistDataLoader`. :class:`~dgl.distributed.DistDataLoader`.
...@@ -246,7 +242,11 @@ difference is that users need to use :func:`dgl.distributed.sample_neighbors` an ...@@ -246,7 +242,11 @@ difference is that users need to use :func:`dgl.distributed.sample_neighbors` an
for batch in dataloader: for batch in dataloader:
... ...
When using the high-level API, the distributed sampling code is identical to the single-machine sampling: The same high-level sampling APIs (:class:`~dgl.dataloading.pytorch.NodeDataloader` and
:class:`~dgl.dataloading.pytorch.EdgeDataloader` ) work for both :class:`~dgl.DGLGraph`
and :class:`~dgl.distributed.DistGraph`. When using :class:`~dgl.dataloading.pytorch.NodeDataloader`
and :class:`~dgl.dataloading.pytorch.EdgeDataloader`, the distributed sampling code is exactly
the same as single-process sampling.
.. code:: python .. code:: python
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
7.1 Preprocessing for Distributed Training 7.1 Preprocessing for Distributed Training
------------------------------------------ ------------------------------------------
:ref:`(中文版) <guide_cn-distributed-preprocessing>`
DGL requires preprocessing the graph data for distributed training, including two steps: DGL requires preprocessing the graph data for distributed training, including two steps:
1) partition a graph into subgraphs, 2) assign nodes/edges with new Ids. DGL provides 1) partition a graph into subgraphs, 2) assign nodes/edges with new Ids. DGL provides
a partitioning API that performs the two steps. The API supports both random partitioning a partitioning API that performs the two steps. The API supports both random partitioning
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
7.3 Tools for launching distributed training/inference 7.3 Tools for launching distributed training/inference
------------------------------------------------------ ------------------------------------------------------
:ref:`(中文版) <guide_cn-distributed-tools>`
DGL provides two scripts to assist in distributed training: DGL provides two scripts to assist in distributed training:
* *tools/copy_files.py* for copying graph partitions to a graph, * *tools/copy_files.py* for copying graph partitions to a graph,
......
.. _guide-distributed:
Chapter 7: Distributed Training Chapter 7: Distributed Training
===================================== =====================================
:ref:`(中文版) <guide_cn-distributed>`
DGL adopts a fully distributed approach that distributes both data and computation DGL adopts a fully distributed approach that distributes both data and computation
across a collection of computation resources. In the context of this section, we across a collection of computation resources. In the context of this section, we
will assume a cluster setting (i.e., a group of machines). DGL partitions a graph will assume a cluster setting (i.e., a group of machines). DGL partitions a graph
......
.. _guide_cn-distributed-apis:
7.2 分布式计算的API
--------------------
:ref:`(English Version) <guide-distributed-apis>`
本节介绍了在训练脚本中使用的分布式计算API。DGL提供了三种分布式数据结构和多种API,用于初始化、分布式采样和数据分割。
对于分布式训练/推断,DGL提供了三种分布式数据结构:用于分布式图的 :class:`~dgl.distributed.DistGraph`、
用于分布式张量的 :class:`~dgl.distributed.DistTensor` 和用于分布式可学习嵌入的
:class:`~dgl.distributed.DistEmbedding`。
DGL分布式模块的初始化
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:func:`~dgl.distributed.initialize` 可以用于初始化分布式模块。当训练脚本在训练器模式下运行时,
这个API会与DGL服务器建立连接并创建采样器进程。当脚本在服务器模式下运行时,这个API将运行服务器代码,
直到训练任务结束。必须在DGL的任何其他分布式API之前,调用此API。在使用PyTorch时,必须在
``torch.distributed.init_process_group`` 之前调用 :func:`~dgl.distributed.initialize`。
通常,初始化API应按以下顺序调用:
.. code:: python
dgl.distributed.initialize('ip_config.txt', num_workers=4)
th.distributed.init_process_group(backend='gloo')
**Note**: 如果训练脚本里包含需要在服务器(细节内容可以在下面的DistTensor和DistEmbedding章节里查看)上调用的用户自定义函数(UDF),
这些UDF必须在 :func:`~dgl.distributed.initialize` 之前被声明。
分布式图
~~~~~~~~~~~~~~~~~
:class:`~dgl.distributed.DistGraph` 是一个Python类,用于访问计算机集群中的图结构和节点/边特征。每台计算机负责一个且只负责一个分区。
它加载分区数据(包括分区中的图结构、节点数据和边数据),并使集群中的所有训练器均可访问它们。
:class:`~dgl.distributed.DistGraph` 提供了一小部分 :class:`~dgl.DGLGraph` 的API以方便数据访问。
**Note**: :class:`~dgl.distributed.DistGraph` 当前仅支持一种节点类型和一种边类型的图。
分布式模式与独立模式
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
:class:`~dgl.distributed.DistGraph` 可以在两种模式下运行:分布式模式和独立模式。
当用户在Python命令行或Jupyter Notebook中执行训练脚本时,它将以独立模式运行。也就是说,它在单个进程中运行所有计算,
并且不与任何其他进程通信。因此,独立模式要求输入图仅具有一个分区。此模式主要用于开发和测试
(例如,在Jupyter Notebook中开发和运行代码)。当用户使用启动脚本执行训练脚本时(请参见启动脚本部分),
:class:`~dgl.distributed.DistGraph` 将以分布式模式运行。启动脚本在后台启动服务器(包括访问节点/边特征和图采样),
并将分区数据自动加载到每台计算机中。:class:`~dgl.distributed.DistGraph` 与集群中的服务器连接并通过网络访问它们。
创建DistGraph
^^^^^^^^^^^^^^^^^^
在分布式模式下,:class:`~dgl.distributed.DistGraph` 的创建需要(定义)在图划分期间的图名称。
图名称标识了集群中所需加载的图。
.. code:: python
import dgl
g = dgl.distributed.DistGraph('graph_name')
在独立模式下运行时,DistGraph将图数据加载到本地计算机中。因此,用户需要提供分区配置文件,其中包含有关输入图的所有信息。
.. code:: python
import dgl
g = dgl.distributed.DistGraph('graph_name', part_config='data/graph_name.json')
**Note**: 在当前实现中,DGL仅允许创建单个DistGraph对象。销毁DistGraph并创建一个新DistGraph的行为没有被定义。
访问图结构
^^^^^^^^^^^^^^^^^^^^^^
:class:`~dgl.distributed.DistGraph` 提供了几个API来访问图结构。当前,它们主要被用来提供图信息,例如节点和边的数量。
主要应用场景是运行采样API以支持小批量训练(请参阅下文里分布式图采样部分)。
.. code:: python
print(g.number_of_nodes())
访问节点/边数据
^^^^^^^^^^^^^^^^^^^^^
与 :class:`~dgl.DGLGraph` 一样, :class:`~dgl.distributed.DistGraph` 也提供了
``ndata`` 和 ``edata`` 来访问节点和边中的数据。它们的区别在于
:class:`~dgl.distributed.DistGraph` 中的 ``ndata`` / ``edata`` 返回的是 :class:`~dgl.distributed.DistTensor`,
而不是底层框架里的张量。用户还可以将新的 :class:`~dgl.distributed.DistTensor` 分配给
:class:`~dgl.distributed.DistGraph` 作为节点数据或边数据。
.. code:: python
g.ndata['train_mask']
<dgl.distributed.dist_graph.DistTensor at 0x7fec820937b8>
g.ndata['train_mask'][0]
tensor([1], dtype=torch.uint8)
分布式张量
~~~~~~~~~~~~~~~~~
如前所述,在分布式模式下,DGL会划分节点和边特征,并将它们存储在计算机集群中。
DGL为分布式张量提供了类似于单机普通张量的接口,以访问群集中的分区节点和边特征。
在分布式设置中,DGL仅支持密集节点和边特征,暂不支持稀疏节点和边特征。
:class:`~dgl.distributed.DistTensor` 管理在多个计算机中被划分和存储的密集张量。
目前,分布式张量必须与图的节点或边相关联。换句话说,DistTensor中的行数必须与图中的节点数或边数相同。
以下代码创建一个分布式张量。 除了张量的形状和数据类型之外,用户还可以提供唯一的张量名称。
如果用户要引用一个固定的分布式张量(即使 :class:`~dgl.distributed.DistTensor` 对象消失,该名称仍存在于群集中),
则(使用这样的)名称就很有用。
.. code:: python
tensor = dgl.distributed.DistTensor((g.number_of_nodes(), 10), th.float32, name=’test’)
**Note**: :class:`~dgl.distributed.DistTensor` 的创建是一个同步操作。所有训练器都必须调用创建,
并且只有当所有训练器都调用它时,此创建过程才能成功。
用户可以将 :class:`~dgl.distributed.DistTensor` 作为节点数据或边数据之一添加到
:class:`~dgl.distributed.DistGraph` 对象。
.. code:: python
g.ndata['feat'] = tensor
**Note**: 节点数据名称和张量名称不必相同。前者在 :class:`~dgl.distributed.DistGraph` 中标识节点数据(在训练器进程中),
而后者则标识DGL服务器中的分布式张量。
:class:`~dgl.distributed.DistTensor` 提供了一些功能。它具有与常规张量相同的API,用于访问其元数据,
例如形状和数据类型。:class:`~dgl.distributed.DistTensor` 支持索引读取和写入,
但不支持一些计算运算符,例如求和以及求均值。
.. code:: python
data = g.ndata['feat'][[1, 2, 3]]
print(data)
g.ndata['feat'][[3, 4, 5]] = data
**Note**: 当前,当一台机器运行多个服务器时,DGL不提供对来自多个训练器的并发写入的保护。
这可能会导致数据损坏。
分布式嵌入
~~~~~~~~~~~~~~~~~~~~~
DGL提供 :class:`~dgl.distributed.DistEmbedding` 以支持需要节点嵌入的直推(transductive)模型。
分布式嵌入的创建与分布式张量的创建非常相似。
.. code:: python
def initializer(shape, dtype):
arr = th.zeros(shape, dtype=dtype)
arr.uniform_(-1, 1)
return arr
emb = dgl.distributed.DistEmbedding(g.number_of_nodes(), 10, init_func=initializer)
在内部,分布式嵌入建立在分布式张量之上,因此,其行为与分布式张量非常相似。
例如,创建嵌入时,DGL会将它们分片并存储在集群中的所有计算机上。(分布式嵌入)可以通过名称唯一标识。
**Note**: 服务器进程负责调用初始化函数。因此,必须在初始化( :class:`~dgl.distributed.initialize` )之前声明分布式嵌入。
因为嵌入是模型的一部分,所以用户必须将其附加到优化器上以进行小批量训练。当前,
DGL提供了一个稀疏的Adagrad优化器 :class:`~dgl.distributed.SparseAdagrad` (DGL以后将为稀疏嵌入添加更多的优化器)。
用户需要从模型中收集所有分布式嵌入,并将它们传递给稀疏优化器。如果模型同时具有节点嵌入和规则的密集模型参数,
并且用户希望对嵌入执行稀疏更新,则需要创建两个优化器,一个用于节点嵌入,另一个用于密集模型参数,如以下代码所示:
.. code:: python
sparse_optimizer = dgl.distributed.SparseAdagrad([emb], lr=lr1)
optimizer = th.optim.Adam(model.parameters(), lr=lr2)
feats = emb(nids)
loss = model(feats)
loss.backward()
optimizer.step()
sparse_optimizer.step()
**Note**: :class:`~dgl.distributed.DistEmbedding` 不是PyTorch的nn模块,因此用户无法从nn模块的参数访问它。
分布式采样
~~~~~~~~~~~~~~~~~~~~
DGL提供了两个级别的API,用于对节点和边进行采样以生成小批次训练数据(请参阅小批次训练的章节)。
底层API要求用户编写代码以明确定义如何对节点层进行采样(例如,使用 :func:`dgl.sampling.sample_neighbors` )。
高层采样API为节点分类和链接预测任务实现了一些流行的采样算法(例如
:class:`~dgl.dataloading.pytorch.NodeDataloader`
:class:`~dgl.dataloading.pytorch.EdgeDataloader` )。
分布式采样模块遵循相同的设计,也提供两个级别的采样API。对于底层的采样API,它为
:class:`~dgl.distributed.DistGraph` 上的分布式邻居采样提供了
:func:`~dgl.distributed.sample_neighbors`。另外,DGL提供了用于分布式采样的分布式数据加载器(
:class:`~dgl.distributed.DistDataLoader`)。除了用户在创建数据加载器时无法指定工作进程的数量,
分布式数据加载器具有与PyTorch DataLoader相同的接口。其中的工作进程(worker)在 :func:`dgl.distributed.initialize` 中创建。
**Note**: 在 :class:`~dgl.distributed.DistGraph` 上运行 :func:`dgl.distributed.sample_neighbors` 时,
采样器无法在具有多个工作进程的PyTorch Dataloader中运行。主要原因是PyTorch Dataloader在每个训练周期都会创建新的采样工作进程,
从而导致多次创建和删除 :class:`~dgl.distributed.DistGraph` 对象。
使用底层API时,采样代码类似于单进程采样。唯一的区别是用户需要使用
:func:`dgl.distributed.sample_neighbors`
:class:`~dgl.distributed.DistDataLoader`。
.. code:: python
def sample_blocks(seeds):
seeds = th.LongTensor(np.asarray(seeds))
blocks = []
for fanout in [10, 25]:
frontier = dgl.distributed.sample_neighbors(g, seeds, fanout, replace=True)
block = dgl.to_block(frontier, seeds)
seeds = block.srcdata[dgl.NID]
blocks.insert(0, block)
return blocks
dataloader = dgl.distributed.DistDataLoader(dataset=train_nid,
batch_size=batch_size,
collate_fn=sample_blocks,
shuffle=True)
for batch in dataloader:
...
:class:`~dgl.DGLGraph` 和 :class:`~dgl.distributed.DistGraph` 都可以使用相同的高级采样API(
:class:`~dgl.dataloading.pytorch.NodeDataloader`
:class:`~dgl.dataloading.pytorch.EdgeDataloader`)。使用
:class:`~dgl.dataloading.pytorch.NodeDataloader`
:class:`~dgl.dataloading.pytorch.EdgeDataloader` 时,分布式采样代码与单进程采样完全相同。
.. code:: python
sampler = dgl.sampling.MultiLayerNeighborSampler([10, 25])
dataloader = dgl.sampling.NodeDataLoader(g, train_nid, sampler,
batch_size=batch_size, shuffle=True)
for batch in dataloader:
...
分割数据集
~~~~~~~~~~~~~~~
用户需要分割训练集,以便每个训练器都可以使用自己的训练集子集。同样,用户还需要以相同的方式分割验证和测试集。
对于分布式训练和评估,推荐的方法是使用布尔数组表示训练、验证和测试集。对于节点分类任务,
这些布尔数组的长度是图中节点的数量,并且它们的每个元素都表示训练/验证/测试集中是否存在对应节点。
链接预测任务也应使用类似的布尔数组。
DGL提供了 :func:`~dgl.distributed.node_split` 和 :func:`~dgl.distributed.edge_split`
函数来在运行时拆分训练、验证和测试集,以进行分布式训练。这两个函数将布尔数组作为输入,对其进行拆分,并向本地训练器返回一部分。
默认情况下,它们确保所有部分都具有相同数量的节点和边。这对于同步SGD非常重要,
因为同步SGD会假定每个训练器具有相同数量的小批次。
下面的示例演示了训练集拆分,并向本地进程返回节点的子集。
.. code:: python
train_nids = dgl.distributed.node_split(g.ndata['train_mask'])
.. _guide_cn-distributed-preprocessing:
7.1 分布式训练所需的图数据预处理
------------------------------------------
:ref:`(English Version) <guide-distributed-preprocessing>`
DGL要求预处理图数据以进行分布式训练,这包括两个步骤:1)将一张图划分为多张子图(分区),2)为节点和边分配新的ID。
DGL提供了一个API以执行这两个步骤。该API支持随机划分和一个基于
`Metis <http://glaros.dtc.umn.edu/gkhome/views/metis>`__ 的划分。Metis划分的好处在于,
它可以用最少的边分割以生成分区,从而减少了用于分布式训练和推理的网络通信。DGL使用最新版本的Metis,
并针对真实世界中具有幂律分布的图进行了优化。在图划分后,API以易于在训练期间加载的格式构造划分结果。
**Note**: 图划分API当前在一台机器上运行。 因此如果一张图很大,用户将需要一台大内存的机器来对图进行划分。
未来DGL将支持分布式图划分。
默认情况下,为了在分布式训练/推理期间定位节点/边,API将新ID分配给输入图的节点和边。
分配ID后,该API会相应地打乱所有节点数据和边数据。在训练期间,用户只需使用新的节点和边的ID。
与此同时,用户仍然可以通过 ``g.ndata['orig_id']`` 和 ``g.edata['orig_id']`` 获取原始ID。
其中 ``g`` 是 ``DistGraph`` 对象(详细解释,请参见:ref:`guide-distributed-apis`)。
DGL将图划分结果存储在输出目录中的多个文件中。输出目录里始终包含一个名为xxx.json的JSON文件,其中xxx是提供给划分API的图的名称。
JSON文件包含所有划分的配置。如果该API没有为节点和边分配新ID,它将生成两个额外的NumPy文件:`node_map.npy` 和 `edge_map.npy`。
它们存储节点和边ID与分区ID之间的映射。对于具有十亿级数量节点和边的图,两个文件中的NumPy数组会很大,
这是因为图中的每个节点和边都对应一个条目。在每个分区的文件夹内,有3个文件以DGL格式存储分区数据。
`graph.dgl` 存储分区的图结构以及节点和边上的一些元数据。`node_feats.dgl` 和 `edge_feats.dgl` 存储属于该分区的节点和边的所有特征。
.. code-block:: none
data_root_dir/
|-- xxx.json # JSON中的分区配置文件
|-- node_map.npy # 存储在NumPy数组中的每个节点的分区ID(可选)
|-- edge_map.npy # 存储在NumPy数组中的每个边的分区ID(可选)
|-- part0/ # 分区0的数据
|-- node_feats.dgl # 以二进制格式存储的节点特征
|-- edge_feats.dgl # 以二进制格式存储的边特征
|-- graph.dgl # 以二进制格式存储的子图结构
|-- part1/ # 分区1的数据
|-- node_feats.dgl
|-- edge_feats.dgl
|-- graph.dgl
负载均衡
~~~~~~~~~~~~~~
在对图进行划分时,默认情况下,Metis仅平衡每个子图中的节点数。根据当前的任务情况,这可能带来非最优的配置。
例如,在半监督节点分类的场景里,训练器会对局部分区中带标签节点的子集进行计算。
一个仅平衡图中节点(带标签和未带标签)的划分可能会导致计算负载不平衡。为了在每个分区中获得平衡的工作负载,
划分API通过在 :func:`dgl.distributed.partition_graph` 中指定 ``balance_ntypes``
在每个节点类型中的节点数上实现分区间的平衡。用户可以利用这一点将训练集、验证集和测试集中的节点看作不同类型的节点。
以下示例将训练集内和训练集外的节点看作两种类型的节点:
.. code:: python
dgl.distributed.partition_graph(g, ‘graph_name’, 4, ‘/tmp/test’, balance_ntypes=g.ndata[‘train_mask’])
除了平衡节点的类型之外, :func:`dgl.distributed.partition_graph` 还允许通过指定
``balance_edges`` 来平衡每个类型节点在子图中的入度。这平衡了不同类型节点的连边数量。
**Note**: 传给 :func:`dgl.distributed.partition_graph` 的图名称是一个重要的参数。
:class:`dgl.distributed.DistGraph` 使用该名称来识别一个分布式的图。一个有效的图名称应该仅包含字母和下划线。
.. _guide_cn-distributed-tools:
7.3 运行分布式训练/推断所需的工具
------------------------------------------------------
:ref:`(English Version) <guide-distributed-tools>`
DGL提供了两个脚本来帮助用户进行分布式训练:
* *tools/copy_files.py* 用于将图分区复制到集群,
* *tools/launch.py* 用于在机器集群中启动分布式训练任务。
*copy_files.py* 将计算机(对图进行分区的计算机)中的分区数据和相关文件(例如,训练脚本)
复制到(负责分布式训练的)机器集群上。在这些机器上,分布式训练将需要用到这些分区。该脚本包含四个参数:
* ``--part_config`` 指定分区配置文件,该文件包含本地计算机中分区数据的信息。
* ``--ip_config`` 指定集群的IP配置文件。
* ``--workspace`` 指定训练机器中存储与分布式训练有关的所有数据的目录。
* ``--rel_data_path`` 指定工作空间目录下存储分区数据的相对路径。
* ``--script_folder`` 指定工作空间目录下存储用户的训练脚本的相对路径。
**Note**: *copy_files.py* 会根据IP配置文件找到对应的计算机来存储图分区。因此,copy_files.py和launch.py应该使用相同的IP配置文件。
DGL提供了用于启动集群中的分布式训练任务的tools/launch.py。该脚本有以下假设:
* 分区数据和训练脚本都已被复制到集群或存在集群中所有计算机均可访问的全局存储空间(例如NFS)。
* 主计算机(执行启动脚本的计算机)具有对集群内所有其他计算机的无密码ssh访问权限。
**Note**: 必须在集群中的一台计算机上调用启动脚本。
下面展示了在集群中启动分布式训练任务的示例。
.. code:: none
python3 tools/launch.py \
--workspace ~graphsage/ \
--num_trainers 2 \
--num_samplers 4 \
--num_servers 1 \
--part_config data/ogb-product.json \
--ip_config ip_config.txt \
"python3 code/train_dist.py --graph-name ogb-product --ip_config ip_config.txt --num-epochs 5 --batch-size 1000 --lr 0.1 --num_workers 4"
配置文件 *ip_config.txt* 包含了集群中计算机的IP地址。*ip_config.txt* 的典型示例如下:
.. code:: none
172.31.19.1
172.31.23.205
172.31.29.175
172.31.16.98
每行是一个计算机的IP地址。IP地址后面还可以有一个端口,用来指定不同训练器之间的网络通信所使用的端口。
如果未提供具体端口,则默认值为 ``30050``。
启动脚本中指定的工作空间(--workspace)是计算机中的工作目录,里面保存了训练脚本、IP配置文件、分区配置文件以及图分区。
文件的所有路径都应指定为工作空间的相对路径。
启动脚本会在每台计算机上创建指定数量的训练任务(``--num_trainers``)。另外,
用户需要为每个训练器指定采样器进程的数量(``--num_samplers``)。
采样器进程的数量必须匹配 :func:`~dgl.distributed.initialize` 中指定的工作进程的数量。
.. _guide_cn-distributed:
7章:分布式训练
=====================================
:ref:`(English Version) <guide-distributed>`
DGL采用完全分布式的方法,可将数据和计算同时分布在一组计算资源中。在本节中,
我们默认使用一个集群的环境设置(即一组机器)DGL会将一张图划分为多张子图,
集群中的每台机器各自负责一张子图(分区)。为了并行化计算,DGL在集群所有机器上运行相同的训练脚本,
并在同样的机器上运行服务器以将分区数据提供给训练器。
对于训练脚本,DGL提供了分布式的API。它们与小批次训练的API相似。用户仅需对单机小批次训练的代码稍作修改就可实现分布式训练。
以下代码给出了一个用分布式方式训练GraphSage的示例。仅有的代码修改出现在第4-7行:1)初始化DGL的分布式模块,2)创建分布式图对象,以及
3)拆分训练集,并计算本地进程的节点。其余代码保持不变,与 :ref:`mini_cn-batch training <guide-minibatch>` 类似,
包括:创建采样器,模型定义,模型训练的循环。
.. code:: python
import dgl
import torch as th
dgl.distributed.initialize('ip_config.txt', num_servers, num_workers)
th.distributed.init_process_group(backend='gloo')
g = dgl.distributed.DistGraph('graph_name', 'part_config.json')
pb = g.get_partition_book()
train_nid = dgl.distributed.node_split(g.ndata['train_mask'], pb, force_even=True)
# 创建采样器
sampler = NeighborSampler(g, [10,25],
dgl.distributed.sample_neighbors,
device)
dataloader = DistDataLoader(
dataset=train_nid.numpy(),
batch_size=batch_size,
collate_fn=sampler.sample_blocks,
shuffle=True,
drop_last=False)
# 定义模型和优化器
model = SAGE(in_feats, num_hidden, n_classes, num_layers, F.relu, dropout)
model = th.nn.parallel.DistributedDataParallel(model)
loss_fcn = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=args.lr)
# 模型训练的循环
for epoch in range(args.num_epochs):
for step, blocks in enumerate(dataloader):
batch_inputs, batch_labels = load_subtensor(g, blocks[0].srcdata[dgl.NID],
blocks[-1].dstdata[dgl.NID])
batch_pred = model(blocks, batch_inputs)
loss = loss_fcn(batch_pred, batch_labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
在一个集群的机器上运行训练脚本时,DGL提供了一些工具,可将数据复制到集群的计算机上,并在所有机器上启动训练任务。
**Note**: 当前版本的分布式训练API仅支持PyTorch后端。
**Note**: 当前版本的实现仅支持具有一种节点类型和一种边类型的图。
DGL实现了一些分布式组件以支持分布式训练,下图显示了这些组件及它们间的相互作用。
.. figure:: https://data.dgl.ai/asset/image/distributed.png
:alt: Imgur
具体来说,DGL的分布式训练具有三种类型的交互进程:
*服务器*
*采样器* *训练器*
* *服务器进程* 在存储图分区数据(这包括图结构和节点/边特征)的每台计算机上运行。
这些服务器一起工作以将图数据提供给训练器。请注意,一台机器可能同时运行多个服务器进程,以并行化计算和网络通信。
* *采样器进程* 与服务器进行交互,并对节点和边采样以生成用于训练的小批次数据。
* *训练器进程* 包含多个与服务器交互的类。它用 :class:`~dgl.distributed.DistGraph` 来获取被划分的图分区数据,
:class:`~dgl.distributed.DistEmbedding`
:class:`~dgl.distributed.DistTensor` 来获取节点/边特征/嵌入,用
:class:`~dgl.distributed.dist_dataloader.DistDataLoader` 与采样器进行交互以获得小批次数据。
在初步了解了分布式组件后,本章的剩余部分将介绍以下分布式组件:
* :ref:`guide_cn-distributed-preprocessing`
* :ref:`guide_cn-distributed-apis`
* :ref:`guide_cn-distributed-tools`
.. toctree::
:maxdepth: 1
:hidden:
:glob:
distributed-preprocessing
distributed-apis
distributed-tools
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment