0%

毕昇杯比赛心得

毕昇杯心得体会

这里记录一下2023年华为毕昇杯比赛心得经验。仓库链接

经验

  1. 做的优化及时合并,虽然自己写的优化跑通了,但是加上其他队友的优化之后往往会浮现出新的bug,要尽早解决。
  2. 编写好用的调试工具,段错误的时候可能打印都打印不出来信息(需要刷新缓冲区),这里建议写一个比较好用的log工具,我们直接把PA实验的Log工具搬过来了。
  3. 编写数据结构合法性检查工具,对于ssa形式的ir中间代码,维护每个operand的def和use的正确性非常重要,这里建议编写检查工具,每执行一个优化pass都进行检查,尽早发现问题,否则可能会导致其他优化不充分或者优化错误。
  4. 尽早调bug,虽然有的bug可能显得不是十分严重,但是也许这些bug是由比较严重的错误导致的,或者会影响其他优化,这里发现bug一定要尽早解决,拖到最后会让人手忙脚乱。
  5. 进行良好的内存管理,如果使用C++进行项目编写,要注意释放内存,否则有时候可能会出现莫名奇妙的错误,尤其是使用STL的时候。可以学学智能指针。
  6. Patience is the key of life. 要对自己和自己的代码有耐心,往全面了想,只要我们做的比别人更加全面,我们就胜利了。不要着急写出来优化,先想好再编写往往会更快,bug也更少。如果发现没得优化了,就停下看看其他优化是否还有不足,灵感往往是周期性来的,只要编译出来的程序每天都更快一点点,最后就可以快很多。
  7. 多和队友沟通交流,多push队友,遇到自己解决不了的及时和队友商量。不只是队友,也可以多和其他参赛队沟通,大家互补起来可以起到共赢,比如我们决赛的时候就得到了兄弟队伍的帮助,性能分直接++。(当然这个也要分时候)
  8. 代码的可扩展性和可复用性很重要。前者可以使我们以最快的速度添加新的改进(比如我在决赛最后只花了将近30分钟添加了几条新的指令,把一个样例优化到了最好);后者可以降低我们的代码量和debug量,这里建议把一些常用的比如lva分析、define reach分析、循环相关的分析、纯函数分析等单独编写为工具类。

具体细节

  1. 寄存器分配是最重要的环节之一,别用课上给的线性扫描,又慢生成的指令溢出还多(但是简单好实现)。推荐对线性扫描进行改进,比如使用greedy,或者实现图着色寄存器分配(我们的选择)。此外,尽可能多的使用寄存器,比如我们除了R0-R10,还使用了ip寄存器和lr寄存器,可用的寄存器越多,溢出越少。
  2. 纯函数可以看作表达式,因此做gvn或者cse的时候可以考虑把重复的纯函数也删除了。
  3. 做后端优化的要对汇编代码有较清晰的了解,选择合适的汇编指令,尽量减少访存操作。比如把立即数加载到寄存器中的时候,别一个劲只用ldr r0, =1这样的伪指令,可以根据立即数的范围来选择使用mov或者mvn指令,有的浮点常数也可以直接vmov.f32到s寄存器中。还有就是了解arm的寻址方式,ldr和str的地址操作数可以有好多种不同的形式。等等等等。
  4. 对于某些递归导致栈溢出的程序,做尾调用优化可能比尝试减少栈空间消耗来的更快。
  5. 注意栈对齐,尤其是代码中有浮点数的情况,栈不对齐可能会导致结果为0(这个特征比较明显,就是最后打印出来的浮点数很多是很小的数)。
  6. 学学文字池是干啥的,这个用的好了也可以减少一些多余的指令。
  7. 想得一等奖,得做并行优化。