CHAPTER 45 / Cerebras · 晶圆级计算

WSE 与 PE:把数据放在拥有它的计算节点旁边

三个PE各有两项数据,怎样得到一个全局结果?

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

这一章要弄清楚

  • 区分PE本地存储与全局数学数组
  • 解释复制计算与分布计算的差异
  • 用容量与通信量约束问题分解

先备知识:并行分解、分块与负载均衡 / Reduction、scan 与数值正确性

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

先把一个大问题拆成小所有者

假设六个整数为2、4、6、8、10、12,总和是42。我们让三个教学节点各持有两项,局部和分别是6、14、22。这里的“全局数组”是数学视图,实际数据可以分散在不同所有者。某节点要使用另一个节点的结果,必须通过明确的数据移动或通信得到它,不能凭空读取一个全局变量。

Cerebras的WSE由大量PE组成。公开CSL材料把PE程序、本地数据和PE之间的通信放在显著位置。初学时可以先想成许多小工作台,每个工作台附近有自己的材料,工作台之间按安排传递消息。这只是帮助建立所有权和通信直觉;真实路由、任务激活和资源限制需要对应SDK及架构文档。

复制同一程序,不等于把工作分开

公开多PE教程先展示在多个PE复制相同工作,再进一步展示跨PE共同完成一个计算。这两个阶段不能混淆。如果三个PE都处理完整六项输入,每个都得到42,再把它们相加得到126,就重复计算了三次。真正的数据并行分解需要明确每项由谁负责,以及最终结果怎样合并。

例一使用三个独立vector保存三份不重叠数据,然后显式收集局部和。它是普通C++逻辑模型,不是Cerebras fabric simulator。模型没有模拟PE指令、路由、时钟或通信阻塞;它验证的是数据分区和局部结果合并的数学关系。

本地容量迫使程序做预算

如果一个教学PE可给这次问题使用六个元素位置,而输入、输出和通信缓冲分别需要三、二、二,总需求七,已经超预算。不能因为输入只有三个元素就认为一定放得下。中间状态、双缓冲、暂存结果和协议数据也消耗空间。例二对这类预算做显式检查。

真实PE的本地存储还要考虑代码与实现资源,容量及布局受目标代际和SDK约束。教材不把某代产品的固定数字当所有设备共同性质。工作分配策略应该先满足容量与通信合同,再讨论增加并发;平均分配元素数也不一定平均分配计算量。

通信是算法的一部分

局部和6、14、22可以由host回读合并,也可以通过PE之间的某条通信算法合并。这两种方案的结果可能相同,但数据流、同步和性能含义不同。报告时要说清最终合并发生在哪里,不能把host完成的一步写成设备内完成。

沿一条三节点链传递累积值时,第一个发6,第二个加14后发20,第三个加22得42。链式依赖便于理解,却并非一定是性能最优方案。更复杂树形或集合通信需要更完整的路由和同步设计;先做对简单路径,才能清楚评估进一步并行化的收益与代价。

将图变成可验证程序

先在纸上写每个节点的输入、输出、发送内容和结束条件,再写CPU reference。测试至少包括一个节点、空分区、不能整除的长度、零值和负值。消息数量也应成为合同:等待两条消息的接收端,必须确实有两条对应发送。

学习本章时可以直接运行原创C++例子,核对数学与容量推理。真实CSL代码、fabric simulator运行和WSE硬件执行分别是后续不同层次的验证。我们只查公开资料,不需要读取任何私有项目源码或SDK结果,就能建立这个基本模型。

观察 · 推演

三个本地分区的累积

PE0 model2 4PE1 model6 8PE2 model10 1201 / 03 · NETWORKPE0 model2 4PE1 model6 8PE2 model10 1201 / 03 · NETWORK
分区

每个元素仅属于一个教学节点。

1 / 3
阅读完整推演文字
  1. 分区

    PE0 model:2 4;PE1 model:6 8;PE2 model:10 12

    每个元素仅属于一个教学节点。

  2. 局部

    PE0:6;PE1:14;PE2:22

    先在各分区求和。

  3. 合并

    P0→P1:6;P1→P2:20;P2 result:42

    显式通信模型产生全局和。

跟着例子,走完一遍

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

三个局部所有者

