2021华为软件精英挑战赛
2021华为软件精英挑战赛
github地址: https://github.com/lh4027/huawei-software-competition2021.git.
比赛心得
今年首次参加华为软挑,一开始只想进前64 强拿个证书就满足了,没想到队友太猛直接肝进初赛正式赛第六。
复赛由于时间关系没有好好准备加上没有很好的思路,训练赛的时候掉到了16,现场赛3个小时又出现了意外(换了数据集后,训练赛提交成功的代码竟然正式赛运行异常),只好现场改用初赛最好成绩那份代码,不出意料,最后只取得了复赛21的成绩,总的来说还是比较遗憾的,毕竟复赛期间改良的代码没有用上。初赛,复赛成绩如下:
接下来我会具体总结一下我们队伍的思路和方法,时间仓促,可能有叙述不合理的地方,见谅。
赛题分析:(具体赛题也上传在github上)
题目中所给的虚拟机有两种部署方式,分别为单双节点部署,单节点部署指的是一台虚拟机所需的资源(CPU和内存)完全由主机上的一个节点提供;双节点部署指的是一台虚拟机所需的资源(CPU 和内存)必须由一台服务器的两个节点同时提供,并且每个节点提供总需求资源的一半。
赛题要求根据所给的请求序列,创建服务器,部署虚拟机,或者按照用户请求在对应的服务器上删除相应的虚拟机。但要注意,服务器上的任意一个节点(A和 B)上的资源负载(CPU 和内存)均不能超过其容量上限。在完成每一天的服务器的扩容之后,在处理每一天的新请求之前,你还可以对当前存量虚拟机进行一次迁移,即把虚拟机从一台服务器迁移至另一台服务器。对于单节点部署的虚拟机,将其从一台服务器的 A 节点迁移至 B 节点(或反之)也是允许的。但迁移的虚拟机总量不超过当前存量虚拟机数量的千分之五。
我们可以发现这是一个类似于装箱的问题,把服务器比作箱子,把虚拟机比作需要放进去的货物。官方推文上给的提示复杂难懂,但本质好像也是多维装箱问题。
我们程序的流程
首先解析出来所有服务器类型,虚拟机类型,以及请求天数,然后对每一天到来的虚拟机请求处理,迁移,部署最后扩容。
我们的方法是针对每一天的请求数据来进行的,(初赛一次性给出了所有天数的请求,意味着可以用上帝视角去处理这个问题,但是实际场景中不可能知道全部数据,只能预测到有限天数的请求,这也是复赛赛题变动的地方)。
第一天的时候我们根据所有的Add请求进行扩容,也就是首次购买服务器,如何选取服务器会在后续扩容策略里面详述,然后再进行虚拟机的部署,也就是分配,我们的add请求和delete请求是分开处理的,先处理完所有add请求,再去处理所有delete请求,因为我们是基于一天数据的全局视角来处理数据的,这对我们的程序来说很重要。
后面的每一天我们先取出所有虚拟机请求,首先进行迁移,这里的迁移其实是针对上一天的,因为上一天会有删除请求,会空出很多服务器资源,这时候就需要对这些空置资源重新整合。然后进行虚拟机的分配,也就是部署add请求的虚拟机。将这一天的所有add请求单独拿出来,往剩余的服务器资源里面部署,直到剩余服务器资源再也部署不进去虚拟机后终止。
将剩余的add请求交给扩容,选择购买一批服务器放入这剩下的add请求,至此所有add请求我们都处理完毕,接下来处理所有delete请求。一天结束。循环往复,直至最后一天。
扩容策略:
我们的扩容策略其实就是基本的装箱问题加贪心算法,主要利用了降序梯度最佳适应算法,加上一些小技巧,在我们的代码中,将每天分配部署后的剩余虚拟机add请求拿过来,按照这些请求所需资源大小降序排列,即让大的虚拟机先放,遍历所有可购买的服务器,每一台服务器放入其自身容量极限的虚拟机后,计算服务器剩余资源,取出差值最小的服务器,一次循环选出一台服务器,每次选出后服务器后,记录该服务器上的虚拟机,这里在购买服务器的同时已经相当于把这些虚拟机分配好了,后面直接查找这些虚拟机所在的服务器就可以直接输出了。
每选择好一台服务器后,就更新现在的虚拟机请求总表,即去掉已经分配在购买的服务器上的虚拟机请求。当这一天的虚拟机总表为空时,我们就完成了扩容。这种方法使得利用率很高,但有个很大问题,时间复杂度会很高,尤其是一天的虚拟机请求特别多时,会很耗费时间。
这里我们用了一些小技巧,一个是数据切分,另一个是按照虚拟机内核比>1和内核比<1分类,服务器也按照内核比分成两类。流程:数据切分->按照内核比分类->按照请求所需资源大小降序排列,这样当虚拟机请求数很多时(程序中设置为3000),我们分为几个数据块,每个数据块单独执行扩容策略,再用上多线程,很好地解决了超时问题。
分配策略:
每天在扩容之前,我们需要将虚拟机请求先进行一次部署,如何保证较好的资源利用率尤为重要,在这个阶段,我们部署越多的虚拟机请求,扩容时需要购买的服务器就越少,成本就会越低。这里使用的策略依旧是贪心算法,找放入虚拟机后剩余服务器资源量最小的,每次遍历所有服务器,策略和扩容类似。
迁移策略:
将剩余服务器资源从大到小排序,将剩余资源多的服务器上的虚拟机迁移到剩余资源少的服务器上,复杂度很高,采用了很多剪枝方法,加了很多限制,如迁移成功率,失败率等。(膜拜大佬队友,优化时间很有一套)具体可看代码。
复赛的时候我们又改进了分配算法和迁移算法,用初赛数据集测试总成本可以达到11亿以下,可惜复赛现场赛出了bug,所以代码一定要多测试,提升鲁棒性。
以上仅为我们团队思路和方法,非科班出身,能力不足请轻喷。
最后总结一下,在参加这类比赛时,代码更新迭代非常快,最好做好版本管理和代码留存说明,写代码时多思考,不要堆砌代码,否则后期自己都看不懂自己的代码了,修改起来很麻烦。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!