文档

创建训练任务

更新时间:

完成准备工作后,您可以通过控制台、Python SDK或命令行提交DLC任务。本文为您介绍提交DLC任务的具体操作步骤。

前提条件

通过控制台创建

步骤一:进入新建任务页面

  1. 登录PAI控制台

  2. 在左侧导航栏单击工作空间列表,在工作空间列表页面中单击待操作的工作空间名称,进入对应工作空间内。

  3. 在工作空间页面的左侧导航栏选择模型开发与训练 > 分布式训练(DLC),在分布式训练任务页面中单击新建任务,进入新建任务页面。

步骤二:配置训练任务的参数

基本配置

基本信息区域,完成以下关键参数的配置:

参数

描述

节点镜像

工作节点的镜像。当前支持选择使用不同类型的镜像:

  • PAI官方镜像:由阿里云PAI产品提供的多种官方镜像,支持不同的Python版本及深度学习框架(包括TensorFlow、PyTorch等)。镜像列表及详情,请参见准备工作

  • 用户自定义镜像:可选择使用您添加到PAI的自定义镜像,选择前,您需要先将自定义镜像添加到PAI中,操作详情请参见自定义镜像

    说明
  • 镜像地址:支持配置您的自定义镜像、社区镜像以及PAI平台镜像地址。您需要在配置框中配置公网环境下可访问的Docker Registry Image URL。

    如果您配置的是私有镜像地址,您需要单击输入,并配置镜像仓库用户名镜像仓库密码,为私有镜像仓库授权。

    您也可以使用加速镜像,来提升模型训练速度。具体操作,请参见镜像加速

数据集配置

指定任务运行过程中,任务数据的存储位置,以扩展训练任务所需的存储空间。

此处需配置为前期已准备好的数据集。如何准备数据集,请参见准备工作

重要
  • 如果添加OSS或NAS类型的数据集,则需要授权PAI访问相关云产品OSS或NAS的权限,否则读取或写入数据失败。具体操作,请参见PAI访问云产品授权:OSS与NAS

  • 如果配置了CPFS类型的数据集,则需要配置专有网络,且选择的专有网络需要与CPFS一致。否则,提交的DLC训练任务会运行异常,表现为已出队。

代码配置

支持以下两种配置方式:

  • 在线配置

    指定任务代码文件的存储位置(代码仓库信息)。此处需配置为此前已准备好的代码配置。如何准备代码集,请参见步骤四:准备代码集

    说明

    由于DLC会将代码下载至指定工作路径,所以您需要有代码仓库的访问权限。

  • 本地上传

    单击image.png按钮后,按照界面操作指引上传代码配置。上传成功后,将挂载路径配置为容器内部的指定路径,例如/mnt/data

三方库配置

支持以下两种方式配置第三方库:

  • 三方库列表:直接在下方文本框中输入三方库。

  • requirements.txt文件目录:将第三方库写入requirements.txt文件中,在下方文本框中指定该requirements.txt文件的路径。

环境变量

提供额外的配置信息或参数。格式为Key:Value。最多支持配置20个环境变量。

执行命令

本任务需要执行的命令。支持Shell命令。例如,使用python -c "print('Hello World')"运行Python。

提交训练任务时,PAI会自动注入多个通用环境变量,您可以通过配置$环境变量名来获取指定环境变量的值。关于DLC默认提供的环境变量列表,请参见通用环境变量列表

说明
  • 如果配置了数据集,则训练结果默认输出到数据集挂载目录。

  • 如果您在执行命令时通过配置启动参数来指定了输出路径,则训练结果将会输出到指定的路径中。

资源配置

资源配置区域,完成以下关键参数的配置:

参数

描述

资源配额

您可以选择使用已准备的公共资源组、通用计算资源或灵骏智算资源。关于如何准备资源配额,请参见资源配额(Quota)功能介绍

说明

目前公共资源组支持运行的资源上限为GPU 2卡、CPU 8核。如果您在训练任务时使用的公共资源超出上限,请联系您的商务经理来提升资源上限。

优先级

资源配额选择通用计算资源或灵骏智算资源时,支持配置该参数。

表示同时运行的任务执行的优先级,取值范围为[1,9],其中1表示优先级最低。

框架

支持使用以下几种深度学习训练框架和训练工具,它们提供了丰富的功能和接口,方便您进行构建、训练和优化深度学习模型。

  • Tensorflow

  • PyTorch

  • ElasticBatch

  • XGBoost

  • OneFlow

  • MPIJob

说明

