Cluster是硬件资源到逻辑资源的映射,支持不同分组策略将硬件资源划分为多组Virtual Devices。本文介绍Cluster支持的分组策略、调用格式、参数说明、调用示例及Worker角色概念,以指导您进行资源划分和映射。
背景信息
分布式框架的工作是将用户模型的各部分通过不同并行化方法放至分布式计算硬件上,并进行计算。该过程在Whale中总结为模型划分、资源划分及映射。Whale提供的分布式计算资源划分工具Cluster,适用于资源划分和映射部分。
- cluster
cluster是对整个硬件资源到逻辑资源的划分映射管理类,支持不同分组策略将硬件资源划分为多组Virtual Devices。
- layout
layout决定了如何从硬件资源到逻辑资源划分映射,其中layout是cluster的一个参数。
格式
cluster(worker_hosts=None,
ps_hosts=None,
job_name="worker",
rank=0,
layout="all")
参数
- worker_hosts:Worker Hosts信息,STRING类型。默认值为None,表示从TF_CONFIG环境变量中获取Hosts、Rank等信息。
- ps_hosts:Parameter Server Hosts信息,STRING类型。
- job_name:当前Worker Job Name,STRING类型,默认值为"worker"。
- rank:当前Worker Rank,INTEGER类型。
- layout:Cluster的分组策略,DICT类型,默认值为all。Whale的Cluster提供的资源分组策略有以下几种:
- all
将所有GPU放置在一个分组中。
以下图的资源为例,介绍如何实现该分组策略及实现效果。您可以使用如下代码实现该分组策略。
返回的import whale as wh cluster = wh.cluster(layout="all")
cluster.slices
内容如下。[ [ [Worker0:GPU0], [Worker0:GPU1], [Worker0:GPU2], [Worker0:GPU3], [Worker1:GPU0], [Worker1:GPU1], [Worker1:GPU2], [Worker1:GPU3] ] ]
- average
Cluster内的所有资源平均划分,每份N张卡。
将Worker内的GPU按行排布,如下图所示。您可以使用如下代码实现该分组策略。
返回的import whale as wh cluster = wh.cluster(layout = {'average' : 4 } )
cluster.slices
内容如下。
Cluster的划分结果如下图所示。[ [ [Worker0:GPU0], [Worker0:GPU1], [Worker0:GPU2], [Worker0:GPU3] ], [ [Worker1:GPU0], [Worker1:GPU1], [Worker1:GPU2], [Worker1:GPU3] ], ]
- block
将Cluster按照GPU Block分组。
下图中的资源划分为两个组,分别包含6张卡和2张卡。每个分组又细分为两个子分组,通过Cluster的slices属性可以获取各分组信息。您可以使用如下代码实现该分组策略。
返回的import whale as wh cluster = wh.cluster(layout={"block" : "3,1"})
cluster.slices
内容如下。[ [ [ Worker0:GPU0, Worker0:GPU1, Worker0:GPU2 ], [ Worker1:GPU0, Worker1:GPU1, Worker1:GPU2 ] ], [ [Worker0:GPU3], [Worker1:GPU3] ] ]
- row
将Worker内的GPU按行排布。
如下图所示,row的划分则是水平机器内划分。您可以使用如下代码实现该分组策略。
返回的import whale as wh cluster = wh.cluster(layout = {"row" : 4 })
cluster.slices
内容如下。[ [ [Worker0:GPU0], [Worker0:GPU1], [Worker0:GPU2], [Worker0:GPU3] ], [ [Worker1:GPU0], [Worker1:GPU1], [Worker1:GPU2], [Worker1:GPU3] ] ]
- column
将Worker内的GPU按行排布,Column的划分按照垂直跨机划分。
Column的划分如下图所示。您可以使用如下代码实现该分组策略。
返回的import whale as wh cluster = wh.cluster(layout = {"column" : 2 })
cluster.slices
内容如下。[ [ [Worker0:GPU0], [Worker1:GPU0] ], [ [Worker0:GPU1], [Worker1:GPU1] ], [ [Worker0:GPU2], [Worker1:GPU2] ], [ [Worker0:GPU3], [Worker1:GPU3] ] ]
当存在更多Worker时,Cluster按column划分,如果使用layout={"column" : 2 }
策略,则Cluster划分结果如下图所示。返回的
cluster.slices
内容如下。[ [ [Worker0:GPU0], [Worker1:GPU0] ], [ [Worker2:GPU0], [Worker3:GPU0] ], [ [Worker0:GPU1], [Worker1:GPU1] ], [ [Worker2:GPU1], [Worker3:GPU1] ], [ [Worker0:GPU2], [Worker1:GPU2] ], [ [Worker2:GPU2], [Worker3:GPU2] ], [ [Worker0:GPU3], [Worker1:GPU3] ], [ [Worker2:GPU3], [Worker3:GPU3], ] ]
- specific
通过配置具体的Device信息进行cluster划分。
将Worker内的GPU按行排布,如下图所示。您可以使用如下代码实现该分组策略。
返回的import whale as wh cluster = wh.cluster( layout = {'specific' : [ [['worker:0/gpu:0'], ['worker:0/gpu:1']], [['worker:1/gpu:0'], ['worker:1/gpu:1']] ] } )
cluster.slices
内容如下。
Cluster划分结果如下图所示。[ [ [Worker0:GPU0], [Worker0:GPU1] ], [ [Worker1:GPU0], [Worker1:GPU1] ], ]
- all
返回值
whale.Cluster
对象,具有以下属性:
- rank调用方式如下。
返回当前的Worker Rank。cluster.rank
- worker_num调用方式如下。
返回Worker数量。cluster.worker_num
- gpu_num_per_worker调用方式如下。
返回每个Worker的GPU数量。cluster.gpu_num_per_worker
- slices调用方式如下。
返回Cluster通过layout划分后的资源分组,返回类型为嵌套的LIST。cluster.slices
- total_gpu_num调用方式如下。
返回Cluster中所有GPU数量。cluster.total_gpu_num
示例
- 使用
with
自动映射在模型定义最前面,通过with
语法,Whale框架可以自动将模型映射到Virtual Devices,示例代码如下。import whale as wh with wh.cluster(layout = {"row" : 4 }): # 假设将Cluster划分为如下2个Slices。 # [ # [ [Worker0:GPU0], [Worker0:GPU1], [Worker0:GPU2], [Worker0:GPU3] ], # [ [Worker1:GPU0], [Worker1:GPU1],[Worker1:GPU2], [Worker1:GPU3] ] # ] with wh.stage(): model_part_1() with wh.stage(): model_part_2()
- 使用Slices手动映射
Whale的Cluster通过layout划分之后,可以通过Slices方法获取划分后的分组。Whale Scopes支持直接设置Devices信息,因此可以使用Slices手动映射。示例代码如下。
手动设置的方法可以更灵活地为每个Scope设置Device信息,例如多个Scopes复用相同Slices。import whale as wh cluster = wh.cluster(layout = {"row" : 4 }) # 假设将cluster划分成如下2个slices。 # [ # [ [Worker0:GPU0], [Worker0:GPU1], [Worker0:GPU2], [Worker0:GPU3] ], # [ [Worker1:GPU0], [Worker1:GPU1],[Worker1:GPU2], [Worker1:GPU3] ] # ] with wh.stage(cluster.slices[0]): model_part_1() with wh.stage(cluster.slices[1]): model_part_2()
with
自动用法和手动用法。
Whale中Worker角色概念
根据whale.cluster
定义,申请到的所有Worker会通过layout策略进行分组,生成Virtual Devices Slices,该Slices是一个嵌套LIST。Whale框架将slices[0]
中所有Device的对应Worker称之为Master Worker,负责原始图构造,并完成并行化图的改写。其余Worker不进行构图,直接调用server.join
等待Master Worker分配任务,这些Worker称之为Slave Workers。
layout=wh.cluster(layout={"block" : "3,3" })
生成对应的cluster.slices
如下。[
[
["/job:worker/replica:0/worker:0/device:GPU:0"],
["/job:worker/replica:0/worker:0/device:GPU:1"],
["/job:worker/replica:0/worker:1/device:GPU:0"]
],
[
["/job:worker/replica:0/worker:1/device:GPU:1"],
["/job:worker/replica:0/worker:2/device:GPU:0"],
["/job:worker/replica:0/worker:2/device:GPU:1"]
]
]
由上可知cluster.slices[0]
取值如下。[
["/job:worker/replica:0/worker:0/device:GPU:0"],
["/job:worker/replica:0/worker:0/device:GPU:1"],
["/job:worker/replica:0/worker:1/device:GPU:0"]
]
所以task_index为0和1的Worker即为Master Workers,task_index为2的Worker即为Slave Workers。
在文档使用中是否遇到以下问题
更多建议
匿名提交