第117章 大杀器(2/3)
第一层,抽象原语层。
排序、选择、求秩、中位数、top-k等微内核,首先在纯粹的数学语义上被定义得滴水不漏。
输入的数据分布是什么?
输出的排序稳定性要求是什么?
是否允许数组中存在重复值?
算法边界是否存在哨兵机制?
最重要的是,整数比较、浮点运算中的非数字以及带符号零的特殊值处理,必须在这一层就明确分流。
第二层,源码与中间表示层。
到了这一层,无论是c代码、LLVm IR,还是手工编写的Intrinsic内联函数,都绝对不允许用一句轻飘飘的它看起来等价糊弄过去。
c语言标准中恶名昭彰的未定义行为、有符号整数溢出的未定义行为、无符号整数的模回绕语义、不同宽度整数转换时的截断规则、浮点比较中的NaN传播、正负零排序、舍入模式、异常标志,以及不同平台对denormal数的处理,全都要在这一层被数学逻辑无情地拆开揉碎,确保IR在被声明的语义子集内,与上层抽象语义保持一致。
第三层,机器码层。
这是最贴近金属的领域。
最终生成的二进制指令序列,必须能够逆向回连到上层语义。
无论是高效率的条件传送cmov、向量混合blend,还是用于打包求最小值的pminsd,甚至是几条为了避开流水线冒险而看似绕远路的逻辑指令组合,都必须由系统自动给出严格的逻辑等价证明。
裴砺在办公室里那个关于规模化的刁钻问题,直到这一年,才在废土的黄沙中,得到了江临用代码堆砌出的工程回答。
零一验证器从来都不是终点,它不过是一条通向微内核工业化的坚固证明链的第一环。
第十九年,江临迎来了另一个巨大的挑战。
代价评估后端重写。
旧版本的代价模型天真得可笑,它只会根据静态的指令周期给出一个冰冷的排名。
第一名,理论上看起来最快。
第二名,看起来慢一点。
但在真实的冯·诺依曼架构机器上,硅片不是干净的数学纸面,它充满了物理世界的狂躁与不确定。
L1/L2缓存命中率会随着上下文波动。
操作系统的线程调度会随时引发中断。
cpU的睿频机制会因为热量的累积而动态改变工作频率。
不同的处理批量大小会彻底改变流水线的吞吐瓶颈。
同样一段看似完美的指令,在机器A上巧妙地避开了执行端口的拥堵,到了机器b上,可能正好一头撞进分支预测器失误的惩罚陷阱中。
所以,江临彻底推翻了旧后端。
新后端不再输出苍白无力的单点分数。
对于每一个候选的微内核,它输出的是三组立体的评估。
理论代价: 基于微架构模型的纯静态计算。
实测分布: 候选微内核必须在多种缓存冷热状态、多种批量长度、多种代码预热方式、甚至多种强制锁频条件下,进行数万次的重复测试,绘制出执行时间的概率密度分布图。
鲁棒性评分: 衡量代码在恶劣硬件噪声下的抗干扰能力。
最终被mpS-Kernel保留下来的,绝对不是某一次特定benchmark跑分中侥幸跑出的冠军。
而是在排除了所有硬件环境噪声窗口之后,其性能底线依然能够稳定领先其他方案的铁血候选者。
第二十四年,工作站风扇发出一阵持续的嘶吼,mpS-Kernel终于生成了第一批真正意义上的证据卡。
本章未完,请翻下一页继续阅读.........