2414 字
约 8 分钟
7
S23-J14 · 数据搬移与多芯封装互联

适用读者:要读懂 kernel 的访存报告、要解释"为什么加带宽没变快"、要做多卡/多 die 放置决策的人。
前置:S23-J13(算术强度与容量)。
覆盖旧文:A-4337 §4.4–§4.5(数据搬移 + 多芯片封装与互联,296 点)→ 296 点。
扩展点:E-S23-039(布局与描述符:32 KiB 有效数据跨 1 MB 地址空间)、E-S23-040(双缓冲只把总时间从 n(t_l+t_c) 降到 t_l + n·max)、E-S23-041(die 间/本地带宽比决定计算放在哪)、E-S23-042(点对点传输的 α+V/R 与 879 KiB 转折点)。
上一篇:S23-J13 · 加速器:计算单元与存储层次
下一篇:S23-J15 · 架构演进与加速器选型。


1. 一句话结论

搬移时间 = 固定开销 + 数据量/带宽,两项各有各的优化手段。 8 KiB 的消息换更快的链路只快 0.5%,2 MiB 的消息能快 26%;而 100 次串行小交换,光启动开销就是 200 μs。先判断你在公式的哪一项上,再决定花钱。

出处:AI Infra 教材 §4.4–§4.5(id 4337)。

T_edge = α + V / R
转折点 V* = α·R      (小于它:合并消息;大于它:减字节或提带宽)

2. 布局:数学上的块 ≠ 内存里的块(E-S23-039)

二维视图的地址:

addr(i,j) = base + i·s_r + j·s_c
行优先存储时 s_c = b(元素字节),s_r = 完整行宽字节

实例:从 BF16、行宽 4,096 的矩阵里取 128 行 × 每行连续 128 个元素:

项 数值
有效数据 128×128×2 = 32 KiB
每行有效 256 B
相邻行起点间距(步长) 8,192 B
首行起点到末行终点跨越 127×8192 + 256 = 1,040,640 B

判据:32 KiB 的有效数据散落在约 1 MB 的地址空间里。 逐行读只搬蓝区;整段读会把灰色空隙也搬走——差 30 倍。

2.1 描述符:把"重复算地址"交给专用单元

一次规则搬移只需要四个参数就够描述:

起点 base、行数 128、每行 256 B、行步长 8,192 B
部件 能力
普通加载指令 线程逐步算地址、逐个发起访问
TMA(Hopper 起) 多维张量搬移,按描述符重复生成地址
NDDMA(昇腾 950) 多维直接内存访问,同类的描述符式搬移

判据:搬移单元接管"重复地址计算",计算线程才能去干别的。

2.2 分块会放大请求量

DeepSeek V4-Flash 共享专家的一次 w1:[32,4096] × [4096,2048],FP8 输入仅 128 KiB。

分块方式 输入请求总量 权重读取
输出宽度分 16 块 × 128 列 16 × 128 KiB = 2 MiB(16 倍) 8 MiB(各块读自己那份)

输入本身没变大,多出来的请求全部来自"每个输出块都要遍历完整输入"。若这些块共享片上缓存,重复请求可被缓存吸收;若一个计算组保留输入连续算多个输出块,复用又移到局部缓冲。

判据:分块决定"发出多少请求",缓存决定"这些请求打到哪一级"。 两者必须一起设计。


3. 双缓冲:只买到 max 而不是 sum(E-S23-040)

串行:n 块 × (t_l + t_c) = n(t_l + t_c)
双缓冲:t_l + n·max(t_l, t_c)     (第一块先加载,之后以较慢阶段为节奏)
情形 串行 双缓冲 收益
t_l = t_c 2n·t (n+1)·t ≈ 2×
t_l = 4t_c 5n·t n·4t 仍被加载卡住

判据:双缓冲的上限是把"和"变成"最大值",天花板由较慢的那一侧决定。 加载慢就要加大加载并发,计算慢就要减少等待——两者不能靠同一个改动同时解决。


4. 多 die 封装:带宽比决定计算放哪(E-S23-041)

封装内多颗 die 各有本地 HBM,跨 die 走片内链路。判据只一个比值:

k = die 间链路带宽 / 每 die 本地 HBM 带宽
k ≥ 1 → die 可当一颗 GPU 用(跨 die 读取不比本地慢)
k < 1 → 让计算贴着权重走,只传输入与结果

4.1 两款双 die 产品的实数

产品 每 die 本地 die 间链路 k
HGX B200 90 GB / 4 TB/s NV-HBI 10 TB/s 2.5
昇腾 910C 64 GB / 1.6 TB/s 每方向 270 GB/s 0.17

场景:两颗 die 各存 32 GiB 权重,某阶段要把 64 GiB 全读一遍,计算全放在 die 0。

产品 本地读 32 GiB 跨 die 读 32 GiB 整阶段
B200 约 8.6 ms 约 8.6 ms(受 die 1 的 HBM 限制) 8.6 ms
910C 约 21.5 ms 约 127 ms(受 270 GB/s 链路限制) 127 ms

改成"计算贴着权重走"(两边各读本地):

