直接使用
请打开使用Python SDK管理DSW实例,并点击右上角 “ 在DSW中打开” 。
概述
PAI-DSW(Data Science Workshop)是为数据科学团队和算法团队们量身定制的云端机器学习交互式开发IDE,使读取数据、开发、训练及部署模型更简单高效且安全。
您可以在PAI的Web控制台使用DSW的同时,还可以使用OpenAPI和对应的Python SDK来使用DSW,基于代码来管理您的DSW实例。本文将介绍如何使用DSW Python SDK(底层封装了对OpenAPI的调用)来创建、停止、启动、删除实例,以及保存环境(镜像)等。
您可以参考PAI-DSW快速入门来获取更多与DSW和PAI相关的功能使用和最佳实践。
前提条件
- 开通PAI-DSW,并完成授权,详情请参见DSW 开通与授权。
- [可选] 购买专有资源组,目前是邀测期间,如有需要请联系我们。
- 已获取阿里云账户的AccessKey ID和AccessKey Secret,详情请参见获取AccessKey。
步骤一:安装Python SDK
- 安装AI工作空间SDK
- 安装PAI-DSW的SDK
- 安装专有资源组管理的SDK(可选)
!pip install alibabacloud-aiworkspace20210204 -U -q !pip install alibabacloud_pai_dsw20220101 -U -q # 安装专有资源组相关功能的SDK,在正式发布到pypi之前,请使用如下地址: !pip install https://sdk-portal-us-prod.oss-accelerate.aliyuncs.com/downloads/u-b8602de7-c468-436c-8a02-2eca4a30d376-python-paistudio.zip -U -q
步骤二:初始化Python SDK中的Client对象
PAI的Python SDK都是标准的阿里云SDK,每一个子产品都有自己的安装包和Package;但是每一个Package的使用方法是一致的:
- 从client Package中import 对应子产品(阿里云服务)的Client类
- 从modesl Package中import 需要使用的各种request/response类
- 使用阿里云AK来初始化Client对象,并且指定Region
- 调用Cliend对象中的各种方法,每个方法对应一个OpenAPI,简单参数是python原子类型,复杂参数是models Package中的各种request/response对象
# Import各种Client和Models类 from alibabacloud_pai_dsw20220101.client import Client as DSWClient from alibabacloud_aiworkspace20210204.client import Client as AIWorkspaceClient from alibabacloud_aiworkspace20210204.models import (ListWorkspacesRequest, ListImagesRequest, ListDatasetsRequest, ListResourcesRequest) from alibabacloud_pai_dsw20220101.models import (ListInstancesRequest, ListEcsSpecsRequest, CreateInstanceRequest, StopInstanceRequest, CreateInstanceShutdownTimerRequest, CreateInstanceRequestRequestedResource, CreateInstanceSnapshotRequest, ListInstanceSnapshotRequest, GetInstanceMetricsRequest, CreateIdleInstanceCullerRequest) from alibabacloud_tea_openapi.models import Config as AliyunConfig from alibabacloud_tea_openapi.client import TeaException from alibabacloud_paistudio20220112.models import (ListResourceGroupMachineGroupsRequest) from alibabacloud_paistudio20220112.client import Client as StudioClient
# 构造各个子产品(也就是不同子产品的Service)的Client对象 # 准备Region和阿里云账户的AK region_id = 'cn-beijing' access_key_id = '**你的access_key_id**' access_key_secret = '**你的access_key_secret**' import os.path config_path="/mnt/data/pai.config" if os.path.isfile(config_path): with open(config_path) as f: access_key_id = f.readline().strip('\n') access_key_secret = f.readline().strip('\n') # create client workspace_client = AIWorkspaceClient( AliyunConfig(access_key_id=access_key_id, access_key_secret=access_key_secret, region_id=region_id, endpoint='aiworkspace.{}.aliyuncs.com'.format(region_id))) dsw_client = DSWClient( AliyunConfig(access_key_id=access_key_id, access_key_secret=access_key_secret, region_id=region_id, endpoint='pai-dsw.{}.aliyuncs.com'.format(region_id))) # 只有预付费资源组才需要Studio Client studio_client = StudioClient(AliyunConfig(access_key_id=access_key_id, access_key_secret=access_key_secret, region_id = region_id)) # 定义一个用来显示DSW实例信息的Helper函数 def show_instance(instance_id): instance = dsw_client.get_instance(instance_id=instance_id).body print(instance.status, instance.instance_name, instance.ecs_spec, instance.accumulated_running_time_in_ms)
步骤三:准备工作 - 工作空间中的AI资产
使用PAI-DSW经常涉及到OSS、NAS、CPFS、容器镜像、专有资源组等信息,为了方便管理,PAI平台把这些资源统一叫做“AI资产”,并且使用工作空间进行组织,方便复用和权限管理。工作空间相关的功能可以使用workspace_client对象进行查询和操作。
准备AI工作空间(必须)
工作空间是PAI的顶层概念,为团队提供统一的计算资源管理及人员权限管理能力,目的就是为AI开发者提供支持团队协作的全流程开发工具及AI资产管理能力。
PAI平台在开通时,会自动给用户 创建默认的工作空间
# 查询一个已经存在的工作空间(Workspace)的属性和ID workspace_name = '**已有的AI工作空间名称**' # 获取工作空间列表。 workspaces = workspace_client.list_workspaces(ListWorkspacesRequest( page_number=1, page_size=10, workspace_name=workspace_name, # 模糊匹配,如果不指定名字,则返回所有workspace )) if len(workspaces.body.workspaces) == 0: raise RuntimeError('请指定正确的workspace_name') for workspace in workspaces.body.workspaces: print(workspace.workspace_name, workspace.workspace_id, workspace.status, workspace.creator) # 使用查询到的第一个结果作为后续操作的workspace,您可以按需切换或者直接指定一个字符串类型的ID workspace_id = workspaces.body.workspaces[0].workspace_id
准备镜像(必须)
创建DSW实例时需要明确指定某个镜像作为AI的开发环境,PAI-DSW支持选择使用不同类型的镜像:
- 社区镜像:由社区提供的标准镜像,不同的镜像的详情请参见社区镜像版本详情。
- PAI平台镜像:由阿里云PAI产品提供的多种官方镜像,支持不同的资源类型、Python版本及深度学习框架TensorFlow和PyTorch,镜像列表请参见公共镜像列表。
- 用户自定义镜像:可选择使用您添加到PAI的自定义的镜像,选择前,您需要先将自定义镜像添加到PAI中,操作详情请参见查看并添加镜像。也可以通过DSW的“保存镜像”功能来自定义镜像,详情见本文后续章节。
- 镜像地址:可选择使用您自定义的镜像,选择镜像地址后,您需要在配置框中配置公网环境下可访问的Docker Registry Image URL。
可以使用工作空间的list_images函数来查询PAI内置和用户自定义的镜像,参数labels可以用来做各种过滤。如果您对labels不熟悉,可以不指定labels来获取所有镜像的所有labels,然后再进行挑选。
# 获取镜像列表,可以用labels来做过滤 images = workspace_client.list_images(ListImagesRequest( page_size=100, #workspace_id=workspace_id, #不指定workspace_id则意味着查询所有PAI平台内置的镜像 labels=','.join(['system.supported.dsw=true', #'system.framework=tensorflow', #指定pytorch或者tensorflow 'system.pythonVersion=3.6', ]), verbose=True # verbose=True会列出更加详细的信息,包括labels )) # 可以查看所有可用的镜像 for image in images.body.images: print(image.image_id, image.image_uri) # 获得用于提交任务所使用的镜像,这里取第一个作为示例 image_uri = images.body.images[0].image_uri print('image_uri', image_uri)
准备节点规格(针对按量付费是必须的操作)
为训练任务,准备计算节点的规格,详细的规格列表和费用请参见PAI-DSW计费说明。
# 获取DSW的节点规格列表。 try: resp = dsw_client.list_ecs_specs(ListEcsSpecsRequest(accelerator_type='CPU', # CPU 或者 GPU )).body except TeaException as t: print("List ECS Specs failed:", t.message) else: for spec in resp.ecs_specs: print(spec.instance_type + ", CPU: " + str(spec.cpu) + ", Memory: " + str(spec.memory)) # 获得用于提交任务的节点规格 ecs_spec = resp.ecs_specs[0].instance_type print('Selected ecs_spec:', ecs_spec)
准备数据集(推荐必须)
AI开发工作离不开数据访问,无论是训练数据或者是代码或者是配置文件。PAI-DSW支持挂载OSS或者NAS到实例中,做作为“本地文件系统”访问。而为了能够在DSW中挂载这些数据,需要提前在工作空间中创建对应的“数据集”对象,并且设置相关属性。
DSW作为开发工具,需要编写代码或者脚本,为了方便这些文件的自动持久化,强烈建议挂载至少一个NAS文件系统作为工作目录,这样所有的文件操作就自动被持久化到NAS中。不推荐把OSS挂载为文件系统作为工作目录,因为OSS是Object Store,不是分布式文件系统,不支持随机读写;挂载OSS到实例中是为了更加方便的访问训练数据或者保存模型,而不是用于编写代码。
dataset_name = 'example-nas-data' nas_id = '**已创建的nas的id' 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 # mouthPath是挂载到DSW或者DLC中的默认本地文件目录,可以在创建DSW实例或者提交DLC任务时Override掉 }) )) 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 # 查看已经创建的数据集 datasets = workspace_client.list_datasets(ListDatasetsRequest( workspace_id=workspace_id, # name=dataset_name, #不指定具体的dataset_name时,表示查询所有dataset data_source_types="NAS", # NAS或者OSS properties='DIRECTORY')) for dataset in datasets.body.datasets: print(dataset.name, dataset.dataset_id, dataset.uri, dataset.data_source_type, dataset.options) if len(datasets.body.datasets) == 0: # 当前数据集不存在时,创建数据集。 dataset_id = create_nas_dataset( client=workspace_client, region=region_id, workspace_id=workspace_id, name=dataset_name, nas_id=nas_id, nas_path='/', mount_path='/mnt/data/example-nas') print('create dataset with id: {}'.format(dataset_id)) else: dataset_id = datasets.body.datasets[0].dataset_id selected_dataset = workspace_client.get_dataset(dataset_id=dataset_id).body print('Selected dataset:', dataset_id, "name: ", selected_dataset.name)
步骤四:创建DSW实例
准备好创建DSW实例需要的资源和配置之后,可以创建实例了。关于接口的更多说明,请参见DSW API参考。
查询已有实例
# 查询指定workspace下的所有实例 instances = dsw_client.list_instances(ListInstancesRequest(workspace_id=workspace_id)) for ins in instances.body.instances: print('\t'.join([ins.instance_id, ins.instance_name, ins.status, ins.accelerator_type, ins.ecs_spec, str(int(ins.accumulated_running_time_in_ms / 1000.0/60.0))]) )
创建后付费实例(按量付费)
在Web控制中,创建到公共资源组中的实例都是后付费实例,也被称为按量付费,根据实例的运行时长来计费。可以随时停止实例,在停止阶段不收取任何费用。
# 创建后付费实例 request = CreateInstanceRequest(instance_name="Test_From_SDK_1", ecs_spec=ecs_spec, workspace_id=workspace_id, #image_id='', #可以指定工作空间中的镜像的ID,但是与image_url只能指定一个参数 image_url=image_uri) try: ins_resp = dsw_client.create_instance(request) except TeaException as t: print('创建实例失败,错误消息:' + t.message) else: instance_id = ins_resp.body.instance_id print("Created Instance ID:", instance_id) show_instance(instance_id)
创建独占资源组作业(预付费)
独占资源组(目前也都是预付费资源组)是PAI推出的新功能,正在邀测阶段,如有需要,请联系PAI团队。在预付费资源组中的资源为用户独占,用户可以提交DLC任务或者DSW实例,并且指定任务或者实例的资源量。
# 获取工作空间中的云原生独占资源组,用于DLC或者DSW resp = workspace_client.list_resources(ListResourcesRequest( page_number=1, page_size=10, workspace_id=workspace_id, product_types='DLC' # 这里'DLC'代表“云原生资源组” )) # 提交DLC或者DSW到预付费资源组,需要获取资源组ID;资源组ID存于工作空间的资源Spec中的resourceGroupId字段 selected_resource_group_id = None for resource in resp.body.resources: cluster_type = resource.spec['clusterType'] if cluster_type == 'private': # 'private'代表 专有资源组, 'share'代表公共资源组(后付费) resource_group_id = resource.spec['resourceGroupId'] resource_group_name = resource.spec['resourceGroupName'] mgs = studio_client.list_resource_group_machine_groups(resource_group_id=resource_group_id, request=ListResourceGroupMachineGroupsRequest()).body print("resource group:", resource_group_id, resource_group_name) if len(mgs.machine_groups) < 1: print("资源组没有任何资源:", resource_group_name) else: for g in mgs.machine_groups: print(g.ecs_count, g.ecs_spec) # 这里相当于选取了最后一个有资源的Resource Group;可以按照自己的需要来选取 selected_resource_group_id = resource_group_id
# 创建专有资源组实例 if selected_resource_group_id is None: raise RuntimeError("请指定专有资源组ID") else: print("使用专有资源组创建DSW实例,ID:", selected_resource_group_id) requested_resource = CreateInstanceRequestRequestedResource(cpu=2, memory='4Gi') request = CreateInstanceRequest(instance_name="Test_From_SDK_ResourceGroup_1", resource_id=selected_resource_group_id, requested_resource=requested_resource, workspace_id=workspace_id, #image_id='', #可以指定工作空间中的镜像的ID,但是与image_url只能指定一个参数 image_url=image_uri) ) try: ins_resp = dsw_client.create_instance(request) except TeaException as t: print("Failed to create DSW Instance in private resource group. Error Message:", t.message) else: instance_id = ins_resp.body.instance_id print("Created Instance ID:", instance_id)
步骤五:管理实例
创建完实例之后,可以进行实例的管理:
- 停止
- 启动
- 保存环境(镜像)
- 设置定时关机
- 共享实例
查看实例状态
用我们的Helper方法来查看某个实例的状态。
show_instance(instance_id)
保存镜像(环境)
对运行中的实例,可以把当前环境保存为一个用户镜像仓库中的一个镜像,方便下次使用或者分享给团队其他人。在Web控制台中,实例列表的右边的按钮“保存镜像”提供同样的功能。在DSW中,我们用instance_snapshot来操作实例的镜像。
前提:用户开通ACR镜像仓库服务,并且准备好镜像仓库的namespace。
# 保存环境(镜像)到指定用户自己的Docker Registry;如果是同一个Region,请指定registry-vpc.{region}这样的内网地址。 to_save_image_url = 'registry-vpc.cn-beijing.aliyuncs.com/fengqi_dsw_test/dsw1:snapshot20220101' snapshot_request = CreateInstanceSnapshotRequest(image_url=to_save_image_url, snapshot_name="snap-2022-01-01") try: resp = dsw_client.create_instance_snapshot(instance_id=instance_id, request = snapshot_request) except TeaException as t: print("Failed to create snapshot. Reason:", t.message) show_instance(instance_id) else: snapshot_id = resp.body.snapshot_id print("Saved Snapshot ID:", snapshot_id, "The instance is:", resp.body.instance_id) # 查看刚保存的Snapshot try: resp2 = dsw_client.get_instance_snapshot(instance_id, snapshot_id) except TeaException as t: print("Failed to get snapshot. Reason:", t.message) else: print("Snapshot's imageID:", resp2.body.image_id, "image url:", resp2.body.image_url)
在工作空间中查看刚刚保存的镜像:
# 保存过的镜像也可以在工作空间中查看;在网页控制台的 "AI资产管理" -> "镜像" -> “用户自定义镜像”中也可以看到 resp = workspace_client.list_images(ListImagesRequest(labels='system.source=DSW,', workspace_id=workspace_id, page_size=10, page_number=1, verbose=True)) for i in resp.body.images: print(i.name, i.image_id, i.image_uri)
停止、启动和删除实例
# 停止一个实例, save_image参数可以指定是否保存当前环境到PAI仓库,使得下次打开继续使用。 # 如果设置save_image=True,停止实例会持续1~5分钟不等,取决于当前环境的size,此时镜像将会保存到PAI的后端,成为下次启动实例的基础镜像。 try: dsw_client.stop_instance(instance_id, StopInstanceRequest(save_image=False)) except TeaException as t: print("Failed to stop instance. Error:", t.message) else: print("Instance has been stopped.")
# 启动一个已经停止的实例。如果在停止实例是选择了保存镜像,那么启动的实例会使用上次保存的最新镜像。 try: dsw_client.start_instance(instance_id) except TeaException as t: print("Failed to start instance, Error Message:", t.message) # 显示最新状态 show_instance(instance_id)
# 删除实例,请谨慎操作,无法恢复! try: dsw_client.delete_instance(instance_id=instance_id) except TeaException as t: print("Failed to delete instance, Error Message:", t.message) else: print("Instance has been deleted. Instance ID:", instance_id)
设置定时关机
可以为每个正在运行的实例设置定时关机,DSW用ShutdownTimer来封装相关功能。
# 定时关机有两种设置方法:某个具体时间点关机或者倒计时。这里演示的是8个小时候后自动关机。 req= CreateInstanceShutdownTimerRequest(# due_time='2022-07-26T20:00:00Z', # 指定关机时间 remaining_time_in_ms= 1000 * 60 * 60 * 8) #指定倒计时时间,单位是毫秒 try: dsw_client.create_instance_shutdown_timer(instance_id, request=req) except TeaException as t: print("Failed to set sthudown timer. Reason:", t.message) else: instance = dsw_client.get_instance(instance_id=instance_id).body # 查看 关机倒计时的剩余分钟数 print("Remaining minutes:", instance.instance_shutdown_timer.remaining_time_in_ms/1000.0/60)
设置闲置实例自动关机
可以为每个正在运行的实例设置闲置自动关机策略,DSW用IdleInstanceCuller来封装相关功能。
# 创建指定实例的闲置自动关机策略,满足条件时将自动停止DSW实例。 # 一个DSW实例只支持创建一个闲置自动关机策略,同时低于指定的各个指标阈值,则判定实例为闲置状态。 # 如果指定实例已设定过闲置自动关机策略,请先调用 delete_idle_instance_culler API 将其删除。 req = CreateIdleInstanceCullerRequest(cpu_percent_threshold=30, # CPU利用率阈值,单位是百分比,取值1~100 #gpu_percent_threshold=10, # GPU实例可以指定GPU利用率阈值,单位是百分比,取值1~100 max_idle_time_in_minutes=60 # 闲置等待时间阈值,单位是分钟。如果闲置时长超过此值,将自动停止DSW实例。 ) try: dsw_client.create_idle_instance_culler(instance_id, request=req) except TeaException as t: print("Failed to create idleInstanceCuller. Reason:", t.message) else: instance = dsw_client.get_instance(instance_id=instance_id).body # 查看运行中实例的闲置时长,单位是分钟 print("Idle minutes:", instance.idle_instance_culler.idle_time_in_minutes)
# 删除指定实例的闲置自动关机策略 try: dsw_client.delete_idle_instance_culler(instance_id=instance_id) except TeaException as t: print("Failed to delete idleInstanceCuller, Error Message:", t.message) else: print("IdleInstanceCuller has been deleted. Instance ID:", instance_id)
获取实例指标
可以获取某个实例在某一段时间内的资源利用指标,如CPU、GPU、内存等
# metric_type可以有多个选项,如 # * GpuCoreUsage:GPU使用率 # * GpuMemoryUsage:GPU Memory使用率 # * CpuCoreUsage:CPU使用率 # * MemoryUsage:Memory使用率 # * NetworkInputRate:网络写入速率 # * NetworkOutputRate:网络写出速率 # * DiskReadRate:磁盘读取速率 # * DiskWriteRate:磁盘写入速率 metric_type = "CpuCoreUsage" start_time = "2022-08-29T04:10:30.781+08:00" end_time = "2022-09-01T04:10:30.781+08:00" time_step = "15m" request = GetInstanceMetricsRequest(metric_type=metric_type, start_time=start_time, end_time=end_time, time_step=time_step) try: response = dsw_client.get_instance_metrics(instance_id=instance_id, request=request) print("instance metrics:", response.body.pod_metrics) except TeaException as t: print("Failed to get metrics. Reason:", t.message)