资源配额选择灵骏智算资源时,仅支持提交Tensorflow、PyTorch、ElasticBatch和MPIJob类型的任务。

任务资源

根据您选择的框架,支持配置Worker节点、PS节点、Chief节点、Evaluator节点、GraphLearn节点。

  • 使用公共资源组

    支持配置以下参数:

    • 节点数量:运行DLC任务的节点数量。

    • 资源规格:您可以单击image.png按钮来选择资源规格。关于资源规格的费用详情,请参见通用计算资源(DSW/DLC)计费说明

    • 竞价实例:您可以选中竞价实例复选框,使用竞价实例低成本运行任务。对于运行时间比较短的计算任务、可中断和继续训练的计算任务、对运行时长和连续性要求不高的任务,建议选择使用竞价实例,可节约资源成本。具体操作实践,请参见使用竞价实例

      说明

      如果您需要使用阿里云的竞价实例,您可以先提交工单,申请添加竞价实例使用白名单。

  • 使用通用计算资源或灵骏智算资源

    各类节点支持配置的参数项一致,均包含节点数量CPU(核数)GPU(卡数)内存(GB)共享内存(GiB)等配置项。

自动容错

资源配置区域,打开自动容错开关后,系统将提供作业检测和控制能力,能够及时检测训练任务算法层面的报错,并规避错误,从而提升GPU的利用率。更详细的配置说明,请参见AIMaster:弹性自动容错引擎

健康检测

资源配置区域,打开健康检测开关,健康检测会对参与训练的资源进行全面检测,自动隔离故障节点,并触发后台自动化运维流程,有效减少任务训练初期遇到问题的可能性,提升训练成功率。具体操作,请参见SanityCheck:算力健康检测

说明

仅基于灵骏智算资源提交的训练任务支持开启健康检测功能。

高级配置

框架PyTorch类型的任务时,支持通过高级配置提高训练灵活性,或满足一些特定的训练场景。

  • 配置要求:

    • 需配置为使用半角逗号(,)分隔的一组字符串形式,其中每个字符串都符合key=value的形式。

    • 其中key为当前支持的高级参数,value需配置为对应参数的取值。

    • 当前支持的高级参数列表和取值说明请参见附录1:高级参数列表

  • 典型场景与配置示例:

    • 场景:

      通过使用高级配置参数,可以实现Worker之间的网络互通,从而实现更灵活的训练方法。例如,可以利用额外开放的端口,在DLC容器中启动像Ray这样的框架,并与PyTorch配合进行更高级的分布式训练。

    • 配置示例:

      createSvcForAllWorkers=true,customPortNumPerWorker=100

      后续,您可以通过JOB_NAMECUSTOM_PORTS环境变量获取到域名和可用端口号,即可拉起并连接到像Ray之类的框架。

最长运行时长

您可以设置任务运行的最长时长,在完成配置后,超过该时长的任务将停止运行。默认为30天。

实例保留时长

配置执行成功或失败的任务的保留时长。超过该时长的任务将被删除。

重要

DLC任务删除后无法恢复,请谨慎操作。

专有网络配置

资源组选择公共资源组时,支持配置该参数。

  • 不配置专有网络,将使用公网连接。由于公网连接的带宽有限,可能导致任务执行过程中出现卡顿或无法正常进行的情况。

  • 配置专有网络,以确保充足的网络带宽和更稳定的性能。

    选择当前地域可用的专有网络,并选择对应的交换机与安全组。配置完成后,任务运行的集群将能够直接访问此专有网络内的服务,并使用此处选择的安全组进行安全访问限制。

    重要
    • 当前运行DLC任务时,需保障任务资源组实例、数据集存储(OSS)在同一地域的VPC网络环境中,且与代码仓库的网络是连通状态。

    • 如果数据集配置选择CPFS类型的数据集,需要配置专有网络,且选择的专有网络需要与CPFS一致。否则提交的DLC训练任务会运行异常,表现为已出队。

步骤三:提交训练任务

单击提交,训练任务创建成功。您可以在分布式训练任务列表中,单击任务名称进入任务详情页面查看当前任务的执行状态。关于DLC任务执行状态详情,请参见附录2:DLC任务执行状态

通过SDK或命令行创建

使用Python SDK

步骤一:安装Python SDK

  • 安装工作空间SDK。

    pip install alibabacloud_aiworkspace20210204==3.0.1
  • 安装DLC SDK。

    pip install alibabacloud_pai_dlc20201203==1.4.0

步骤二:提交任务

使用公共资源组提交任务

创建并提交任务的具体调用代码如下所示。

#!/usr/bin/env python3

