APP下载

面向深度学习的分布式任务执行系统①

2021-08-02高国樑陈雷放刘一鸣

计算机系统应用 2021年7期
关键词:任务调度执行器日志

高国樑,陈雷放,刘一鸣

1(中国石油大学(华东) 计算机科学与技术学院,青岛 266580)

2(青岛农业大学 理学与信息科学学院,青岛 266109)

3(华北电力大学(保定) 电气与电子工程学院,保定 071003)

近年来,深度学习技术广泛应用在图像处理、语音识别等领域,极大地促进了人工智能的进步,对人类生活的改善有着重要意义.然而,深度学习实践并非一件易事,往往需要花费大量的时间和精力,因此,使深度学习变得尽可能“简单”显得尤为重要.深度学习托管平台可为深度学习实验任务提供全流程的管理服务,给深度学习实践带来了积极影响.结合深度学习平台项目的实际需求,本文设计和实现了分布式任务执行系统DTES (Distributed Task Execution System).DTES参照任务执行集群的实时监控数据选出当前压力最小的节点并向其发送执行请求,节点根据请求信息去获取任务所需数据,随后创建Docker 容器来执行该任务,同时回收任务执行期间的日志信息.此外,DTES 基于Spring Boot 框架实现,具有良好的稳定性和可扩展性.

1 研究背景

深度学习全流程托管平台是一个管理深度学习实验任务的网页应用系统.该平台提供了数据集管理、数据集标注、模型训练以及模型部署等服务,它将深度学习实验的所有流程全部集中到网页端进行,有效提升了研究效率.研究者首先将数据集上传到平台,接着对数据集进行标注,之后在平台中编写程序训练模型,最后将符合要求的模型导出部署.

本文结合深度学习平台的具体需要和深度学习实验的特性[1–3],提出了一种面向深度学习模型训练的分布式任务执行系统.

2 需求分析

需求分析是系统开发的基础,关系到开发工程的成败和软件产品的质量.本文提出的分布式任务执行系统主要应用于网页端深度学习模型训练,系统的主要功能有监控、任务调度、任务执行、日志管理等,具体如下.

(1)监控:包括对执行器节点的监控以及对任务的监控,其中节点监控主要是监控各个节点执行器的CPU、GPU、内存、磁盘、网络等情况,任务监控主要是监控任务的当前状态;

(2)任务调度:调度器首先获取各个节点执行器的内存、CPU 等资源的占用情况,以确定可以继续执行任务的执行器,然后向执行器发送任务执行请求;

(3)任务执行:调度器发出的执行请求进入执行器的任务队列,执行器按照优先级顺序执行任务,并返回执行结果;

(4)日志管理:记录系统在任务执行过程中产生的日志.

DTES 作为一个完善的系统,除了满足上述功能性需求外,还应该满足一定的非功能性需求[4],如安全性、兼容性、健壮性、可扩展性等.

系统流程图如图1所示.

图1 DTES 流程图

3 系统设计与实现

3.1 总体设计

3.1.1 系统架构设计

深度学习全流程托管平台采用微服务架构 [5,6] 实现,分布式任务执行系统DTES 最终会作为一个微服务集成到平台中.DTES 选用Spring Boot 作为框架,通过Spring Cloud 提供的注册中心组件Eureka 将DTES作为一个微服务注册到深度学习平台的Eureka 服务端,实现分布式任务执行系统和其他微服务之间的相互访问,通过Ribbon 组件实现HTTP 负载均衡,通过Hystrix 实现容错处理.

DTES 采用模块化设计,根据系统的需求分析,将系统划分为监控、任务调度、任务执行、日志管理4 大功能模块,其中每个模块又包含相应的子模块.系统的功能模块分解图如图2所示.

图2 DTES 功能模块图

DTES 采用分层模式,系统整体分为数据层、业务层和接口层3个层级.层级之间相互配合,共同实现任务执行功能.系统架构图如图3所示.

图3 DTES 架构图

(1)数据层:数据层包括MySQL 数据库、Redis 数据库和RabbitMQ 消息中间件.其中MySQL 主要用于存储任务的基本信息,如任务的状态、工作目录、环境变量等;Redis 用于全局的数据缓存;RabbitMQ 用于消息同步和存放任务执行结果,供深度学习平台的其他微服务进行消费.

(2)业务层:业务层包括系统的业务逻辑实现.其中监控模块负责监控执行器节点的资源使用情况和任务的运行状态;任务调度模块接收提交的任务并添加到任务资源库,根据系统中的调度策略从资源库中读取任务的基本信息并依此确定执行器节点,最后将任务发送给执行器;任务执行模块接收执行请求并执行具体的任务,将执行结果返回给任务调度模块;日志管理模块则主要负责收集任务执行过程中产生的日志信息,以便于后续对任务进行分析.

