前言

决赛的过程颇为坎坷,深深的感受到了自身能力的不足,团队的力量有时要远胜个人。

开源地址:https://github.com/Chadriy/CodeCraft2020


放题

复赛结束,还没来得及感慨,第二天一大早就放题了。实在是不想做题目介绍了,简单说明一下,仍然是给定一个有向加权图,不过解题目标变更为计算网络中节点介数中间性,并返回top100的点与其精确值,对于概念及算法可以参考https://blog.csdn.net/betarun/article/details/51168259。基本上,大家参考的都是2001年brandes在论文《A faster algorithm for betweenness centrality》中提出的算法,一天之内算法就内卷了呢(无奈摊手.jpg)。
然后队友一天写好了base,然后造了份数据集(tql),之后几天就是debug和精度问题。

练习榜A

决赛后我们进入了分别solo的状态,蔡总写好base后被导师gank出差去了,于是交给我继续搞这base。第一版的最短路算法我们用的是优先队列的dijskra算法,配合brandes算法计算介数中间性。由于算法复杂度提高了非常多,之前对io的优化基本上没有作用了。因此优化思路被限制成三种:

  • 算法逻辑的优化
  • 数据结构优化
  • 针对数据集优化

线上开放测试,我们很快意识到针对底层的优化经过初赛复赛已经达到了瓶颈,因此一开始没有很好的方案。榜A第一天,官方公布了数据集的规模,并给了一个线上线下特性同步的数据集,根据其大小我们推测,完全随机图是根本跑不完的。之后测测数据集特性,主要是度特性、权值分布、scc这些,发现平均度为1。继续观测数据集,发现总点数约80w,而其中60w+为入度0出度1点,形状有些像刺猬。
于是根据公示的等价性,入度0点的σ\sigmaσ为其邻接表的∑lrσ\sum\limits_{l~r}\sigmal r∑​σ,其中σ\sigmaσ为以该点为起点的最短路条数。
于是显然,对于入度0出度1的点,其本身必不可达。于是在计算介数中间性时,可以将该点合并到其邻接点,然后在计算邻接点的介数中间性时*(1+n),n表示到该点的特殊父节点数目。通过这样处理,需要计算的点数降至约16w。对于入度0出度任意的点,存在等价性问题(先加后除还是先除后加),因此当时只想到保存中间结果的方法,实现起来很麻烦。因此最终未实现,当然通过分析可知,若实现后点数降至约7w。
不得不说,前排大佬实在是太猛了。我刚加上这个tirck线上从400s到90s,发现不小心冲得太猛0 0,于是赶紧吹一波SPFA转移视线,然而没几个小时大家就都进100了。事实上到了这个阶段,只要不藏分,甚至可以通过前排大佬分数的提升幅度来推断做了什么优化qwq。杭夏赛区真的很强,据说507和鸽鸽鸽都是ACM的金牌选手,一度支配比赛。
A榜存活时间很短,又做了点小改动,最后封榜时77s,貌似还在前五吧

练习榜B

B榜线上增加了随机图,直接一个scc块,扼杀了很多利用scc特性的方向。B榜对新旧两份数据集进行时间累加,作为最终成绩。由于上文trick的存在,我们线上成绩为800s,可以看出图一已经只占很少的比重了。接下来的几天,蔡总未归,我这边思路也陷入了误区。由于旧图trick提分巨大,因此我的思路一直往这如何删点、删边、找等价性替换的方向走,整整两三天没有思考出结果。
这时候很感谢同赛区的各队伍,尤其是服务器队。在观察到数据集分布中权值为100以内的正态分布,一番讨论后,由扫黑除恶小分队提出了对堆内distance的压缩想法,同天晚上服务器队完成了具体实现。事实上我们整个赛区的四支队伍都在700s这里卡了好几天,至此成为了转折点,我们的优化重点全部转移到对数据集的观测性优化。

Last 1

对于第二张图,我们可以观测到:

  • 边权为100以内的正态分布
  • 均匀度为20左右,且分布均匀,因此搜索四次邻接表即可完成全图搜索
  • 对任意一点,所有点均会入堆至少一次

因此,可以修改入队规则,队内只保存distance,然后每个distance对应一个点id列表,通过该tirck线上提升约200s。沿该方向继续深化,distance最高为250左右,图一要比较大约6000。于是考虑分段映射,当distance小于阈值T时,用distance做下标索引,大于阈值则用unordered map。事实上,对于图二根本不需要队列,连数组都不需要,用一个index变量自增就可以。通过这种方法简化了逻辑,抛去了优先队列,同时删掉了两个变量和一个判断,然后线下线上均负优化qwq。队友也尝试了各种堆结构以及手写vector,最后只有vector被保留下来,其余均不如std的优先队列。除此之外,又尝试了一版Neon加载邻接表,负优化+1。通过以上优化,分数来到400+s。