from __future__ import print_function

import json
import time

from alibabacloud_tea_openapi.models import Config
from alibabacloud_credentials.client import Client as CredClient
from alibabacloud_pai_dlc20201203.client import Client as DLCClient
from alibabacloud_pai_dlc20201203.models import (
    ListJobsRequest,
    ListEcsSpecsRequest,
    CreateJobRequest,
    GetJobRequest,
)

from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient
from alibabacloud_aiworkspace20210204.models import (
    ListWorkspacesRequest,
    CreateDatasetRequest,
    ListDatasetsRequest,
    ListImagesRequest,
    ListCodeSourcesRequest
)


def create_nas_dataset(client, region, workspace_id, name,
                       nas_id, nas_path, mount_path):
    '''创建NAS的数据集。
    '''
    response = client.create_dataset(CreateDatasetRequest(
        workspace_id=workspace_id,
        name=name,
        data_type='COMMON',
        data_source_type='NAS',
        property='DIRECTORY',
        uri=f'nas://{nas_id}.{region}{nas_path}',
        accessibility='PRIVATE',
        source_type='USER',
        options=json.dumps({
            'mountPath': mount_path
        })
    ))
    return response.body.dataset_id


def create_oss_dataset(client, region, workspace_id, name,
                       oss_bucket, oss_endpoint, oss_path, mount_path):
    '''创建OSS数据集。
    '''
    response = client.create_dataset(CreateDatasetRequest(
        workspace_id=workspace_id,
        name=name,
        data_type='COMMON',
        data_source_type='OSS',
        property='DIRECTORY',
        uri=f'oss://{oss_bucket}.{oss_endpoint}{oss_path}',
        accessibility='PRIVATE',
        source_type='USER',
        options=json.dumps({
            'mountPath': mount_path
        })
    ))
    return response.body.dataset_id



def wait_for_job_to_terminate(client, job_id):
    while True:
        job = client.get_job(job_id, GetJobRequest()).body
        print('job({}) is {}'.format(job_id, job.status))
        if job.status in ('Succeeded', 'Failed', 'Stopped'):
            return job.status
        time.sleep(5)
    return None


def main():

    # 请确认您的主账号已授权DLC,且拥有足够的权限。
    region_id = 'cn-hangzhou'
    # 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
    # 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
    # 本示例通过Credentials SDK默认从环境变量中读取AccessKey,来实现身份验证为例。
    cred = CredClient()

    # 1. create client;
    workspace_client = AIWorkspaceClient(
        config=Config(
            credential=cred,
            region_id=region_id,
            endpoint="aiworkspace.{}.aliyuncs.com".format(region_id),
        )
    )

    dlc_client = DLCClient(
         config=Config(
            credential=cred,
            region_id=region_id,
            endpoint='pai-dlc.{}.aliyuncs.com'.format(region_id),
         )
    )

    print('------- Workspaces -----------')
    # 获取工作空间列表。您也可以在参数workspace_name中填入您创建的工作空间名。
    workspaces = workspace_client.list_workspaces(ListWorkspacesRequest(
        page_number=1, page_size=1, workspace_name='',
        module_list='PAI'
    ))
    for workspace in workspaces.body.workspaces:
        print(workspace.workspace_name, workspace.workspace_id,
              workspace.status, workspace.creator)

    if len(workspaces.body.workspaces) == 0:
        raise RuntimeError('found no workspaces')

    workspace_id = workspaces.body.workspaces[0].workspace_id

    print('------- Images ------------')
    # 获取镜像列表。
    images = workspace_client.list_images(ListImagesRequest(
        labels=','.join(['system.supported.dlc=true',
                         'system.framework=Tensorflow 1.15',
                         'system.pythonVersion=3.6',
                         'system.chipType=CPU'])))
    for image in images.body.images:
        print(json.dumps(image.to_map(), indent=2))

    image_uri = images.body.images[0].image_uri

    print('------- Datasets ----------')
    # 获取数据集。
    datasets = workspace_client.list_datasets(ListDatasetsRequest(
        workspace_id=workspace_id,
        name='example-nas-data', properties='DIRECTORY'))
    for dataset in datasets.body.datasets:
        print(dataset.name, dataset.dataset_id, dataset.uri, dataset.options)

    if len(datasets.body.datasets) == 0:
        # 当前数据集不存在时,创建数据集。
        dataset_id = create_nas_dataset(
            client=workspace_client,
            region=region_id,
            workspace_id=workspace_id,
            name='example-nas-data',
            # Nas文件系统ID。
            # 通用型NAS:31a8e4****。
            # 极速型NAS:必须以extreme-开头,例如extreme-0015****。
            # CPFS:必须以cpfs-开头,例如cpfs-125487****。
            nas_id='***',
            nas_path='/',
            mount_path='/mnt/data/nas')
        print('create dataset with id: {}'.format(dataset_id))
    else:
        dataset_id = datasets.body.datasets[0].dataset_id

    print('------- Code Sources ----------')
    # 获取代码集列表。
    code_sources = workspace_client.list_code_sources(ListCodeSourcesRequest(
        workspace_id=workspace_id))
    for code_source in code_sources.body.code_sources:
        print(code_source.display_name, code_source.code_source_id, code_source.code_repo)

    print('-------- ECS SPECS ----------')
    # 获取DLC的节点规格列表。
    ecs_specs = dlc_client.list_ecs_specs(ListEcsSpecsRequest(page_size=100, sort_by='Memory', order='asc'))
    for spec in ecs_specs.body.ecs_specs:
        print(spec.instance_type, spec.cpu, spec.memory, spec.memory, spec.gpu_type)

    print('-------- Create Job ----------')
    # 创建DLC作业。
    create_job_resp = dlc_client.create_job(CreateJobRequest().from_map({
        'WorkspaceId': workspace_id,
        'DisplayName': 'sample-dlc-job',
        'JobType': 'TFJob',
        'JobSpecs': [
            {
                "Type": "Worker",
                "Image": image_uri,
                "PodCount": 1,
                "EcsSpec": ecs_specs.body.ecs_specs[0].instance_type,
                "UseSpotInstance": False,
            },
        ],
        "UserCommand": "echo 'Hello World' && ls -R /mnt/data/ && sleep 30 && echo 'DONE'",
        'DataSources': [
            {
                "DataSourceId": dataset_id,
            },
        ],
    }))
    job_id = create_job_resp.body.job_id

    wait_for_job_to_terminate(dlc_client, job_id)

    print('-------- List Jobs ----------')
    # 获取DLC的作业列表。
    jobs = dlc_client.list_jobs(ListJobsRequest(
        workspace_id=workspace_id,
        page_number=1,
        page_size=10,
    ))
    for job in jobs.body.jobs:
        print(job.display_name, job.job_id, job.workspace_name,
              job.status, job.job_type)
    pass


