AI开发调试系列第二弹:多机分布式调测探索之旅

举报
alpha-one 发表于 2022/07/02 15:04:06 2022/07/02
【摘要】 在进行AI开发的过程中,往往需要进行大量的调试才能得到满意的结果。modelarts提供了在开发环境中调试训练作业的工具,帮助用户快速验证自己的模型,并无缝衔接modelarts新版训练。本文将借助一篇在线案例,说明如何在开发环境中,利用SDK快速完成AI开发的本地调试工作。

背景知识

在ModelArts平台提交新版训练作业时,经常会出现以下情况:在长时间的准备后,战战兢兢地点击了提交,再经过长时间的排队,结果任务刚跑起来,就报失败,经过仔细检查后,发现时一个参数写错了,修改后提交,又要排队,结果又有代码问题…反反复复多次后,终于运行成功了。一看表,发现已经过了晚饭的时间。为解决用户这样的烦恼,ModelArts隆重推出了调测功能,可以帮助您在开发环境中将训练作业调试好之后再提交,节约大量时间,提升效率,有更多的时间可以和小姐姐小哥哥吃饭去了,想想就开心。

准备工作

在ModelArts平台上,创建开发环境(图中是一个pytorch类型的开发环境)
image.png
点击打开,可以看到
image.png
再点击最上边的PyTorch-1.4,就打开了一个ipynb文件,接下来就正式开始开发调测流程。

单机调测

代码中涉及到的OBS路径,请用户替换为自己的实际OBS路径。代码是以Pytorch为例编写的,不同的AI框架之间,整体流程是完全相同的,仅需修改6和10中的 framework_type参数值即可,例如:MindSpore框架,此处framework_type=Ascend-Powered-Engine。

1、Session初始化

华为云上代码如下:这里只列出最常用的一种方式,更多方式请参考《Session鉴权章节》

from modelarts.session import Session 
session = Session()

2、准备训练数据,这里支持三种形式,用户可根据自己的情况选择一种

import os
from modelarts.train_params import InputData
base_bucket_path = "obs://modelarts-cn-north-4-a0de02a6/dis-train/cifar10/"
base_local_path = "/home/ma-user/work/cifar10/"

# 形式1,数据在OBS上,且是一个压缩文件
obs_path = os.path.join(base_bucket_path, "dataset-zip/dataset.zip")
data_local = os.path.join(base_local_path, "dataset/") 
input_data = InputData(obs_path=obs_path, local_path=data_local, is_local_source=False)

# 形式2,数据在OBS上,且是一个目录
#obs_path = os.path.join(base_bucket_path, "dataset/")
#data_local = os.path.join(base_local_path, "dataset/") 
#input_data = InputData(obs_path=obs_path, local_path=data_local, is_local_source=False)

# 形式3,数据在Notebook中,且是一个目录,一般是使用SFS挂载磁盘的场景
#obs_path = os.path.join(base_bucket_path, "dataset-local/")
#data_local = os.path.join(base_local_path, "dataset/") 
#input_data = InputData(obs_path=obs_path, local_path=data_local, is_local_source=True)

参数解释:

  • is_local_source:可选参数,默认为False,指定训练数据的保存位置。
    • False:训练数据保存在参数obs_path指定的位置中;
    • True:训练数据保存在notebook中,由local_path指定。
  • obs_path:obs地址。根据is_local_source值的变化,有不同的含义。
    • is_local_source=False,此时是必选参数,代表训练数据位置,支持文件夹和压缩文件。
    • is_local_source=True,此时是可选参数。如果是在开发环境中进行本地训练,则该参数不会起作用。如果要将训练作业提交到远程,则开始训练时会将开发环境中的训练数据压缩并上传到该位置,不可重复上传。
  • local_path:必选参数,Notebook中的路径。用户的训练脚本需要从该目录中读取数据,完成训练任务。根据is_local_source值的变化,有不同的含义。
    • is_local_source=True,此时代表训练数据位置,仅支持文件夹。
    • is_local_source=False,训练过程中SDK会帮助用户将数据下载到该位置,如果训练数据是压缩文件,下载完成后会进行解压缩。

3、准备训练脚本

