本文来自 开心的小福,欢迎关注作者。
本文已经作者授权,原文链接为:编译器工程师的一天
最近要招个26届的实习生,大家最多的疑问是,编译器已经非常成熟稳定了,进去是不是没有趣的活可干,大多数时间跑测试,改改简单的bug,偶尔加几条新指令的时候写会描述文件。甚至前天工友在饭桌上也问了一样的问题。
其实我入职前也是这么想的,可以说我就是冲着这么清闲才来的,没想到会这么充实。本文从任务的来源给大家介绍我们的日常工作,顺便再收点实习生简历,准备要安排面试了,如果你们转正的话我还能挣点内推费。总的来说,我们的活非常的工程,但如果想发论文、写专利老板也是支持的,只要新东西能“广泛”地有效。我入职伊始(22年)曾问老板是否考虑过现在很火的多面体技术,老板直接回绝,因为编译时间和代码质量实在是不可控。1 日常维护
世界成千上万的开发者以及内部的工程师每天都会用到我们的编译器,相当于对编译器的DDOS攻击编译器毕竟也是人写的,我们只能尽量减少出现BUG的概率。有些BUG很显而易见,如参数写错了,或corner case没判断就加个if-else,确实很无聊。
但有些BUG藏得比较深,需要对整个编译器都非常熟悉。时常会出现以下情况,一开始怀疑是PASS A,为了搞清楚A干了啥和哪里可能出错,需要看很多次文档/代码/论文。结果发现是另有其人,循环该过程,直到找到最终出问题的PASS。刚入职时,老板故意随机分配各个模块的BUG给我们,以便快速熟悉整个系统。我也比较认同修小BUG->大BUG->加feature的路径。年初加一个新PASS的时候,对它的位置我们就讨论了许久,放在位置A好实现,但是会错过后续转换暴露的优化机会;放在位置B,得到的分析结果更精确,但如果边优化边维护分析结果的准确性,会让编译时间变得太长。这都需要对整体有清晰的认知。偶尔会碰到疑似DRIVER的锅,就得去问东问西,能学到一些未曾设想的操作。2 硬件迭代
不知道CPU厂商们每一代的微架构调整幅度如何,但这边代际升级确实会给编译器工程师带来不小的工作量。除了写在白皮书上公开的那些,有不少不公开的,只需编译器和驱动去适配。就拿加新指令来说,也不止是加个指令选择就结束了,有些指令对寄存器分配、指令调度都有要求,还有一些面子大到要专门写PASS去处理,搞不好误伤其他程序的性能,又得去调。为了节省工作量,一些现有的逻辑是处理一类指令,如果这类指令里新加了一个另类,破坏了原来的某些“假设”,就搞出很隐蔽的BUG。为了处理这个刺头,可能整个逻辑都得重写,甚至另写一些分析(比如时常要处理包含乱GOTO的控制流),非常头疼。迭代的多了,一些从十几年前流传下来的代码可能就不适用了,有两个弊端:- 代码可读性低,有些代码对近代架构没用,新人(比如我)不敢删,也不知道在哪加新功能。就得花时间去读古老的文档和提交历史。但可以安慰自己对硬件演化了如指掌... 这就是俗称的“屎山”。
- 为旧架构设计的算法和模型不再准确。如果没人记得或是没时间细究,它们就一直跑着,直到有人DEBUG到,实在受不了了再重写。
新特性不断涌出,加上各种突发情况,所以积累了很长一段TODO LIST,实习生有空可以挑几个来做做。因为要支持各种特性,碰到名字看起来有趣的,我就在内部搜罗资料,并BFS看关联的特性。偶尔会对比学术圈的论文,研究下为什么和我们的做法的优劣。关于硬件对编译器的影响,大家也可以参考intel graphics compiler的报告,虽不足说“颠覆”对教科书上造成的对CPU编译器的印象,但也可管中窥豹,略知工业GPU编译器师都在干什么。严格来说,硬件迭代也属于内部需求,但这里侧重其他软件变革造成的影响。
在“框架->库->编译器<->驱动->硬件”层次里,经常会出现多层级的联动,而且这样的项目出现频率不低。
但大多数时候是比较朴素的联动,比如写库的工程师,为了追求极限性能,经常能试出编译BUG和优化没到位的地方,导致每次吃饭,我都会被投诉一番。
4 其他疑问
Q1: 传统的编译优化(特指LLVMGCC完成的)累死累活性能提个(0%,10%)有何意义?A1: 还真不止。编译器的性能贡献主要取决于硬件设计,一些特性实现在硬件里不值得,会把锅甩给编译器。大的就比如我们得在编译器实现伪Tomasulo。另提一点,AI编译器高层转换完,直接映射到microkernel,似乎可以抛弃掉大部分传统编译器里的优化,这点我确实认同,而且也建议朋友在他们的研究项目里这么做。但世界上不止有AI程序,游戏佬的命也是命!Q2: 需不需要精通C++,对C++标准倒背如流?A2: 主要用C++1,不鼓励过度用“高大上”的模板,不需要语言律师我们平时也不需要对着规范来实现。只要不犯“返回对局部变量的指针/引用”这类低级错误即可。另外,我个人不赞成使用RUST。A3:有耐心,会写C++,能读源码,学过体系结构和编译器,熟悉LLVM最好。大多数命令式编程语言的工业级编译器都大同小异,有Hotspot C1/C2,GCC或V8经验的转过来也就一两个礼拜的事情;有AI编译器/推理框架经验的也很好,反正都是摆弄I,只是需要更细节的体系结构知识,可以边干边补;如果先前写算子/shader调优,也非常欢迎,我认为肯定熟悉体系结构,入职前有一堆时间补编译器知识。我入职的时候,老板表示对校招生要求并不高,可以在实践中培养。对实习生理应更加宽容,所以我出的题也是以考概念为主... 关于BG要求,可以以我的为参考,我是末流985计算机专业,后考研到中科院计算所学习编译优。编译器本质上还是干工程,无它唯手熟尔,周边同事同学其实鲜少是本科就是计算机专业,因此我认为,只要智力水平同我相当,都有潜力成为合格的编译器工程师!A4: 鉴于代码和搭环境的难度(尤其是前者),不建议远程,base上海。如果让我赚到内推费,将赠送本人1v1教学的编译器、体系结构和cp课程若干节。A5: 每天都要用英文,我自己四六级都是460分,经过两年的捶打,听说能力也还算合格。teams的实时字幕降低了一些难度。Q6: 需要会程序语言理相关的知识吗? 如类型系统客观来讲,编译器方向薪资一般,难度大,需求量极小,成就感也因人而异。
具体来说,薪资远不如算法和大模型工程,需求量远不如JAVA/GO等后台开发(在市场机制下,需求量大的岗位通常薪资也水涨创高)。
在2021年我秋招时,局面和今日并无本质差别,只是大模型相关岗位换成了IC设,数据库和自动驾驶,当年本人也蠢蠢欲动,也拿了若干其他方向的offer,但最终还是做编译器,原因如下:1. 芯片需要编译器。一直有新的芯片,就一直需要编译器工程师。3. 竞争少。经验在这一行非常重要,不是随便拉个人培训几个月就能放手去干,这确保了不像后台开发那样,每年有数以万计的新鲜牛马来卷我。而且据我经验,大多数人都选择了“当下”话题度最高的方向,比如本科同学院的很多就去做了IOS/安卓开发,硕士期间认识不少跨行转去做数据库,反观LLVM,像坨屎一样没人去炒。4. 对其他方向实在无感。一如当年思想政治考了27分迫使我在最后十分钟弃文从理,我一看到“双亲委派”,“GO协程调度器”,“JVM垃圾回收”,“C++对象布局”类似的字眼就想睡觉。不过我对数据库颇有兴趣,但当时的判断是,基于技术角度,新兴数据库如何证明自己的稳定性?5. NVIDIA发了OFFER。当时我都没验证OFFER上的薪资就签字了,是基于一种朴素的情感:我想知道世界上最酷的公司到底在干什么。十几年前,我妈给我买了一张NV显卡,回家直接打开了<孤岛危机>最高画质,从那一刻起,加入NV就已经和金钱无关了,稍微理性点说,就做(AI/LLVM/GCC)编译器而言,我更倾向于去芯片厂体验一下,一来是有最准确的资料和回复;二来厂商主业就是把卡卖出去,编译器还算比较重要的一个环节,好歹是在核心链条上,"又不是不能用”有时候行不通…6. 加入一个好团队,比自我奋斗省力。匹配度最高的几个OFFER里,我认为还是核弹厂最有前途...另外,我非常赞同“nv中国没有核心技术,不建议去”的论调,可以过滤掉不少竞争对手,一位同年秋招的老友就因此放弃了NV,只是现在时常感叹。