基于强化学习在云计算环境中的虚拟机资源调度研究
随着云计算规模的持续扩大,数据中心虚拟机资源调度面临动态负载、异构资源适配及多目标优化等挑战。传统启发式算法在复杂场景下易陷入局部最优,而深度强化学习(DRL)凭借序贯决策能力为该问题提供了新路径。本研究以动态多目标组合优化理论为基础,结合CloudSimPy仿真框架与TensorFlow,构建“仿真-训练-验证”闭环调度系统,重点设计动态加权多目标奖励函数、时序建模网络及多进程并行训练策略,支持非DAG任务、长周期分块任务等复杂场景。实验表明,DRL算法在总完成时间(Makespan)、平均完成时间(AC)、平均延迟(AD)等指标上显著优于传统算法(如首次适应、Tetris),资源利用率提升5%以上,训练效率通过多进程优化缩短80%。研究为云计算智能运维提供了可迁移的模型与策略,推动DRL从理论验证向实际落地迈进。
关键字:云计算;虚拟机资源调度;深度强化学习;多目标优化;长周期任务;CloudSimPy;策略网络;动态环境适配
更多应用细节功能参考:CloudSimPy 开源项目使用教程-CSDN博客
本文实现与报告见绑定资源:基于强化学习在云计算环境中的虚拟机资源调度研究 Cloud_Computing.7z
Job数据集的字段含义说明
根据 CloudSimPy 框架中对作业(Job)、任务(Task)、任务实例(TaskInstance)的建模逻辑,以下是字段的含义:
字段名 | 含义 | 关联实体(参考 CloudSimPy 建模) |
---|---|---|
submit_time | 作业或任务的提交时间(仿真时间戳),表示该任务/作业被提交到集群的时刻。 | 作业(Job)/任务(Task) |
duration | 任务实例的执行持续时间(仿真时间单位),表示该任务实例需要运行多久才能完成。 | 任务实例(TaskInstance) |
cpu | 任务实例运行所需的 CPU 资源量(如核心数)。 | 任务实例(TaskInstance) |
memory | 任务实例运行所需的内存资源量(如 GB)。 | 任务实例(TaskInstance) |
job_id | 作业的全局唯一标识符,用于区分不同作业。 | 作业(Job) |
task_id | 任务的局部唯一标识符(需结合 job_id 唯一确定),表示作业中的具体任务。 | 任务(Task)(属于某个 Job) |
instances_num | 该任务包含的任务实例数量(即一个任务由多少个并行的 TaskInstance 组成)。 | 任务(Task)(Task 是 TaskInstance 的集合) |
disk | 任务实例运行所需的磁盘存储资源量(如 GB)。 | 任务实例(TaskInstance) |
补充说明
- 数据集中的每条记录可能对应一个 任务(Task),其中 instances_num 表示该任务需要创建的任务实例数量,而 duration、cpu、memory、disk 是该任务下所有任务实例的统一资源需求(假设任务内实例资源需求相同)。
- job_id 和 task_id 的组合可唯一标识一个任务,而任务通过 instances_num 生成多个任务实例(TaskInstance),最终由调度算法分配到集群机器上运行。
仿真逻辑补充
结合 CloudSimPy 的仿真流程(来自「高性能仿真」部分):
- Broker 进程会 按照作业的提交时间(即 submit_time) 将作业配置列表中的作业提交至集群 Cluster 实例。
- 作业提交后,需要等待调度器 Scheduler 根据调度算法分配资源(如机器的 CPU、内存等),才能开始运行。因此,作业的实际开始运行时间通常会晚于 submit_time(具体取决于调度算法的效率和集群资源的空闲状态)。
Job 和 Task 补充
- 数据结构层面(代码视角)
- Task(任务):由 TaskConfig 表示,对应数据集中的一条记录(每行数据)。每个 TaskConfig 包含任务的基本信息(如 task_id、instances_num(任务实例数量)、cpu/memory/disk(资源需求)、duration(执行时长))。
- Job(作业):由 JobConfig 表示,是多个 TaskConfig 的集合。一个 JobConfig 包含:
- job_id(作业唯一标识)
- submit_time(作业提交时间)
- task_configs(该作业包含的所有 TaskConfig 列表)
- 业务逻辑层面(仿真视角)
- Task(任务):是作业的子单元,一个作业可包含多个任务(例如,一个作业可能需要先执行数据预处理任务,再执行模型训练任务,每个任务是作业的一个步骤)。
- Job(作业):是用户提交的完整计算需求,由多个具有逻辑关联的任务组成(如 DAG 任务间的依赖关系,或 Non-DAG 任务的并行执行)。
- 实例化关系(运行时视角)
在仿真运行时:
- 每个 Task(任务)会根据 instances_num 生成多个 TaskInstance(任务实例),这些实例是实际占用资源(CPU、内存、磁盘)并运行的实体。
- 每个 Job(作业)的状态(如“运行中”“完成”)由其所有 Task 的状态合成(例如,当作业的所有任务都完成时,作业才标记为完成)。
Jobs(作业)是用户提交的完整计算任务集合,由多个具有逻辑关联的 Tasks(任务) 组成;每个 Task(任务) 进一步拆分为多个 TaskInstance(任务实例)(实际运行的最小单元)
考虑任务类型(非DAG vs DAG)、并行方式(多进程 vs 单进程)、优化目标(总完成时间 vs 平均完成时间)、任务输入方式(单批 vs 分块长周期)、特殊功能(任务依赖 vs 任务分组)
文件名称 | 任务类型 | 并行方式 | 优化目标 | 特殊功能 |
---|---|---|---|---|
main-makespan.py | 非DAG | 多进程 | 总完成时间(makespan) | 基础非DAG任务调度 |
main-AC.py | 非DAG | 多进程 | 平均完成时间 | 适配平均完成时间的奖励函数 |
main-makespan-long.py | 非DAG(长周期) | 多进程 | 总完成时间(makespan) | 分块处理大规模任务 |
main-single-process.py | DAG(有依赖) | 单进程 | 总完成时间(makespan) | 处理DAG任务 |
性能评估指标
指标名称 | 计算方式/含义 | 代码实现位置 |
---|---|---|
总完成时间 | 所有任务完成的最大时间(仿真环境中最后一个任务实例的完成时间),即 episode.env.now | 基准测试中直接获取:episode.env.now;训练循环中通过 makespans 列表统计平均值 |
平均完成时间 | 单个任务从提交到完成的平均时长(所有任务实例的完成时间 - 提交时间的平均值) | 通过工具函数 average_completion(episode) 计算,训练循环中统计 average_completions 平均值 |
平均延迟 | 任务完成时间与任务本身时长的平均值(反映任务执行的“拖延程度”) | 通过工具函数 average_slowdown(episode) 计算,训练循环中统计 average_slowdowns 平均值 |
性能对比方法
- 基准算法对比(横向对比)
通过运行 3 种经典启发式算法(随机算法、首次适应算法、Tetris 算法),在相同任务配置下收集上述指标,作为强化学习算法的性能基线。具体步骤如下:
- 相同输入条件:使用同一组机器配置(machine_configs)和任务配置(jobs_configs);
- 独立运行:分别运行每种基准算法的 episode.run(),记录各指标;
- 输出对比:直接打印各算法的指标结果
- 强化学习训练迭代统计(纵向对比)
在强化学习训练过程中,通过多进程并行收集多轮次的模拟数据,统计每轮迭代的平均指标,观察算法性能随训练轮次的变化趋势。具体逻辑如下:
- 多进程数据收集:每轮迭代启动 n_episode 个子进程(默认 12 个),并行执行强化学习模拟,收集各回合的 makespans、average_completions、average_slowdowns;
- 指标统计:计算每轮迭代的平均指标(如 avg_makespan = np.mean(makespans)),并输出对比:
- 趋势观察:通过多轮迭代的指标变化(如总完成时间是否逐渐降低),评估强化学习算法的优化效果。
- 总结:模型性能通过 总完成时间、平均完成时间、平均延迟 三个核心指标评价,对比方法包括:
- 与经典启发式算法(随机、首次适应、Tetris)的横向对比;
- 强化学习训练过程中多轮次的纵向性能趋势对比。