from modelarts.train_params import TrainingFiles
code_dir = os.path.join(base_local_path, "train/") 

# 这里提前将训练脚本放在了obs中,实际上训练脚本可以是任何来源,只要能够放到Notebook里边就行
session.obs.download_file(os.path.join(base_bucket_path, "train/test-pytorch.py"), code_dir)
training_file = TrainingFiles(code_dir=code_dir, boot_file="test-pytorch.py", obs_path=base_bucket_path + 'train/')

参数解释:

  • code_dir:必选参数,训练脚本所在的目录。在训练任务调测的情况下,必须是notebook中的目录,不能是OBS目录。
  • boot_file:必选参数,训练启动文件路径,路径格式为基于code_dir目录的相对路径,如实例代码中boot_file的完整路径为/home/ma-user/work/cifar10/train/test-pytorch.py,这里就只需要填写test-pytorch.py
  • obs_path:可选参数,一个OBS目录。仅在本地单机调试时不需要该参数,提交远程训练时必选,会将训练脚本压缩并上传到该路径。

4、准备训练输出,如果用户不需要将训练输出上传到OBS,可以省略这一步

from modelarts.train_params import OutputData
output = OutputData(local_path=os.path.join(base_local_path, "output/"), obs_path=os.path.join(base_bucket_path, 'output/'))
  • local_path:必选参数,一个notebook中的路径,训练脚本需要将输出的模型或其他数据保存在该目录下。
  • obs_path:必选参数,一个OBS目录。SDK会将local_path中的模型文件自动上传到这里。

5、查看训练支持的AI框架

from modelarts.estimatorV2 import Estimator
Estimator.get_framework_list(session)

参数session即是第一步初始化的数据。如果用户知道要使用的AI框架,可以略过这一步。

6、Estimator初始化

from modelarts.estimatorV2 import Estimator
parameters = []
parameters.append({"name": "data_url", "value": data_local})
parameters.append({"name": "output_dir", "value": os.path.join(base_local_path, "output/")}) 
parameters.append({"name": "epoc_num", "value": 2}) 
estimator = Estimator(session=session,
                      training_files=training_file,
                      outputs=[output],
                      parameters=parameters,
                      framework_type='PyTorch',  
                      train_instance_type='local', 
                      train_instance_count=1,
                      script_interpreter="/home/ma-user/anaconda3/envs/PyTorch-1.4/bin/python",
                      log_url=base_bucket_path + 'log/',
                      job_description='This is a image net train job')

参数解释:

  • session:必选参数,第一步中初始化的参数。
  • training_files:必选参数,第三步中初始化的训练文件。
  • outputs:可选参数,这里传入的是一个list,每个元素都是第四步中初始化的训练输出。
  • parameters:可选参数,一个list,每个元素都是一个字典,包含"name"和"value"两个字段,以"–name=value"的形式传递给训练启动文件。value支持字符串,整数,布尔等类型。对于布尔类型,建议用户在训练脚本中使用action='store_true’的形式来解析。
  • framework_type:必选参数,训练作业使用的AI框架类型,可参考步骤5查询的返回结果。
  • train_instance_type:必选参数,训练实例类型,这里指定’local’即为在notebook中进行训练。
  • train_instance_count:必选参数,训练使用的worker个数,单机训练时为1,训练作业只在当前使用的notebook中运行。
  • script_interpreter:可选参数,指定使用哪个python环境来执行训练任务,如果未指定,会默认使用当前的kernel。
  • log_url:可选参数,一个OBS地址,训练过程中,SDK会自动将训练的日志上传到该位置。但是如果训练任务运行在Ascend上,则是必选参数。
  • job_description:可选参数,训练任务的描述。

7、开始训练

estimator.fit(inputs=[input_data], job_name="cifar10-dis")

参数解释:

  • inputs:可选参数,一个list,每个元素都是第二步生成的实例。
  • job_name:可选参数,训练任务名,便于区分和记忆。

本地单机调试任务开始后,SDK会依次帮助用户完成以下流程:

  • 初始化训练作业,如果步骤2指定的训练数据在OBS上,这里会将数据下载到local_path中。
  • 执行训练任务,用户的训练代码需要将训练输出保存在步骤4中指定的local_path中。
  • 将训练任务得到的输出上传到步骤4指定的obs_path中,日志上传到第六步指定的log_url中。