if __name__ == '__main__':
    main()

使用通用计算资源提交任务

  1. 登录PAI控制台

  2. 按照下图操作指引,在工作空间列表页面查看您所在的工作空间ID。image.png

  3. 按照下图操作指引,在通用计算资源页面查看您的专有资源组的资源配额ID。image.png

  4. 使用以下代码创建并提交任务。可使用的公共镜像列表,详情请参见步骤二:准备镜像

    from alibabacloud_pai_dlc20201203.client import Client
    from alibabacloud_credentials.client import Client as CredClient
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_pai_dlc20201203.models import (
        CreateJobRequest,
        JobSpec,
        ResourceConfig, GetJobRequest
    )
    
    # 初始化一个Client,用来访问DLC的API。
    region = 'cn-hangzhou'
    # 阿里云账号AccessKey拥有所有API的访问权限,建议您使用RAM用户进行API访问或日常运维。
    # 强烈建议不要把AccessKey ID和AccessKey Secret保存到工程代码里,否则可能导致AccessKey泄露,威胁您账号下所有资源的安全。
    # 本示例通过Credentials SDK默认从环境变量中读取AccessKey,来实现身份验证为例。
    cred = CredClient()
    client = Client(
        config=Config(
            credential=cred,
            region_id=region,
            endpoint=f'pai-dlc.{region}.aliyuncs.com',
        )
    )
    
    # 声明任务的资源配置,关于镜像选择可以参考文档中公共镜像列表,也可以传入自己的镜像地址。
    spec = JobSpec(
        type='Worker',
        image=f'registry-vpc.cn-hangzhou.aliyuncs.com/pai-dlc/tensorflow-training:1.15-cpu-py36-ubuntu18.04',
        pod_count=1,
        resource_config=ResourceConfig(cpu='1', memory='2Gi')
    )
    
    # 声明任务的执行内容。
    req = CreateJobRequest(
            resource_id='<替换成您自己的资源配额ID>',
            workspace_id='<替换成您自己的WorkspaceID>',
            display_name='sample-dlc-job',
            job_type='TFJob',
            job_specs=[spec],
            user_command='echo "Hello World"',
    )
    
    # 提交任务。
    response = client.create_job(req)
    # 获取任务ID。
    job_id = response.body.job_id
    
    # 查询任务状态。
    job = client.get_job(job_id, GetJobRequest()).body
    print('job status:', job.status)
    
    # 查看任务执行的命令。
    job.user_command

