华为2021软件精英挑战赛思路分享

在这里插入图片描述

一、前言

此次是第一次参加华为软件精英挑战赛,前几届实验室师兄都有参加这个比赛并都取得不错的成绩。通过这次比赛学到了很多,小到c++基本语法,大到算法的分析建模过程,都得到极大锻炼。也通过比赛明白了优秀的算法工程师和开发工程师为什么得到各个大厂的疯抢,好的算法思维能为一个企业带来的潜在价值不可估量。
整个比赛赛题有三个(技术还不够强,没能进入决赛,看了决赛的赛题采用分组对抗,很有意思),风别是预赛、正式赛和复赛,各个赛题变化不大,在github上传了复赛赛题及数据集
初赛预赛的时候花了很多时间,最终排名第2 (后来才发现原来大佬都是不怎么玩预赛),结果就是到了正式赛时原先方案严重过拟合,在新的数据集上表现很差,然后重新设计策略。
最终以成渝赛区初赛第10名的成绩进入复赛,在复赛中排名第7,无缘决赛。对前面的大佬不服不行,用一样的数据集愣是比我们少了上亿的成本,这就是算法的魅力吧。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

二、赛题方案

该赛题是一个NP的问题,理论上很难求解出最优解,目前争对这类问题的研究论文也有很多,粗略看了几篇,基本上都按照平衡放置各种资源思路来思考。真实业务有所不同,除了虚拟机的放置和购买,还涉及到迁移。在比赛过程中实际参考论文内容很少,基本都是基于数学模型的思考以及一些先验知识一步步优化模型。

1.服务器购买策略:
由于评价策略的指标是整个时间段内的消耗成本,主要包括购买服务器时的成本和部署服务器每天的能耗成本两部分组成。几乎都能想到的是:在前期应该主要考虑能耗成本,越到后期就应该越优先考虑购买成本,思路很明确,重点是该如何权衡这两部分之间的比重,以及服务器不同资源比例对其又有何影响。
同类服务器在不同时期购买的性价比是动态变化的,为了更准确衡量服务器在每天的性价比,通过数学模型分析,我们提出了基于滑动窗口的有效资源利用比在每次需要购买新的服务器时来实时更新不同种类的服务器性价比。这一改进也是复赛中最大的提分点。总成本一下少了好几千万。

具体如下:

int cpu = 0, mem = 0, count = 18;

for(int k = OpCntofOneDay; k < OneDayAdd_VC.size() && k < OpCntofOneDay+count; k++)
            {
                cpu += OneDayAdd_VC[k].CpuNeed;
                mem += OneDayAdd_VC[k].Memory_Need;
            }
            double rad  = 1.0 * cpu / mem;
            double rad1 = 1.0 * mem / cpu;
            for(auto &k : HostCate)
            {
                int value = min(k.CoreNum / rad + k.CoreNum, k.Memory / rad1 + k.Memory);
                k.myPrice = (1.0 * k.Prices * 1.01/ (DaysNum - Day) + k.EleCharge * 0.8) / (value+(k.CoreNum+k.Memory-value)*0.28);
                if(CpuNeedAll > MemNeedAll && k.CoreNum < k.Memory)
                    k.myPrice = 9999999;
                if(CpuNeedAll < MemNeedAll && k.CoreNum > k.Memory)
                    k.myPrice = 9999999;
            }

上述程序中count是滑动窗口的大小,cpu,mem分别表示在从此时开始今天最新count个虚拟机放置请求的cpu和内存和,它们的比例就是该窗口内虚拟机的资源比,mem/内存=rad,内存/mem=rad1。count为可调参数。

int value = min(k.CoreNum / rad + k.CoreNum, k.Memory / rad1 + k.Memory);

这个语句是计算当前服务器k放置滑动窗口内虚拟机比例的资源是最多能利用的有效资源个数,(这里的有效资源个数=该类服务器的cpu有效利用个数+该类服务器的内存有效利用个数)它会随着滑动窗口的改变而动态变化,也就是同一类服务器k,在不同时间有效资源个数会不同
比如当前有有一个CPU=20,内存=40的服务器。某一时刻A滑动窗口内的CPU/内存=1/2,则A时刻该服务器有效资源个数为20+40=60,比例相同,所有资源都可以用。某一时刻B滑动窗口内的CPU/内存=2/1,比例相差很大,计算出的有效资源个数为20+10=30。
计算出有效资源个数后,下一步就是要计算当前时刻该类服务器的性价比,也就是最重要的公式:

