
# 使用SDK调测多机分布式训练作业
代码中涉及到的OBS路径，请用户替换为自己的实际OBS路径。
代码是以PyTorch为例编写的，不同的AI框架之间，整体流程是完全相同的，仅需修改[7]和[11]中的 framework_type参数值即可，例如：MindSpore框架，此处framework_type=Ascend-Powered-Engine。
1. Session初始化，与[使用SDK调测单机训练作业中的1](https://support.huaweicloud.com/sdkreference-modelarts/modelarts-distributed-0003.html#ZH-CN_TOPIC_0000001402154592__li10128121814566)相同。
2. 准备训练数据，与[使用SDK调测单机训练作业中的2](https://support.huaweicloud.com/sdkreference-modelarts/modelarts-distributed-0003.html#ZH-CN_TOPIC_0000001402154592__li15983350144713)相同，唯一的不同在于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. 准备训练输出，与单机训练作业调试[4]相同。
5. 查看训练支持的AI框架，与单机训练作业调试[5]相同。
6. 保存当前Notebook为新镜像，与单机训练作业调试[9]相同。
7. 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：可选参数，训练任务的描述。
   
   
   
   

8. 开始训练。 
   ```
   estimator.fit(inputs=[input_data], job_name="cifar10-dis")
   ```
   参数解释：
   - inputs：可选参数，一个list，每个元素都是步骤2中生成的实例；
   
   - job_name：可选参数，训练任务名，便于区分和记忆。
   
   
   本地分布式训练任务开始后，SDK会依次帮助用户完成以下流程：
   1. 将训练脚本打包成zip文件，上传到[3]中指定的obs_path中。
   
   2. 如果训练数据保存在Notebook中，则将其打包成zip文件并上传到指定的obs_path中。
   
   3. 创建一个附属Notebook，与当前使用的Notebook组成分布式训练的两个worker。
   
   4. 初始化训练作业，将数据下载到local_path中。
   
   5. 执行训练任务，用户的代码需要将训练输出保存在[4]指定的local_path中。
   
   6. 将训练任务得到的输出上传到[4]指定的obs_path中，日志上传到[7]指定的log_url中。
   
   
   
   

9. 多次调试，与单机调测时[8](https://support.huaweicloud.com/sdkreference-modelarts/modelarts-distributed-0003.html#ZH-CN_TOPIC_0000001402154592__li13644236791)作用相同。
10. 查询训练支持的工作节点类型，与单机调测时[9](https://support.huaweicloud.com/sdkreference-modelarts/modelarts-distributed-0003.html#ZH-CN_TOPIC_0000001402154592__li1688127162517)相同。
11. 提交远程训练作业。
    
    ```
    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，需要从[10]得到的结果中选择一个；参数train_instance_count的值取决于第10步中的max_num。
    训练任务提交后，SDK会依次帮助用户完成以下流程：
    1. 将训练脚本打包成zip文件，上传到[3]中指定的obs_path中；
    
    2. 如果训练数据保存在Notebook中，则将其打包成zip文件并上传到指定的obs_path中；
    
    3. 将训练作业提交到ModelArts训练服务中，训练作业会使用当前Notebook的镜像来执行训练作业；
    
    4. 训练任务得到的输出上传到[4]指定的obs_path中，日志上传到log_url指定的位置中。
       在这一步中需要注意的一个问题：
       如果用户在自己的训练脚本中要创建新的目录或文件，请在以下几种目录中创建：
       （1）/home/ma-user/work；
       （2）/cache；
       （3）inputs或者outputs中指定的local_path，如在[2]中初始化InputData时，填写了local_path="/home/ma-user/work/xx/yy/"，则在该目录下也可以创建新目录或文件；
       
    
    
    
    
 