三个分区[2,4]、[6,8]、[10,12]。

  1. 各自求局部和6、14、22
  2. 显式收集局部结果
  3. 合并并比较全局oracle
41-a.cpp
下载
// Original CPU teaching model; not a device simulator or benchmark.
#include <iostream>
#include <vector>
#include <numeric>
#include <stdexcept>

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

int main() {
 const std::vector<std::vector<int>> local{{2,4},{6,8},{10,12}};
 std::vector<int> partial;
 for(const auto& values:local) partial.push_back(std::accumulate(values.begin(),values.end(),0));
 const int total=std::accumulate(partial.begin(),partial.end(),0);
 require(partial==std::vector<int>({6,14,22}) && total==42);
 std::cout<<"partials="<<partial[0]<<' '<<partial[1]<<' '<<partial[2]<<" total="<<total<<'\n';
}

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

结果与解释

partials=6 14 22,total=42。

分区互不重叠,合并位置是CPU模型。

在本机运行这个例子

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

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

预期标准输出:

partials=6 14 22 total=42
例题 02C++20 · 本机可运行

不能只算输入的容量预算

教学可用容量6项;输入3、输出2、通信2。

  1. 分别列三类存储
  2. 计算需求7
  3. 拒绝超预算配置
41-b.cpp
下载
// Original CPU teaching model; not a device simulator or benchmark.
#include <iostream>
#include <stdexcept>

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

int main() {
 const int input=3,output=2,communication=2,capacity=6;
 const int required=input+output+communication; const bool fits=required<=capacity;
 require(required==7 && !fits);
 std::cout<<"required="<<required<<" capacity="<<capacity<<" fits="<<fits<<'\n';
}
结果与解释

required=7 capacity=6 fits=0。

容量是假设元素位置,不是任何真实PE参数。

在本机运行这个例子

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

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

预期标准输出:

required=7 capacity=6 fits=0
常见错误

把复制误当分区

每个节点都计算全输入,再把结果全部相加。

修正思路:明确每项所有者与合并语义,区分replication和partitioning。

轮到你动手

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

练习 1

把五项1分给三个PE,列一种合法分区及局部和。

给我一点提示
  1. 每项恰属一个PE
  2. 最后分区可以更小
查看答案与推理

可分[1,1]、[1,1]、[1],局部和2、2、1,总和5。需记录各分区真实长度,不能让尾部多读取一项。

练习 2

三节点链局部和6、14、22,列两次发送及最终值。

给我一点提示
  1. 消息承载累计值
  2. 不要把局部值重复加两次
查看答案与推理

PE0发6;PE1收到6后加14,向PE2发20;PE2收到20后加22得到42。host若读取最终节点,只读一次结果;若同时回读所有累计值再相加,会重复计数。

把理解说出来

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

解释

全局数组是否意味着任意PE都能直接访问所有元素?

参考回答 / English answer

不意味着。数学视图与实际分布不同,远端数据需要明确通信或搬运。

A global mathematical array does not imply direct access from every PE. Distributed ownership requires explicit data movement.
预测

三个PE各算完整总和42,再合并会怎样?

参考回答 / English answer

得到126,重复计数;需分区或明确只取一份复制结果。

Combining all three replicated results produces one hundred twenty-six. Work partitioning and replication have different contracts.
解释

本地容量只统计输入够吗?

参考回答 / English answer

不够,还应考虑输出、中间、通信、双缓冲及代码等实现资源。

Inputs are only part of the memory budget. Outputs, temporaries, communication buffers, and implementation resources also matter.
追问

host合并局部结果能叫设备内reduction吗?

参考回答 / English answer

不能,需明确合并位置;它仍可作为正确性baseline。

Host aggregation can be a useful baseline. It is not a device-internal reduction.
调试

空分区为什么是重要测试?

参考回答 / English answer

可能没有数据却仍需要参与协议或贡献单位元,错误等待容易暴露。

An empty partition still needs a defined protocol behavior. It can expose missing identity handling or impossible waits.
解释

CPU三节点模型与fabric simulator区别?

参考回答 / English answer

前者只运行自定义C++逻辑;后者执行特定SDK设备程序模型,均不直接等于硬件实测。

Our CPU model evaluates a mathematical decomposition. A fabric simulator executes an SDK-specific device model, which is still distinct from hardware.

继续查证

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