如果你在开发项目里用过 i9-13900K,可能也遭遇过这种情况:程序跑得好好的,突然间就崩了。检查下来,问题竟然出在 CPU 的供电电压波动上。对于开发团队来说,这类硬件缺陷我们无力改变,但应用又必须要跑起来。 于是我们决定换个角度——从代码入手,看能否通过分析调试,来降低故障率。这篇文章,就是这次尝试的复盘记录。
关注腾讯云开发者,一手技术干货提前解锁👇
游戏启动编译PSO的时候会偶尔出现崩溃在shader编译或者驱动里面:
在看到设备详细信息后,第一印象就是CPU故障(i9-13900K的故障率实在太高了),但是在这个机器上多次运行其他游戏以及AIDA64、IPDT等多个测试工具,并没有发现问题,所以首先排除了这方面的可能性,
然后开始了踩坑过程:因为总是崩溃在和dxilconv相关的地方,所以怀疑传递给dxilconv的数据错了,找到dxilconv的源码https://github.com/microsoft/DirectXShaderCompiler.git,编译调试各种折腾,直到截获了一次非常重要的证据,重新把问题聚焦到cpu上:
很明显,rbx+8这个地址上保存的值不为0,但是读到rax的时候变成了0,这是非常明显的cpu的问题,同一天机器也出现了蓝屏,至此,已经可以下定论:这颗CPU是存在江湖传言的缩缸故障的。
但是,为什么之前运行其他游戏和benchmark不会出现问题?
是不是意味着有方法可以通过程序的手段降低CPU的故障率?
经过多次对比测试,发现PSO预热和AIDA64不同的地方是:
AIDA64是所有线程都跑满的
PSO预热是单线程跑满,其他线程空闲:
抱着死马当活马医的心态将PSO预热改为多线程,跑满所有的核,最终的结果令人振奋:
修改前基本2到3次就会出现crash,修改后连续启动20+次,都没有crash,同时速度从20多秒下降到不到3秒,时间基本差了一个数量级。
Intel曾经对类似的问题做过调研,据说是因为主板过于激进的供电策略加剧了CPU故障的出现
具体到本例满负荷运行没问题,单核满负荷有问题的可能原因,个人推测的原因如下:
主板上对CPU一般采用多组开关电压通过PWM(脉宽调压)方式供电(多相供电),但相数通常少于核数,这种情况下必然会有多个核共用一相供电。当共相的多核中,如果只有其中一个核满负荷的话(假设PWM输出到各个核的线路电阻基本一致),这个核的供电电流必然比其他核大,供电线路的电压降也会增大,实际加到工作的晶体管上的电压相对其他空闲核就会下降,此时主板对CPU供电面临的问题是:
如果增加脉宽提高输出电压,那么空闲核的电压就会升高,很可能会引发过压问题(老化加速和击穿)
如果不提高输出电压,满负荷的核就会欠压,导致逻辑电平0和1区分不开(眼图睁开不够高)
主板供电策略难以兼顾,很容易就会引起故障,但当所有核都处于满负荷的时候,供电都是平衡的,反而不容易出问题。
但由于没有硬件测试环境可以证实,以上纯属推测,如果有大神能够给出明确的结论,请不吝指教。
-End-
原创作者|柯达昭