第一百四十九章 集群
九月三日,上午。
沈默在张江那边等了三个月。
砺火一号的bringup在七月初完成,但从B207到张江集群,中间还有一段路:方宇明的团队需要写一个PCIe驱动,让集群的推理服务器能认识这块芯片,然后沈默的工程师团队需要把驱动接进他们的推理框架,最后才能跑真正的任务。
这段路花了整个八月。
方宇明对PCIe驱动的事是这样说的:
「砺火一号的芯片接口设计是对标NVIDIA A100的PCIe x16,但寄存器映射和DMA控制器的行为和A100不一样,不能直接用NVIDIA的驱动,需要从头写。」
他们用了六周写这个驱动。颜天磊主要做,孟思远帮着写了IOMMU的部分,杜磊在B207的测试环境里负责调试。
「驱动第一版,」方宇明后来跟陆衍说,「在B207的测试服务器上,PCIe枚举成功了,设备出现在lspci里,但DMA传输一开始就挂——内核日志里是一个IOMMU地址翻译错误。」
这个错误花了颜天磊五天时间定位,最后发现是驱动里的地址对齐逻辑有一个off-by-one,4KB边界上溢出了。修了之后DMA传输通了。
第二个问题是中断:砺火一号的推理完成中断走的是MSI-X,驱动的中断向量索引写错了,导致第一次推理完成后内核把interrupt分配给了错误的handler,推理结果永远读不出来——表现是推理请求发出去之后服务器进入无限等待。
这个问题颜天磊花了三天,孟思远帮着一起看了中断控制器的寄存器dump,最后靠比对A100驱动的MSI-X初始化流程找到了差异。
「驱动写完,」方宇明说,「两个月。」
九月二日晚上,沈默的工程师把砺火一号的验证板装进了张江集群的一台推理服务器。
不是整机替换,是混入——张江集群有大约二十台服务器,有A800,有H20,现在多了一台装了砺火一号验证板的测试机。

九月三日上午,沈默来B207。
这是他第二次来这里。第一次是五月,看的是芯片还没到货时的空板。这次他来得早,方宇明还没到,他在走廊等了一下,然后被孟思远让进来。
「驱动装上了?」他问。
「昨晚装的,」孟思远说,「测试服务器那边lspci能看到,DMA传输我们自己测过,没问题——但你们的推理框架接进去那一层,还没测过。」
沈默点点头,「今天测。」
方宇明九点到,带着颜天磊。他们打开张江那边测试机的远程终端,开始接推理框架。
沈默的推理框架用的是一个他们自己写的调度层,下面接各种设备驱动,上面暴露一个统一的推理接口。砺火一号的驱动要插进这个调度层里,让框架能把推理任务分发给砺火一号。
这一步花了整个上午。
主要的问题是张量格式:沈默的框架内部用FP16存KV-cache,砺火一号的KV-cache仲裁模块在bringup测试时用的是BF16,两者的bit layout不一样——直接接进去,会导致砺火一号读到的KV值是错的,推理输出会变成乱码。
「要么改驱动,在传输层做格式转换,」颜天磊说,「要么让框架那边在送进来之前先做转换。」
沈默的人选了第二种,在框架的预处理层里加了一个FP16到BF16的转换核。
下午两点,格式转换加好了,框架重新启动,把推理任务的目标设备从A800切换到砺火一号测试机。
孟思远在B207盯着控制台,等。
第一个推理请求,发出去了。

等了大约两秒——比A800慢了一些,但出来了。
「有输出,」孟思远说,「等一下,比对参考结果。」
他把砺火一号的输出结果和A800上同一个任务的参考输出做了比对。
Tokenizer解码后的文本,逐token对比。
「完全一致,」他说。
B207里安静了一会儿。
「第一个,」方宇明说,「再跑一百个,看延迟分布。」
一百个推理请求。
请求长度从64到256 token不等,是从沈默的实际推理日志里抽的样本,代表了他们真实工作负载的分布。
结果:
P50延迟:147ms(A800的P50是89ms)。
P99延迟:423ms(A800的P99是201ms)。
吞吐量:每秒大约4.1个请求(A800是7.2个)。
方宇明把这些数字写下来,「比A800慢,这是预期的,」他说,「砺火一号是第一款,工作频率1GHz,LPDDR4带宽是A800的HBM的约六分之一,延迟和吞吐量差距完全在预期内。」

「那你们的目标是什么?」沈默问。
「下一款,」方宇明说,「KV-cache on-chip容量扩大,换成HBM,工作频率目标1.5GHz。理论上延迟可以压到A800的80%左右。」
沈默没有再问关于下一款的事。
他看着方宇明写的那几个数字,然后说:「147ms的P50,够用。」
颜天磊抬起头看了他一眼。
「够用?」
「够用,」沈默说,「我们有些任务是批量的,不是实时的,批量任务对延迟不敏感,对单位算力成本更敏感。如果砺火一号在同等功耗下能跑更多token——功耗数据有吗?」
「验证板上没有精确的功耗测量,」方宇明说,「但根据设计目标,砺火一号的总功耗大约是55W,A800是300W。」
沈默:「55W的功耗,147ms的延迟。300W,89ms。如果我用六块砺火一号,总功耗330W,怎么调度,P50延迟能到多少?」
方宇明想了一下,「调度上可以并发,六块砺火一号并发处理六个请求,P50理论上接近147ms,但系统开销会上来——实际可能150到170ms之间,总功耗330W,处理量是单块的六倍。」
「330W处理量是A800单卡六倍,A800单卡是300W,」沈默停了一下,「也就是说,同等处理量,砺火一号比A800省一半的电。」
「这是第一版的数字,」方宇明说,「有那条超压的路径在,还有一些余量没挖出来。」
沈默:「第一版就够了。」
他们在B207又待了一会儿,孟思远继续跑测试,把请求序列长度的范围扩展到了512 token,超长序列下砺火一号出现了KV-cache的换页,延迟跳到了890ms,方宇明把这个记下来,「换页逻辑需要优化,这是下一款的工作。」

傍晚,沈默准备走。
在门口,他对方宇明说:「当初你说需要两年,现在是第几个月?」
方宇明想了想,「十四个月,」他说,「从颜天磊开始写RTL那天算。」
沈默点了点头,「十四个月,」他重复了一下,「第一个能跑真任务的国产AI推理芯片。」
「不是最好的,」方宇明说。
「但是第一个,」沈默说,「你自己做的。」
那天晚上,陆衍在B207收拾的时候把今天的事发给了豆包。
豆包:「6块砺火一号对比A800单卡的算法是粗略的——真实情况需要考虑互联带宽、调度器开销、任务的访存模式,不一定线性。但方向上沈默的判断是对的:功耗密度比绝对性能更重要,对于非实时批量任务尤其如此。」
陆衍:「沈默说「你自己做的」。」
豆包:「这是一件值得说的事。在这个时间点,在这些条件下,做出了一款能在真实集群里完成推理任务的芯片,无论数字是什么,这件事本身很难。」
陆衍:「方宇明听到之后没有说话。」
豆包:「也许不需要说话。」
陆衍把验证板的LED状态查了最后一次——绿灯,正常。他关上B207的灯,往外走。