(3)接口层:系统使用REST (REpresentational State Transfer,表述性状态转移)协议对外提供接口服务,使用JSON 进行数据交互.系统对外开放的接口主要有任务提交接口和日志查询接口.

3.1.2 数据库设计

数据库设计是设计阶段的重要一环,分布式任务执行系统选用MySQL 数据库实现数据的持久化.根据系统的业务功能设计,系统共涉及任务、日志、执行器节点等多个实体,现将系统中重要的数据表描述如表1和表2所示.

表1 任务数据表

表2 日志数据表

3.2 详细设计

3.2.1 任务调度模块设计与实现

任务调度是DTES的重要功能之一,整个系统的有序稳定运行得益于系统合理有效的调度策略[7–11].除了常见的任务队列和随机分配方法,系统还实现了依据执行器资源利用率进行调度的策略.DTES为监控模块[12–14]的核心类GlobalHardwareMonitor的update 方法添加Spring的心跳机制@Scheduled (fixedDelay=5000)实现对各个节点执行器信息的实时更新.@Scheduled的参数定义了update 方法执行的时间规则,如fixedDelay=5000 表示该方法从上一次执行完开始计时,经过固定的延迟时间5000 ms 后执行下一次.在update 方法中订阅执行器资源利用信息,并依据利用率进行任务调度.

任务调度模块的核心类图如图4所示.在Schedule-ThreadSupport 类中调用TaskManager 接口的schedule方法进行任务调度,schedule 方法通过上行链路服务UpstreamService 发送HTTP GET 请求至下行链路控制器ClientController 加载任务信息.此外,UpstreamService中注入了硬件监控服务GlobalHardwareMonitor,依据任务信息和硬件资源利用率确定执行节点,并将结果返回给TaskManager.

图4 DTES 任务调度核心类图

3.2.2 任务执行模块设计与实现

顾名思义,任务执行模块[15–17]负责任务的具体执行.考虑到深度学习平台的实际需求以及深度学习实验的特性,DTES 现阶段的任务执行主要基于Docker容器[18]的方式.用户根据具体的任务自定义Docker 镜像并将镜像上传至深度学习平台,深度学习平台的其他微服务可以接收镜像并保存,由于不是本文的重点,具体过程不再详细陈述.

任务执行模块的核心类图如图5所示.接口Task-Manager中声明了任务执行的必需方法,它有两个实现类,分别是ThreadPoolTaskManager和AbstractDocker-TaskManager,后者是对Docker 容器任务管理器的抽象,它提供了用于获取任务镜像的方法pullImage.若后续需要支持其他类型的任务,只要实现该接口进行扩展即可.DefaultTaskManagerImpl是容器任务管理的具体实现类,UpstreamService 使用Spring的@Autowired注入进来,实现了启动方法start和终止方法kill 等任务处理方法.

图5 任务执行核心类图

任务执行的具体流程如下:

(1)TaskManager 调用UpstreamService的loadTask方法加载任务,loadTask 使用Spring的RestTemplate方式发送HTTP GET 请求至下行链路控制器Client-Controller,ClientController 调用TaskService 查询数据库将结果返回;

(2)TaskManager 调用UpstreamService的prepare方法更新任务的当前状态,prepare 使用Spring的RestTemplate 方式发送HTTP POST 请求至任务控制器TaskController,TaskController 将任务的状态由ACCEPTED(被执行器接受)改为PREPARING(任务数据准备中);

(3)检查任务所需镜像是否存在,若不存在则进行拉取;

(4)设置数据卷等信息;

(5)创建Docker 容器;

(6)开启日志收集;

(7)启动Docker 容器,执行任务.

3.2.3 日志管理模块设计与实现

作为系统的支撑模块,日志管理模块在分布式任务执行系统中也起着重要的作用[19–21].日志管理模块收集了任务执行期间产生的日志信息,给用户对任务结果的分析总结带来极大的便利.

日志管理模块的核心类图如图6所示.TaskLog-Receiver 类用于收集任务日志,当有当异步事件结果产生时就会调用该类的onNext 方法,onNext 方法通过Builder 模式实例化一个LogRecord 对象,记录下日志产生的时间、日志级别、日志具体内容等信息.DTES的日志级别分为3 种,分别是标准输出STDOUT、标准错误STDERR和纯日志输出RAW.实例化的LogRecord对象通过日志服务LogService 传到上行链路服务UpstreamService,之后用RestTemplate 方式通过HTTP POST 请求转发给LogController,LogController 调用日志存储服务LogStorageService 将任务日志保存到MySQL 数据库中.LogController 对外开放了日志查询API,深度学习全流程托管平台的其他相关微服务可以调用该API 将日志信息展示给用户.

