CHAPTER 48 / Cerebras · 晶圆级计算

功能模型、simulator 与硬件:分别证明什么

测试全绿之后,哪些结论仍然不能写?

阅读与推演约 55 分钟练习时间另计

这一章要弄清楚

  • 分开数学模型、SDK simulator和硬件证据
  • 设计边界与变形测试
  • 用事件记录定位未完成协议

先备知识:测试与调试:独立定位失败 / Reduction、scan 与数值正确性 / 多PE scan:消息里到底应该传什么

C++20 本机逻辑模型;不是设备仿真或性能测量。厂商语法片段未在设备或 SDK 执行,实际 API 以匹配版本的公开文档为准。

先写下测试正在证明的命题

“程序通过了”至少可能指三件不同的事:C++数学模型产生正确答案;真实CSL程序在SDK fabric simulator运行并符合预期;同一程序在目标硬件上运行正确。这三个层次都可能有价值,但不能互相替代。自写几个节点的C++循环不是厂商simulator,也不包含其指令、任务和路由语义。

本章只运行原创CPU模型。它能快速枚举小输入,帮助在接触复杂设备环境前发现数学和分区错误。将这类结果写成“设备模拟通过”会夸大检查范围;把真实SDK simulator的运行时间当硬件耗时,也会混淆模型与实际机器。

Oracle要足够独立

例一用简单顺序求和作oracle,再用分块求和作candidate。输入长度从零到四,每项从负1、0、2中选择,一共有121个小案例。穷举覆盖空输入、单项、零、负值和尾部分块,却仍不是对所有整数输入的证明。这里取值很小,避免signed overflow;真实大输入需要明确范围或更宽累积类型。

若oracle与candidate调用同一个分区函数,同一处漏项可能在两边都发生。尽量让reference简单、独立、容易手算。设备程序还应测试边缘PE数量、不能整除的长度、空分区、最大合法容量和连续多次调用;前一次状态残留经常不会在单次成功中显现。

变形测试把性质变成检查

当全部期望值难以手写时,可以检查数学性质。求和在无溢出的整数合同下,追加零不改变结果,复制序列使总和加倍;scan的最后一项应等于总和,但这只是必要条件,不能代替逐位置检查。浮点情况下这些关系可能受到舍入影响,必须说明容差与前提。

例二检查一段原创消息记录是否包含规定数量,并按序到达。三条正确消息通过,缺失一条被拒绝。记录检查并没有运行通信,也不能证明实际任务无死锁;它展示应记录哪些信息,才能从“卡住了”走向一个可定位的等待条件。

Debug输出和性能记录各有边界

Cerebras公开debug教程介绍把值与时间信息记录下来供host读取;simprint教程提供在simulator日志中输出信息的方式。日志可以帮助找出最后到达的节点、未更新的计数或未完成的阶段。不同工具有不同输出和完成要求,应按匹配版本使用。

不要把添加大量日志后的执行成本当最终性能,也不要删除所有日志后就宣称问题修复。保留最小复现、输入、版本、编译参数、运行命令及原始输出,才能让另一个人重复同一结论。模拟时间、host墙钟时间和硬件设备计时需要不同标签。

失败也是有价值的结果

超时可能表示死锁,也可能是配置、资源或运行时间预算问题;要看最后可观察事件,不先下结论。数值不匹配则先定位第一个错误坐标,再追溯其输入和消息。容量拒绝如果符合接口合同,应单独记为预期错误,而不是与正确数值案例混成一个成功率。

面试时可以说清当前通过了哪些输入、哪种执行环境、哪些性质,以及还缺什么验证。这比一个没有范围的“100%正确”更可信。以后具备SDK或硬件条件时,追加新证据层即可,不需要改写已有CPU模型的身份。

观察 · 推演

一条缺失消息如何被拒绝

expected0 1 2count301 / 03 · TIMELINEexpected0 1 2count301 / 03 · TIMELINE
合同

预期三条有序消息。

1 / 3
阅读完整推演文字
  1. 合同

    expected:0 1 2;count:3

    预期三条有序消息。

  2. 观察

    observed:0 2;count:2

    第二条消息缺失。

  3. 判断

    complete:false;next:追查序号1

    数量不符先拒绝,不能宣告完成。

跟着例子,走完一遍

例题 01C++20 · 本机可运行

121个小输入交叉验证

长度0–4,每项取-1、0、2;块大小3。

  1. 枚举每种短输入
  2. 顺序和作oracle
  3. 分块和作candidate并比较
44-a.cpp
下载
// Original CPU teaching model; not a device simulator or benchmark.
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <stdexcept>

void require(bool ok) { if (!ok) throw std::runtime_error("model check failed"); }