Last 2

由于一次疏忽,distance的vector替换为手写vector后写成了uint,分数莫名提了几十s我们浑然不觉…某次三联线上0%后,我误以为是uint导致的,然后发现这玩意还能上分。于是第二个大trick,对数据结构进行压缩。一通大改,尽可能的压缩数据结构。同时与同赛区小伙伴们交流了一下数据结构方面的心得,将brandes算法反向搜索的表改成二维,同时简化构图中G.l与G.r结构体中r与l+1的等价性,只存l。这时候对赛制有些担忧,只要官方调一下权值分布,我们这些trick就完全失效了。但是如果官方不调,那如果不用这些tirck就基本凉凉。
这时候倒计时两天,我们来到了340s左右,然而还进不了第一页的样子(摊手)。

Last 3

这时候由其他队想出来一个很厉害的trick,通过对邻接表BFS然后重映射,对于图一这种出度很大的局部稠密图来说,cache友好提升巨大。通过该trick图一只需要8s就可以跑完,图二没变化。线上330->315s。之后也做了一些对图二的cache优化,但是并没有起到左右。最后一天下午,我加了一点unlikely和prefetch的优化,并且把distance数组从结构体提出来,放到邻接表G旁边(调整变量顺序)。线上跑到了300s,封榜时第三。
这时候我们图二线下约126s(也可能是130s),晚上和第二天上午我们做了一些逻辑判断、变量结构的调整,譬如在for循环中,往往用如下写法

for(i = G[v].l;i < G[v+1].l;i++)

而替换成如下写法相当于prefetch了,节省了一次跳址

for(i = G[v].l,end = G[v+1].l;i < end;i++)

同样,对部分变量封装结构体,也可以减小访址代价。

struct  Result{double bc;  //中介中间性double delta;
};

通过这些细小优化,最后图二分数提升到113s,吃完午饭就开始最终的决赛了。

End

不得不说,对于我们这样很少打现场赛的队伍来说,决赛中我们并没有什么发挥。前半个小时我们遇到了一个很崩溃的bug,新服务器编译不过。折腾了半个多小时,其他队伍都已经出分,我们还是编译不过,几乎处于崩溃边缘。然后蔡总发现编译选项用的-o3,应该是-O3。旧服务器上一直用的-o3没啥问题,然而新服务器直接编译不过。蔡总nb,差点我们就没分了。
然后拿最新版直接提交,第一发276s。凌少分享了一个调参的trick,把反向遍历的二维表,第二个维度由250改为150提升至265s。然后是一发探测,线上ushort就能过,去掉所有切换换成ushor,同时微调了一处逻辑即263s。
关于NUMA的特性,之前做过线程绑定的尝试,由于效果很差没有备份。现场大概写了10min就感觉这个特性如果要利用上,除了绑定还要对数据做内存隔离。于是将所有精力放到了调参上,然后我贡献了两发re与一发263。封榜的时候,我们第四名,离第三名只差0.5s左右。如果这样GG掉,可能我要自闭很久。因为我的两次re,最后只有两次调参机会。
略带遗憾,最后两次机会调错了方向,没有提升,最终凭借着平淡的临场发挥拿到了全国第五。
就这样,两个月的历程拉下了帷幕,我们收拾好行李,又各自奔赴向更远的地方。
最后,再次感谢比赛途中遇到的所有人,谢谢。我们有缘再见。

