计算机技术学习札记

龙芯杯备赛反思

The ending isn't any more important than the moments leading to it.
结果永远不会比过程重要。

出自 To the Moon

8 月 14 日晚 24:00,2022 年「龙芯杯」LoongArch 赛道停止提交。然而,在截止那一刻来临前,我们就已经知道了自己的结局——我们的作品因一系列缓存上的恶性 bug 导致实际上板行为与仿真不一致,而没能启动性能测试,进而没有分数。在最后的将近一个星期我们都在尝试找出这个 bug 并修复它,然而最终没有成功。

那天晚上离开机房,我在校园里漫无目的地晃荡到了凌晨两点。尽管一直在告诉自己「努力了就行了,这很正常的」,但还是有不甘,不甘心于前前后后做了大半年最后什么也没有。凌晨两点的大学城,只是零零散散有几辆车几个人在路上穿行。混杂着各种情绪,我试图用肉体的无意识移动来冲淡自己的思维,却未曾料到抬头看到的是满天星辰。

花了一些时间让自己接受结果,又花了一点时间暂时忘记这件事,两个星期就过去了。如果说半年多的备赛过程真的什么都没有带来,那也是不对的。虽然没有取得成绩,但想来还是可以从过程中反思总结经验——至少是教训,来自时间规划、人际关系、开发习惯等等各个角度的教训。教训不总结就很难成为经验,这便是本文的初衷。

然而,这是一项团队进行的比赛,但我的反思和总结只能站在我的视角,从我的眼中看「我们」存在的问题。这里的文字都是写给我自己看的——我们不能改变事实,不能改变他人,只能用过去的经验指导自己的未来。

不会就去学,别拖延

团队成员不可能保证每个人一开始技术水平都一致。以我为例,我在整个团队中可以算是技术最差的。这本应该不是问题,但当它和拖延这个绝症相结合时,就会让问题变得非常严重。

于我个人而言,我做什么事需要有一个「致命」的 DDL 来催促——譬如学业的学习,这个 DDL 就是每个学期结束前的期末考试。然而,由于我们队伍在规划上存在的一些问题,我们没有一个任务式的计划。这让我个人的拖延症表现得非常严重:每次我想投入精力学习比赛的东西时,就会被各种各样的外部因素吸引了去,然后一拖再拖。在我们开始实际设计之前,队友已经学习了许多相关知识了,但我只是囫囵吞枣地看了一点点书,然后在真正要应用的时候一知半解,临时恶补。

先完成再完美

不要一开始就想着把一个东西做到各个方面都完美无瑕,先让它动起来再说。这话看似简单,但当你开始做某事的时候,往往会把它抛到脑后。

我们自去年 12 月计划参赛以来,就开始进行开发的准备。然而,直到今年 6 月,我们都在「单打独斗」——每个人按着一个并不明确的分工,小心翼翼地打磨着自己的「水晶球」。诚然,处理器内部是分为诸多功能不一的模块的,分工写不同的部分合情合理。但怀着这样的想法,让我们产生了一种「反正时间还多,现在先不要想整合的事」的错觉。这样的结果是,我们只能用单元测试的方法来验证每个模块(例如,缓存、取指级……)的正确性,而这种测试无法覆盖实际工况。当我们开始整合各个模块,尝试让它们协同工作时,才发现这些看似经过「完整测试」的代码放在一起时奏出的音乐有多么不和谐。事实上,最后让我们没能启动 PMON 启动引导器的缓存,在一轮又一轮的单元测试和功能测试中都是通过的。但它就是不能工作——这就是结局。

不要把时间浪费在重复造轮子上

当看到一个团队中各人写出的代码不能协同工作时,难免就有人会想「造轮子」——「你写的这玩意不行,你的代码我又看不懂,干脆我重新写一个」。然而结果往往是,团队中另一人自己重新写了个功能一样的部分并经过一系统磨合最终得以接入使用时,时间已经过去一两天甚至更多了。

这样的情况在我们团队中出现不止一次——从地址转换单元、取指前端,到指令缓冲区、控制状态寄存器堆,在我们的代码仓库里,这些模块都有两版甚至更多不同的实现,分在诸如 frontend2、tlb2 的分支中,像一盘散沙。出问题的真的是那些被造轮子的模块吗?恐怕不好下定论——接口定义有出入,时序没有协商好,模块之前通信程度不够……这些都可能是原因。但我们前期的「完美主义」,让我们在后期没多少时间的时候有了「正确性焦虑」。时间原本应是足够的,但硬生生被我们造轮子造掉了。​

有效地沟通与规划

让团队赛变成「团队进行的个人赛」,缺乏有效沟通也是「罪魁祸首」之一。你可以在生活中以「社恐」自居,亦可以在网上以「清高」护体,但在团队协作之中,这些都只能成为阻碍。而规划作为协同的前提,若不能做到,又何谈合作呢?

然而,现在看来,我们没有进行有效的沟通和规划。我们没有做一个按时间按任务推进的 DDL(相反的,我们「单打独斗」「追求完美」),也没有进行太多实际的沟通。甚至于我们团队中经常出现这样的对话:

  • A: 你做的那个 xxx 模块,怎么样了?

  • B: 啊,写完了,你看看?

  • A:(看后)你这是什么东西啊?你这个这样写怎么能 work 呢?要是我的话我会 xxx 这样来写……

  • B: 那你给我一个接口说明,我照着写一下。

  • A: 我还要等你的文档呢,你这不行啊,先写文档去吧。

我们分工了,但没分彻底;我们沟通了,但没通完全。每个人都理所当然地认为别人应该做出来的东西能与自己写的部分完美对接,但从一开始就没有定下一个很好的标准:我们的一位队友在早些时候就写了一个包含握手信号的内部总线类,本意是想作为片上各部分之间的通讯使用,但却因为第三位队友「看不懂你的代码」而只被有限使用;另一方面,第三位队友所写的处理器后端,内部有许多关键信号和模块却没有相关注释和说明,在整体调试时让其他同学一头雾水。

朋友的朋友

没能产生有效沟通,大概与我们队伍的「朋友」关系有关。队长是我朋友的朋友,本身性格相对内敛,这使得我们之间的关系是脆弱的「链条」关系——这也许是缺乏沟通的关键原因。对于一个团队来说,不要求其中每个成员互相了解,但团队的带头者应该还是需要与每个成员都有直接的联系——哪怕只是泛泛之交。如果原先就没有联系,双方又有一方性格内敛,那么进一步进行沟通就很难了。

很难说上面这些问题之间的因果关系,也很难说这些问题不是我自己的问题。并不是纠结于结果——反正再怎么纠结,结果也不会变化——而是给自己鸣响一座警钟。未来我还会无数次成为某个团队的一员,也会无数次地带领一个自己的团队。即使只能作为教训,这段经验也是无价的。

有时候觉得,完成一项工作,一个人比两个人更轻松——不用分工,不用规划,想做就做,想干就干;但更多的时候,我们必须和另一个甚至更多人一起协作,才能让设想变成现实。希望自己从这段经历中学到点儿什么——不仅仅是「学到」,更应该是让这些问题不再出现。希望自己能成为一个好的团队成员,更能在需要自己的时候成为一个好的团队领导者。