int chunked(const std::vector<int>& a) {
 int total=0;
 for(std::size_t base=0;base<a.size();base+=3) {
  int local=0;for(std::size_t i=base;i<std::min(base+3,a.size());++i) local+=a[i];total+=local;
 }
 return total;
}
int main() {
 int cases=0;
 for(int n=0;n<=4;++n) {
  int combinations=1;for(int i=0;i<n;++i) combinations*=3;
  for(int mask=0;mask<combinations;++mask) {
   int code=mask;std::vector<int> a;const int values[3]={-1,0,2};
   for(int i=0;i<n;++i){a.push_back(values[code%3]);code/=3;}
   require(chunked(a)==std::accumulate(a.begin(),a.end(),0));++cases;
  }
 }
 require(cases==121);std::cout<<"cases="<<cases<<" mismatch=0\n";
}

如何编译和运行下载的 .cpp 文件 →

结果与解释

cases=121 mismatch=0。

只覆盖这套小输入,不证明任意输入或设备程序。

在本机运行这个例子

下载后,在文件所在目录执行。需要支持 C++20 的编译器;POSIX 示例还需要章节说明中的系统条件。

clang++ -std=c++20 -Wall -Wextra -Wpedantic -Werror -pthread 44-a.cpp -o example && ./example

预期标准输出:

cases=121 mismatch=0
例题 02C++20 · 本机可运行

缺失消息必须被检测

预期序号0、1、2;比较完整和缺少1的记录。

  1. 先检查数量
  2. 再检查每项序号
  3. 缺失记录拒绝
44-b.cpp
下载
// Original CPU teaching model; not a device simulator or benchmark.
#include <iostream>
#include <vector>
#include <stdexcept>

void require(bool ok) { if (!ok) throw std::runtime_error("model check failed"); }

bool complete(const std::vector<int>& sequence) {
 if(sequence.size()!=3) return false;
 for(std::size_t i=0;i<sequence.size();++i) if(sequence[i]!=static_cast<int>(i)) return false;
 return true;
}
int main() {
 const bool a=complete({0,1,2}),b=complete({0,2});
 require(a && !b);std::cout<<"complete="<<a<<" missing="<<b<<'\n';
}
结果与解释

complete=1 missing=0。

这是日志合同检查,不是网络或SDK运行。

在本机运行这个例子

下载后,在文件所在目录执行。需要支持 C++20 的编译器;POSIX 示例还需要章节说明中的系统条件。

clang++ -std=c++20 -Wall -Wextra -Wpedantic -Werror -pthread 44-b.cpp -o example && ./example

预期标准输出:

complete=1 missing=0
常见错误

把不同证据层合并成成功数

CPU案例、simulator启动和硬件运行混写成设备测试通过。

修正思路:按执行环境与测试命题分开计数,保留限制及原始记录。

轮到你动手

先写预测或代码,再按需打开提示。完整答案用于对照自己的推理。

练习 1

为整数sum写两个变形测试,并写出前提。

给我一点提示
  1. 零是加法单位元
  2. 先排除溢出
查看答案与推理

在不会溢出的整数范围内,追加零结果不变;拼接自身结果是原和的两倍。第二条还需检查倍增后的范围;浮点不能无条件按精确相等验收。

练习 2

一轮成功、第二轮失败,测试应补什么?

给我一点提示
  1. 状态初始化
  2. 消息与输出残留
查看答案与推理

连续运行不同输入,包括小→大、大→小、空分区与相同输入重复;核对计数器、buffer和完成标记是否重置,并检查输出哨兵是否仍残留。逐轮保存输入和第一个错误位置。

把理解说出来

先用中文讲清因果,再用英文回答。问题依据技能主题编写,并非公司内部题库。

解释

为什么CPU模型不能叫fabric simulator?

参考回答 / English answer

没有执行SDK设备语义,只实现自己选择的逻辑;必须标明范围。

Our model implements selected mathematical behavior. It does not execute the SDK's fabric or instruction semantics.
解释

121个案例全过能证明所有输入正确吗?

参考回答 / English answer

不能,只覆盖有限长度和取值;还需类型范围、边界、协议与环境检查。

Passing a finite test set is not a universal proof. Input ranges, protocol behavior, and execution environments remain relevant.
预测

scan最后一项正确,能通过所有检查吗?

参考回答 / English answer

不能,中间项可能错位;需逐项reference和性质检查。

A correct final value is only a necessary condition. Intermediate prefixes must also match.
调试

如何避免oracle与candidate一起错?

参考回答 / English answer

让oracle简单独立,不共享复杂分区或打包实现,加入手算诊断输入。

I keep the oracle simple and independent. Hand-checkable cases help expose shared preparation mistakes.
追问

simulator周期能当硬件性能吗?

参考回答 / English answer

不能,模拟语义与硬件执行环境不同;需明确指标来源和假设。

Simulator timing is not hardware timing. I label the source and assumptions of every metric.
调试

超时之后首先记录什么?

参考回答 / English answer

最后事件、等待条件、计数、输入、版本和命令;不能先将其一律判成死锁。

I capture the last observable events and outstanding waits. A timeout alone does not identify the root cause.

继续查证

公开资料用于查证;本章图解和例题是独立教学内容。CPU 逻辑模型不能证明设备性能。