产品 整阶段 链路传什么
B200 8.6 ms(不变) —
910C 21.5 ms(5.9× 改善) 输入+结果 64 MiB,经 270 GB/s ≈ 0.25 ms

判据:k<1 时,链路上该传"小输入/小结果",不该传"大权重"。 CloudMatrix384 的 384 颗 910C 在 decode 中以 die 为单位放专家、每 die 一个专家,正是这条规则的工程化。


5. 主机↔加速器,卡↔卡

5.1 主机侧的两条路

路径 数据流 省掉什么
独立显存(常规) CPU → 主机内存 → 复制到显存 → GPU 读 —
统一内存/共享物理内存 CPU 写同一块,GPU 直接读(同步后) 单独 H2D 副本与其传输

复用判据:一次上传的开销,要跟"加速器读一次"比较。原文给出的结论是 R ≥ 32(复用次数)时,单次上传分摊已不大于一次加速器读取——所以"权重常驻"永远优先于"每次上传"。

5.2 卡间:固定开销主导小消息(E-S23-042)

T_edge = α + V/R
HGX H100:NVLink 双向 900 GB/s → 每方向 R = 450 GB/s;A100 SXM:R = 300 GB/s
取 α = 2 μs
传输 H100 A100 差异
8 KiB(M=1 的 BF16 激活) 2.02 μs 2.03 μs 0.5%
2 MiB(M=256) 6.66 μs 8.99 μs −26%

转折点:

V* = α·R = 2 μs × 450 GB/s = 900,000 B ≈ 879 KiB
对应 [M,4096] BF16 激活:M ≈ 110 行

判据:小于 879 KiB,合并消息比换链路更有效;大于它,减字节/提带宽才有意义。 100 次串行 2 μs 小交换 → 光开销 200 μs;跨服务器 16 卡 16 bytes 的 AllReduce 公开实测约 25 μs,100 次就是 2.5 ms。


6. 可复算(实测)

$ cd /root/博客运营官/blog-v2 && python3 tools/s23_book_calc.py | tail -12
布局: 128×128 BF16 子块
  128行×128列: 有效 32 KiB,行步长 8192 B,跨度 1,040,640 B
  64行×128列: 有效 16 KiB,行步长 8192 B,跨度 516,352 B
分块: 16 块 × 128 KiB = 2 MiB(16×);权重 8 MiB
  B200: k=2.50;本地 8.6 ms;跨 die 8.6 ms
  910C: k=0.17;本地 21.5 ms;跨 die 127.3 ms
  910C 链路上传 64 MiB 输入结果 ≈ 0.25 ms

卡间 α=2 μs, R=450 GB/s
  8 KiB: 2.02 μs(启动占 99%)
  2 MiB: 6.66 μs(启动占 30%)
  512 KiB: 3.17 μs(启动占 63%)
  V* = αR = 879 KiB = 900,000.0 B;对应 M ≈ 110 行

7. 前提与边界

结论 成立条件 不成立时
双缓冲收益 ≈ max 加载与计算使用独立资源 共用同一内存接口 → 争用
k≥1 可当一颗 GPU 链路带宽 ≥ 本地 HBM 链路拥塞、协议开销 → 实际更低
V* = αR α 固定、单向带宽稳定 拥塞/多跳 → α 变大
权重常驻优先 有足够显存 模型大于显存 → 分层卸载(J23)

8. 常见误区

误区 纠正
用"整段读"取子矩阵 32 KiB 数据要跨 1 MB 地址,浪费 30 倍
认为双缓冲能叠加收益 上限是"和 → 最大值"
k<1 时还把权重跨 die 传 应让计算贴着权重,只传输入/结果
小消息也换更快的链路 8 KiB 只快 0.5%,应合并消息
忽略固定开销累计 100 次小交换 = 200 μs,比数据本身大得多

9. 自测

  1. 从行宽 4,096 的 BF16 矩阵取 64 行 × 128 列,有效数据多少?跨度多少?
  2. t_l=4t_c、n=10 时,串行与双缓冲各是多少 t_c?
  3. B200 与 910C 的 k 各是多少?k<1 时正确的放置策略是什么?
  4. H100 上 512 KiB 的消息,传输时间约多少?启动开销占比多少?
答案
  1. 64×128×2 = 16 KiB;跨度 63×8192+256 = 516,352 B。
  2. 串行 10×5 = 50 t_c;双缓冲 4 + 10×4 = 44 t_c。
  3. B200 10/4 = 2.5;910C 0.27/1.6 ≈ 0.17;让计算在权重所在 die 上执行,链路只传输入与结果。
  4. 2 μs + 512 KiB/450 GB/s ≈ 2 + 1.17 = 3.17 μs,启动占 63%。

10. 下一篇

S23-J15 · 架构演进与加速器选型 —— 从 TPU v1 到 Blackwell/昇腾 950 的演进脉络,以及"按负载选卡"的检查表:算力、带宽、容量、互联、生态。

S23-J14 · 数据搬移与多芯封装互联
https://www.clxhxhhr.top/posts/5541/
作者
clxstart
发布于
2024-12-31
许可协议
CC BY-NC-SA 4.0
评论
0 条
还没有评论,先写一条吧。