8、多次调试

上一步执行过程中,训练脚本的日志会实时打印到控制台,如果用户的代码或者参数有误的话,可以很方便的看到。在Notebook中经过多次调试,得到想要的结果后,可以进行下一步。

9、查询训练支持的计算节点类型和最大个数

from modelarts.estimatorV2 import Estimator 
Estimator.get_spec_list(session=session)

参数session即是第一步初始化的数据。返回的是一个字典,其中flavors值是一个列表,描述了训练服务支持的所有规格的信息。每个元素中flavor_id是可直接用于远程训练任务的计算规格,max_num是该规格的最大节点数。如果用户知道要使用的计算规格,可以略过这一步。

10、提交远程训练作业

from modelarts.estimatorV2 import Estimator
parameters = []
parameters.append({"name": "data_url", "value": data_local})
parameters.append({"name": "output_dir", "value": os.path.join(base_local_path, "output/")}) 
parameters.append({"name": "epoch_num", "value": 2}) 
estimator = Estimator(session=session,
                      training_files=training_file,
                      outputs=[output],
                      parameters=parameters,
                      framework_type='PyTorch',  
                      train_instance_type='modelarts.vm.cpu.8u', 
                      train_instance_count=1,
                      script_interpreter="/home/ma-user/anaconda3/envs/PyTorch-1.4/bin/python",
                      log_url=base_bucket_path + 'log/',
                      job_description='This is a image net train job')
estimator.fit(inputs=[input_data], job_name="cifar10-dis")

在本地调测完成的基础上,只需要Estimator初始化时将参数train_instance_type修改为训练服务支持的规格即可(即第10步查询出来的flavor_id的值)。执行fit函数后,即可提交远程训练任务。
训练任务提交后,SDK会依次帮助用户完成以下流程:

  • 将训练脚本打包成zip文件,上传到步骤3中指定的obs_path中。
  • 当训练数据保存在Notebook中,则将其打包成zip文件并上传到指定的obs_path中。
  • 向ModelArts训练服务提交自定义镜像训练作业,使用的镜像为当前Notebook的镜像,这样保证了远程训练作业和在Notebook中的训练作业使用的运行环境一致。
  • 训练任务得到的输出上传到步骤4指定的obs_path中,日志上传到这一步log_url指定的位置中。

多机分布式调测

1、Session初始化,与单机调测相同

2、准备训练数据,唯一的不同在于obs_path参数是必选的

3、准备训练脚本

from modelarts.train_params import TrainingFiles
code_dir = os.path.join(base_local_path, "train/") 

# 这里提前将训练脚本放在了obs中,实际上训练脚本可以是任何来源,只要能够放到Notebook里边就行
session.obs.download_file(os.path.join(base_bucket_path, "train/test-pytorch.py"), code_dir)
training_file = TrainingFiles(code_dir=code_dir, boot_file="test-pytorch.py", obs_path=base_bucket_path + 'train/')

参数解释:

  • code_dir:必选参数,训练脚本所在的目录。在本地调试的情况下,必须是notebook目录,不能是OBS目录。
  • boot_file:必选参数,训练启动文件,在code_dir目录下。
  • obs_path:在多机分布式调测时必选参数,一个OBS目录,SDK会将notebook目录code_dir打包上传到obs_path中。

4、准备训练输出,与单机训练作业调试第四步相同

5、查看训练支持的AI框架,与单机训练作业第五步相同

6、Estimator初始化

from modelarts.estimatorV2 import Estimator
parameters = []
parameters.append({"name": "data_url", "value": data_local})
parameters.append({"name": "output_dir", "value": os.path.join(base_local_path, "output/")}) 
parameters.append({"name": "epoc_num", "value": 2})
# 启动脚本以parser.add_argument('--dist', action='store_true')的形式来接收该布尔类型的参数,如果要传入True,则以本行代码的形式传递;
parameters.append({"name": "dist"})
estimator = Estimator(session=session,
                      training_files=training_file,
                      outputs=[output],
                      parameters=parameters,
                      framework_type='PyTorch',  
                      train_instance_type='local', 
                      train_instance_count=2,
                      script_interpreter="/home/ma-user/anaconda3/envs/PyTorch-1.4/bin/python",
                      log_url=base_bucket_path + 'log/',
                      job_description='This is a image net train job')