使用命令行

步骤一:下载客户端并执行用户认证

根据您使用的操作系统下载Linux 64或Mac版本的客户端工具并完成用户认证,具体操作请参见准备工作

步骤二:提交任务

  1. 登录PAI控制台

  2. 按照下图操作指引,在工作空间列表页面查看您所在的工作空间ID(WorkspaceID)。

    image.png

  3. 按照下图操作指引,在通用计算资源页面查看您的资源配额ID。

    image.png

  4. 参考以下文件内容准备参数文件 ./tfjob.params。关于命令行使用方式,详情请参见命令列表

    name=test_cli_tfjob_001
    workers=1
    worker_cpu=4
    worker_gpu=0
    worker_memory=4Gi
    worker_shared_memory=4Gi
    worker_image=registry-vpc.cn-beijing.aliyuncs.com/pai-dlc/tensorflow-training:1.12.2PAI-cpu-py27-ubuntu16.04
    command=echo good && sleep 120
    resource_id=<您的资源配额ID> # 如果您使用公共资源组,该参数允许为空。
    workspace_id=<您的WorkspaceID>
  5. 使用以下代码示例传入params_file参数提交任务,可以将DLC任务提交到指定的工作空间和资源组。

    dlc submit tfjob --job_file  ./tfjob.params
  6. 使用以下代码查看您提交的DLC任务。

    dlc get job <jobID>

相关文档

提交训练任务后,您可以执行以下操作:

  • 您可关注任务运行状态,也可在任务运行后查看任务运行的账单明细,账单明细查看请参见账单明细

  • 查看任务基本信息、资源视图和操作日志。具体操作,请参见查看训练详情

  • 管理任务,包括克隆、停止和删除任务等。具体操作,请参见管理训练任务

  • 通过Tensorboard查看结果分析报告。具体操作,请参见Tensorboard

  • 设置DLC或资源配额的监控与报警。具体操作,请参见监控与报警

附录1:高级参数列表

参数(key)

参数说明

参数取值(value)

createSvcForAllWorkers

是否允许worker间网络互通。

  • 若为true,则允许所有PyTorch worker之间网络互通。

  • 若为false或未配置,则默认仅有master可以被访问。

打开后,每个worker的域名即为worker名,如dlcxxxxx-master-0,后续会通过环境变量JOB_NAME将作业名称(dlcxxxxx)传到worker内部,之后您即可得出您需要访问的具体worker的域名。

truefalse

customPortList

允许用户定义每个worker上开放的网络端口,可与createSvcForAllWorkers配合使用实现worker间的网络互通。

若未配置,则默认仅有master上开放23456号端口。因此也请注意在该自定义端口列表中避开23456号端口。

重要

该参数与customPortNumPerWorker互斥,请不要同时设置。

分号分隔的一组字符串,其中每个字符串为一个端口号,或由短横线连接的一个端口范围,如10000;10001-10010(将会转化为从10000到10010连续的11个端口号)

customPortNumPerWorker

允许用户请求为每个worker开放若干个网络端口,可与createSvcForAllWorkers配合使用实现worker间的网络互通。

若未配置,则默认仅有master上开放23456号端口。DLC会根据参数定义的端口数目,为worker随机分配端口,具体分配的端口号会通过环境变量CUSTOM_PORTS传到worker内部供您查询,格式为分号分隔的一组端口号。

重要

该参数与customPortList互斥,请不要同时设置。

整数(最大为65536)

附录2DLC任务执行状态

目前DLC的任务执行状态顺序为创建中 -> 排队中 -> 已出队 -> 运行中 -> 已成功、已失败或已停止

  • 当任务执行状态为已出队时如何处理?

    • DLC任务执行状态为已出队时,表示任务已经开始进行资源调度,大约需要等待5分钟,任务执行状态会变为运行中

    • 如果任务长时间处于已出队状态,可能是因为您创建的分布式训练任务配置了CPFS类型的数据集,但没有配置专有网络导致的。您需要重新创建分布式训练任务,配置CPFS类型数据集并配置专有网络,且选择的专有网络需要与CPFS一致。

  • 当任务执行状态为已失败时如何处理?

    您可以在任务详情页面中,将鼠标悬浮到任务执行状态后的image.png,或者查看实例操作日志,来初步定位任务执行失败的原因。

  • 本页导读 (1)
文档反馈