k.myPrice = (1.0 * k.Prices * 1.01/ (DaysNum - Day) + k.EleCharge * 0.8) / (value+(k.CoreNum+k.Memory-value)*0.28);

k.Prices表示当前时刻服务器种类k的性价比。可以将上面的公式拆解为分子和分母两部分:
第一部分[1.0 * k.Prices * 1.01/ (DaysNum - Day) + k.EleCharge * 0.8 ]代表当前购买该类服务器均摊到每天的成本,1.01和0.8分别代表后期平均购买成本和能耗成本的权值(这里假设购买的服务器在后期始终都处于开机状态,虽然现实很难实现,但这样的假设对大部分数据集都聚有良好的鲁棒性),其中k.Prices * 1.01/ (DaysNum - Day) 会随着Day的变化而变化,即越往后购买服务器的成本均摊到剩余每天的也就越大。
第二部分[value+(k.CoreNum+k.Memory-value)*0.28]代表当前第k类服务器的真实有效资源利用个数。它是由前面计算出的有效资源利用个数加上一个补偿因子(补偿因子理解为:若服务器总共有60个资源,有效资源个数为40,那么剩下的20个资源后期仍可能通过迁移操作也被用到从而变为有效资源)
最后用当前的成本/真实有效利用资源个数,即得到服务器k当前时刻的性价比,在购买的时候对依据当前时刻性价比对所有种类服务器进行排序,购买第一个能放下最新虚拟机的服务器。
PS:另外最后的两个if语句起始可以省滤掉,它是对不满足最小放置需求的服务器进行剔除,后面排序后也会再筛选一次

二、虚拟机放置策略:
放置虚拟机时,需要从几个维度同时考虑,避免大的空缺。这里,我们主要从两点来考虑:(具体实现见代码)
1.引入多维空间划分模型,如下图所示,对于一个已经部署的服务器,假设横坐标代表CPU资源已放置个数,纵坐标代表内存资源已放置个数,右上角为最佳放置状态,此时CPU和内存利用率都接近1,而左上角和右下角两种状态会造成很大的空洞,因此应极力避免这类情况。对此采取的策略是:设定一个可接受空洞阈值,当在某一服务器放置虚拟机后使得服务器某一资源小于最小可接受阈值二另一类资源大于最小可接受阈值加上空洞阈值,则该服务器拒绝接入此虚拟机。
在这里插入图片描述
2.定义剩余空闲资源的乘积作为衡量一个虚拟机放在不同服务器上的合适度。思想类似于木桶效应,一个木桶的盛水量往往是由最低的一块木板决定的。服务器的整体资源利用个数也类似,若一类资源剩余个数很少,势必也会限制另一类资源在服务器的布置。只有不同维度的资源之间取得较好的均衡,才能改善整体性能。

三、迁移策略
这部分我认为是我们没怎么做好的一部分,也是进步空间最大的一部分,我们在迁移时,首先按剩余资源个数将部署的服务器由小到大进行排序,然后从后往前依次将服务器中的虚拟机往前迁移,以使能够空出更多的已购买虚拟机减少能耗成本。但对于许多大的虚拟机在前面找不到迁移位置,使得闲置服务器数量集合很难减少,后来改变策略,迁移以将后面的小的虚拟机迁移到前面补齐空洞为主,而较少的考虑空出更多的限制服务器。另外改进了迁移时的数据结构,将程序运行时间由原来的140s优化到30s。该策略虽然相对之前有较大改进,但是总的迁移次数始终提不上去,不到别人的1/2。这里还有很大的优化空间。

三、总结

几次赛题变更都只是迁移次数以及提前获取k天的数据k值的变化,我们的策略迁移次数根本就没提上去,而且在放置虚拟机时也仅考虑了当天放置的请求。所以几次改变的赛题都是用的一套代码。针对这两点,现有方案还有很大的进步空间。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值