参数解释:

  • session:必选参数,步骤1中初始化的参数。
  • training_files:必选参数,步骤3中初始化的训练文件。
  • outputs:可选参数,这里传入的是一个list,每个元素都是步骤4中初始化的训练输出。
  • parameters:可选参数,一个list,每个元素都是一个字典,包含"name"和"value"两个字段,以"–name=value"的形式传递给训练启动文件。value支持字符串,整数,布尔等类型。对于布尔类型,建议用户在训练脚本中使用action='store_true’的形式来解析。
  • framework_type:必选参数,训练作业使用的AI框架类型,可参考步骤5的返回结果。
  • train_instance_type:必选参数,训练实例类型,这里指定’local’即为本地训练。
  • train_instance_count:必选参数,训练使用的worker个数,分布式调测时为2,训练开始时SDK还会再创建一个Notebook,与当前的Notebook组成一个2节点的分布式调试环境。
  • script_interpreter:可选参数,指定使用哪个python环境来执行训练任务,如果未指定,会默认使用当前的kernel。
  • log_url:可选参数,一个OBS地址,本地训练过程中,SDK会自动将训练的日志上传到该位置;但是如果训练任务运行在Ascend上,则是必选参数。
  • job_description:可选参数,训练任务的描述。

7、开始训练

estimator.fit(inputs=[input_data], job_name="cifar10-dis")

参数解释:

  • inputs:可选参数,一个list,每个元素都是步骤2中生成的实例;
  • job_name:可选参数,训练任务名,便于区分和记忆。

本地分布式训练开始后,SDK会依次帮助用户完成以下流程:

  • 将训练脚本打包成zip文件,上传到步骤3中指定的obs_path中。
  • 如果训练数据保存在Notebook中,则将其打包成zip文件并上传到指定的obs_path中。
  • 创建一个附属Notebook,与当前使用的Notebook组成分布式训练的两个worker。
  • 初始化训练作业,将数据下载到local_path中。
  • 执行训练任务,用户的代码需要将训练输出保存在4指定的local_path中。
  • 将训练任务得到的输出上传到步骤4指定的obs_path中,日志上传到步骤7指定的log_url中。

8、多次调试,与单机调测时第8步相同

9、查询训练支持的工作节点类型,与单机调测时第9步相同。

10、提交远程训练作业

from modelarts.estimatorV2 import Estimator
parameters = []
parameters.append({"name": "data_url", "value": data_local})
parameters.append({"name": "output_dir", "value": os.path.join(base_local_path, "output/")}) 
parameters.append({"name": "epoc_num", "value": 2})
# 启动脚本以parser.add_argument('--dist', action='store_true')的形式来接收该布尔类型的参数,如果要传入True,则以本行代码的形式传递;
parameters.append({"name": "dist"})
estimator = Estimator(session=session,
                      training_files=training_file,
                      outputs=[output],
                      parameters=parameters,
                      framework_type='PyTorch',  
                      train_instance_type='modelarts.p3.large.public.distributed', 
                      train_instance_count=2,
                      script_interpreter="/home/ma-user/anaconda3/envs/PyTorch-1.4/bin/python",
                      log_url=base_bucket_path + 'log/',
                      job_description='This is a image net train job')
estimator.fit(inputs=[input_data], job_name="cifar10-dis-1")

Estimator初始化时与本地训练的区别在于参数train_instance_type,需要从步骤9得到的结果中选择一个;参数train_instance_count的值取决于第9步中的max_num。
训练任务提交后,SDK会依次帮助用户完成以下流程:

  • 将训练脚本打包成zip文件,上传到步骤3中指定的obs_path中;
  • 如果训练数据保存在Notebook中,则将其打包成zip文件并上传到指定的obs_path中;
  • 将训练作业提交到ModelArts训练服务中,训练作业会使用当前Notebook的镜像来执行训练作业;
  • 训练任务得到的输出上传到步骤4指定的obs_path中,日志上传到log_url指定的位置中。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。