图6 DTES 日志管理核心类图

代码1.任务执行核心代码public void start(DockerTask task){DockerTask task=upstreamService.loadTask();upstreamService.prepare(task.getTaskId());TaskContext.Builder contextBuilder=TaskContext.Builder.aTaskContext();contextBuilder.withDockerTask(task);prepareImage(task.getImage());ListvolumeBinds=new LinkedList<>();ListtemporaryVolumes=new LinkedList<>();prepareVolume(volumeBinds,temporaryVolumes);contextBuilder.withTemporaryVolumes(temporaryVolumes);Maplabels=new Hashtable<>();labels.put(TAG_TYPE,VAL_TASK_CONTAINER);labels.put(TAG_TASK_ID,task.getTaskId().toString());CreateContainerResponse containerResponse=dockerClient.createContainerCmd(task.getImage()).withWorkingDir(task.getDirectory()).withCmd(task.getCommand()).withEnv(task.getEnvironment()).withAttachStdout(true).withAttachStderr(true).withLabels(labels).withHostConfig(HostConfig.newHostConfig().withBinds(volumeBinds).withAutoRemove(true)).exec();

contextBuilder.withContainerId(containerResponse.getId());TaskLogReceiver logReceiver=applicationContext.getBean(TaskLogReceiver.class,task.getTaskId());dockerClient.attachContainerCmd(containerResponse.getId()).withStdOut(true).withStdErr(true).withFollowStream(true).exec(logReceiver);contextBuilder.withLogAdapter(logReceiver);this.taskContextHolder.put(task.getTaskId(),contextBuilder.build());dockerClient.startContainerCmd(containerResponse.getId()).exec();}

4 系统测试

4.1 接口测试

接口测试用来测试系统与外界之间以及系统内部各个模块之间的交互,主要测试系统的依赖关系以及数据传递等.使用Postman 对DTES 任务提交接口的测试如图7所示.

图7 接口测试

4.2 功能测试

DTES 作为子系统测试通过后,集成到整个深度学习平台中.深度学习平台部署在由3 台物理机构成的集群中,每台机器的硬件配置为CPU Intel Core i7@2.40 GHz,内存8 GB,硬盘100 GB,操作系统Ubuntu 16.04 LTS.本节以深度学习模型训练任务为例,对DTES的功能进行测试.

如图8所示,用户进入工作台页面,在左侧的目录树中将任务需要使用的图片数据和标签数据挂载进来,接着创建程序文件并在右侧区域进行代码编码.编码完成后,鼠标右键点击左侧项目的根目录选择“创建训练任务”,创建成功后,DTES 在后台进行调度执行.切换到任务详情页面,可以看到任务的实时日志信息,如图9所示.

图8 创建任务

图9 日志查询

4.3 性能测试

为测试DTES的性能,本节使用TensorFlow 框架在已集成DTES的深度学习平台与未集成DTES的第一代平台中多次训练手写数字MNIST 数据集,并对完成同一训练任务的平均用时进行比较.实验数据如表3所示.

表3 不同平台完成同一训练任务的平均耗时(单位:s)

通过对比可以看出,对于同样的深度学习训练任务,DTES 可以节约大约23.8%的时间,具有较高的应用价值.

5 总结与展望

使用深度学习平台在网页端进行深度学习模型训练可以给实验研究人员带来极大的便利,本文结合平台的实际需要设计并实现了分布式任务执行系统DTES.DTES 基于Spring Boot 框架实现任务调度、任务执行、日志管理等功能,可以作为一个微服务快速集成到深度学习平台中.DTES 将接收的任务按照既定的调度策略进行调度并创建Docker 容器进行执行,同时将任务执行期间产生的日志信息反馈给实验研究人员.经过系统测试,DTES 已经达到预期目标,但仍然存在待完善之处,接下来要继续对该系统进行扩展,使其可以支持更多类型的任务.

猜你喜欢

任务调度执行器日志
形状记忆合金执行器研究综述
自动驾驶汽车执行器故障冗余算法
基于动态能量感知的云计算任务调度模型
一种软体末端执行结构设计与试验分析
一名老党员的工作日志
执行器中磁滞非线性问题的建模和补偿
读扶贫日志
雅皮的心情日志
雅皮的心情日志
集群渲染系统构建及优化