给定服务器的型号参数列表,包括(服务器的型号,CPU核数,内存大小,硬件成本,每天能耗成本)。
给定所有可申请的虚拟机型号,包括(虚拟机的型号,CPU核数,内存大小,是否单双节点部署)。
每个测试用例包括以下内容:
- 可以购买的服务器类型数量 N,接下来包括 N 个服务器型号,格式如上所示。
- 可以售卖的虚拟机类型数量 M,接下来包括 M 个虚拟机型号,格式如上所示。
- T 天用户请求。
- 每一天有 R 条请求 (add, 虚拟机型号, 虚拟机 ID) 或者 (del, 虚拟机 ID)。
输入实例:
2 (NV603, 92, 324, 53800, 500) (NV604, 128, 512, 87800, 800) 2 (c3.large.4, 2, 8, 0) (c3.8xlarge.2, 32, 64, 1) 3 2 (add, c3.large.4, 5) (add, c3.large.4, 0) 2 (del, 0) (add, c3.8xlarge.2, 1) 3 (add, c3.large.4, 2) (del, 1) (del, 2)
输出格式如下:
- 首先第一行输出(purchase, Q),其中Q是一个整数表示你需要扩容购买多少种类型的服务器。Q不能为负数且不能大于N。
- 接下来Q行,每行的格式为:(服务器型号, 购买数量)。所购买的服务器都会被分配一个编号,从 0 开始。
- 接下来一行输出(migration, W),其中W是一个整数表示你要迁移的虚拟机的数量。迁移格式为 (虚拟机 ID, 目的服务器 ID) 或 (虚拟机 ID, 目的服务器 ID, 目的服务器节点)。
- 接下来是请求的顺序,输出对当前的每一个创建请求,格式为(服务器ID)或者(服务器ID, 部署节点)
输出实例:
(purchase, 2) (NV603, 1) (NV604, 1) (migration, 0) (0, A) (0, B) (purchase, 0) (migration, 0) (1) (purchase, 0) (migration, 0) (1, B)
- 任务目的是为虚拟机设计一套调度算法。
- 要求在能部署所有虚拟机的情况下,最小化价格(服务器的购买价格+每天能耗花费),也就是说尽可能的提高服务器的利用率。
简单的背包问题是,有一个背包,尽可能的装东西。这个问题是背包问题的升级版,维度增加了很多,约束条件增加很多,难度直线上升。
-
要求有单双节点部署,有时候可能某一节点剩余很少,另一节点剩余很多,请求添加一个双节点部署的虚拟机的时候放不下。
-
申请的某些虚拟机型号很恶心,CPU需要很少,内存却需要很多,导致分配不均匀。
变量名 | 变量类型 | 描述 |
---|---|---|
type | string | 服务器类型 |
serverId | int | 服务器 id |
CPUCapacity | int | CPU 总容量 |
partACPULeft | int | A 节点 CPU 剩余 |
partBCPULeft | int | B 节点 CPU 剩余 |
memoryCapacity | int | 内存总容量 |
partAMemoryLeft | int | A 节点内存剩余 |
partBMemoryLeft | int | B 节点内存剩余 |
hardwareCost | int | 硬件成本 |
dailyCost | int | 日常能耗成本 |
方法名 | 返回类型 | 描述 |
---|---|---|
getter() | 参考变量类型 | 获取类中私有变量 |
setter() | 参考变量类型 | 获取类中私有变量 |
getScore() | double | 负载均衡参数:CPU/内存 |
变量名 | 变量类型 | 描述 |
---|---|---|
type | string | 虚拟机类型 |
VMId | int | 虚拟机 id |
CPUNeed | int | CPU 需求 |
memoryNeed | int | 内存需求 |
nodeType | int | 部署类型 0:单节点,1:双节点 |
serverId | int | 部署到了哪一个服务器上 |
deployNode | char | 部署到服务器上哪个节点,'A','B','C':双节点 |
方法名 | 返回类型 | 描述 |
---|---|---|
getter() | 参考变量类型 | 获取类中私有变量 |
setter() | 参考变量类型 | 获取类中私有变量 |
方法名 | 返回类型 | 描述 |
---|---|---|
showMessage() | void | 打印所有资源,包括(可购买的服务器列表,可购买的虚拟机列表,已购买的服务器资源列表,已部署的虚拟机列表) |
findServerAddVM() | shared_ptr | 根据策略,找到可以部署虚拟机的服务器 |
addUpdate() | char | 部署虚拟机到服务器上,更新服务器的资源信息,并打印部署控制台信息 |
delVM() | void | 删除一个虚拟机 |
delUpdate*( | void | 删除虚拟机后,更新服务器和虚拟机的资源信息 |
作为第一个版本,我们的想法很简单:盯着一种服务器来买,先模拟一遍看当天需要买多少服务器,买够之后,再把虚拟机放到服务器里面,有位置就放,迁移虚拟机从后往前迁,也是有位置就迁。
显然这种方法问题很大,没有考虑虚拟机的 CPU/内存 比,会浪费大量资源。这种方法的运行结果是我们的最终成绩的四倍花费。
和现实情况不一样的是,我们有预知能力,可以提前看到接下来所有的请求和删除虚拟机操作,那么我们可以先看,再来挑选组合虚拟机放到同一台服务器上,尽量让虚拟机的搭配更加均衡(就像俄罗斯方块的 L 和 7 搭配均衡更好),让服务器资源利用更高。服务器我们还是盯着同一台来买,根据所有的 CPU/内存 来挑选服务器。
这里还是存在问题,挑服务器是根据整体的 CPU/内存 比例来选的,局部某一天的虚拟机请求和这个比例可能相差很大,还是会放不均匀。
服务器挑选:按 CPU/内存 的比例来划分区间,一共划分了 9 个区间,每个区间,选一种比例相近的服务器作为代表,当天的比例接近哪种服务器,当天就买那种服务器。
部署虚拟机:先挑选搭配合理的虚拟机先部署。
迁移:对 9 种型号的服务器队列,把后面的服务器往前迁移,能够放下就迁移。
总的来说,对自己代码提升还是挺大的,队友都很给力。
感觉打比赛自己的想法可能不是很好,在下手写代码之前,最好先去找一下有没有前辈做的类似的研究,先把前人的复现一下,然后再次基础上进行改进。这次比赛我们全都是靠讨论,按自己的想法来写的,所以效果可能不太好,还有很多可以优化的地方,期待下次的华为软挑比赛!