2020华为软件精英挑战赛历程总结——决赛篇相关推荐

  1. 2020华为软件精英挑战赛历程总结——复赛篇

    前言 最近在打腾讯广告算法大赛,所以一直在鸽0 0,再加上复赛印象不怎么深刻,所以就随便扯啦. 开源地址:https://github.com/Chadriy/CodeCraft2020 放题 一.规 ...

  2. 2020华为软件精英挑战赛历程总结——初赛篇

    前言 去年懵懵懂懂,一个人从头自闭到尾,到最后也没对上判题器,复赛第十遗憾离场.今年的开端也是十分不顺,我们提交的第一发线上14s,这时候前排已经有0.x的成绩了,一度陷入深深的自我怀疑之中.好在队友 ...

  3. 2020华为软件精英挑战赛历程总结

    前言 历时两个月,终于结束了今年的华为软挑,这感觉就很爆肝.非常感谢队友们的强力输出.还有遇到的的大佬.成研所的小姐姐们,虽然成绩不佳,但还是分享一下我们每个阶段的成长. 首先简单自我介绍一下,我是I ...

  4. 2020华为软件精英挑战赛总结

    2020华为软件精英挑战赛总结 00 赛题描述 01 整体思路 02 数据读取以及正反向图构建 03 多线程找环运动 031 反向DFS 3层构建P3 032 正向DFS 4层找环 04 结果输出 0 ...

  5. 2020华为软件精英挑战赛——总结

    2020华为软件精英挑战赛 github:https://github.com/jadyntao/HuaWei_CodeCraft_2020 队伍:助教小分队(粤港澳赛区) 初赛:0.2102(赛区第 ...

  6. 2020华为软件精英挑战赛-有向图找环

    初赛找环,复赛还是找环.初赛没有用到权重(金额),复赛对数据进行加强,同时对相邻两次转账的金额做了限制. 初赛用的单线程,最好成绩:0.2854, 进入了32强.复赛用了多线程,A榜最好成绩:6.11 ...

  7. 2023华为软件精英挑战赛,探寻软件人才与科技创新的最优解

    作者 | 曾响铃 文 | 响铃说 今天,软件行业正呈现出江河入海一般的大汇流趋势. 一方面是技术的汇流,诸如人工智能等前沿技术与软件行业的深度融合,正全面颠覆软件产品的开发模式和服务逻辑. 另一方面则 ...

  8. 2016华为软件精英挑战赛:赛题及其答疑汇总

    注:本文文字均摘自官方指定网站和论坛,权威且可信,答疑见中间部分,非常全,众玩家可放心阅读. 同时文末给出了包括自己在内的诸多玩家的解法. 前言 赛题源自"未来网络"业务发放中的路 ...

  9. 2021华为软件精英挑战赛总结分享

    2021华为软件精英挑战赛总结分享 随着大赛的结束,自己的2021软挑也落下了帷幕,很幸运在自己学业生涯的最后几个月能够再参加一次华为软挑,虽然成绩不是特别好,但已经满足了.这是自己第二次参加华为的比 ...

最新文章

  1. [YTU]_2716 统计不及格人数
  2. 用python写一个简单的推荐系统 1
  3. sql输出带颜色的字段_带你走进MySQL数据库(MySQL入门详细总结一)
  4. windows制作定时关机脚本_自动关机、自动打开程序… 让Windows自动执行任何操作...
  5. NFC 验证平台搭建
  6. LeetCode 1887. 使数组元素相等的减少操作次数(map)
  7. hadoop--Shuffle机制
  8. 1 D触发器verilog与Systemverilog编码
  9. python显示图片_python 一个figure上显示多个图像的实例
  10. linux命令grep如何使用,Linux命令之grep命令简单使用
  11. Linux搭建深度神经网络,linux服务器搭建深度学习环境
  12. 在vpc 2007上安装 ubuntu8.04-desktop(多图解)(转)
  13. 激光打标机不能刻字的处理
  14. matlab2013基础教程,Matlab2013a教程
  15. MATLAB自带函数实现经验模态分解总结
  16. ExoPlayer播放器剖析(七)ExoPlayer对音频时间戳的处理
  17. SQL报错:Ambiguous column name ‘数据库某列’
  18. OI组合数学相关知识点
  19. 解决用联通看不了B站等问题
  20. 一根木棍随机折成三段,能组成三角形的概率多大?

热门文章

  1. 文件恢复 文件改名后如何恢复原来名称分享操作步骤
  2. 梦幻手游服务器维护摆摊公示时间,梦幻西游手游摆摊攻略 卖家关注公示期最重要...
  3. 小米9se是Android6吗,小米9SE评测 优缺点十分明显
  4. 微软Win11 Dev/Beta预览版22581.1(ni_release)发布
  5. 免费OCR图片文字识别小工具,一键提取图片中文字,支持多语言翻译和发票识别
  6. 轻松搞定RabbitMQ开篇:Java消息队列与JMS的诞生
  7. 计算机资源管理器出问题怎么办,W7系统资源管理器已停止工作怎么办
  8. 2021-2027全球与中国电动垂直起降(eVTOL)飞行器基础设施市场现状及未来发展趋势
  9. ROS TF 常用接口函数
  10. ubuntu 20.04添加ubuntukylin源安装 应用的办法