Skip to content

张量并行(Tensor Parallelism, TP)——两台机器在同一个 token 上同时工作,把每一层里最重的矩阵运算切给两边,在图的同步门处交换部分和。与按层切片的流水线并行不同,它降低的是单 token 延迟,而非"塞下更大的模型"。

两种并行,一个根本区别

ds4 有两套"把模型拆到多块芯片上"的方案,先分清它们:

流水线并行(Pipeline张量并行(本文)
切什么按层切片,A 跑层 0–30,B 跑层 31–output按层内工作量切,A、B 同跑每一层
同一时刻A 处理 chunk N,B 处理 chunk N(流水线错位)A、B 处理同一个 token(lockstep)
交换什么整段隐藏状态激活(MiB 级)每层的部分和(16–24 KB)
主要收益塞下超出单机的模型 + 加速长 prefill降低单 token 延迟
decode更慢(每 token 至少一次跨机跳)更快(两人合力算一个 token)

一句话:流水线并行是"装配线",张量并行是"两人抬一件货"。

ds4 的张量并行有两种部署形态,共用同一套 lockstep 协议:

形态一:Mac-to-Mac 张量并行(RDMA)

两台 MacBook 用一根 Thunderbolt 5 线直连,把单个 decode 拆给两张 GPU。实现见 ds4_tp.c / ds4_tp.h(~2.2K 行)。

切分规则:每台机器常驻连续的一半路由专家;dense 权重、注意力、共享专家、embedding、output 在两边复制。这样路由专家内核永远不会碰对方那一半——容量翻倍而无跨专家读取。

lockstep 协议:Leader 是一个普通的前端 session,它把每一次 ds4_session_sync() / ds4_session_eval() 调用原样镜像给 Worker,于是两个引擎执行完全相同的图序列。在一个 token 内部,部分和在图的同步门(每层一个 ATTN 门、一个 FFN 门)处交换:

c
// ds4_tp.h — 门类型
enum {
    DS4_TP_GATE_ATTN = 0,
    DS4_TP_GATE_FFN  = 1,
    DS4_TP_GATES_PER_LAYER = 2,
    DS4_TP_BATCH_MAX_ROWS = 8,   // 推测验证块最多 5 行
};

// 在每个门处:把本机 partial 发给对方,等对方的 partial 到位
int ds4_tp_gate_exchange(ds4_tp *tp, uint32_t layer, uint32_t gate, uint64_t seq);

部分和是 f32,从不在网络上量化vec_bytes = n_embd * 4)。DeepSeek 的 gate 向量 16 KB,一条 RDMA 消息发完;GLM 的 6144 宽、24 KB 向量拆成两条有序 RDMA 消息。

传输:优先 RDMA over Thunderbolt(two-sided SEND/RECV),否则回退到全双工 TCP(--transport tcp)。一个 GPU 可见的共享内存 slab 充当收发缓冲,NIC 用 RDMA 注册它并交换 remote key。

部署要点(详见上游 README "Tensor Parallelism over RDMA"):

sh
# 两台都要:放宽 GPU wired 上限(默认约 RAM 的 75%)
sudo sysctl iogpu.wired_limit_mb=120000

# 两台都要:给 Thunderbolt 成员接口配 IPv4(网桥 IP 不算)
sudo ifconfig en1 inet 10.99.0.2/30 alias   # 机器 A
sudo ifconfig en6 inet 10.99.0.1/30 alias   # 机器 B

# 先启 worker,它会重试直到 coordinator 加载完
./ds4 -m "$MODEL" --tensor-parallel --role worker \
  --coordinator 10.99.0.2 9911 --transport rdma

./ds4 -m "$MODEL" --tensor-parallel --role coordinator \
  --listen 10.99.0.2 9911 --transport rdma -c 8192 \
  -p "Tell me something about the sea."

实测(两台 M5 Max 128 GB,GLM 5.2 IQ2_XXS 188 GiB):decode 约 16.8 t/s(单机 SSD streaming 仅约 4.8 t/s),prefill(4096 token)约 94 t/s。代价是确定性但不逐字节相同——浮点归约顺序变了。

身份校验:握手时交换 ds4_tp_identity(GGUF 字节数、model_id、层数、embd、词表、量化位、上下文、解码门调度)。门调度决定 RDMA recv 落在 slab 的哪个槽:DeepSeek 每层先 ATTN 后 FFN;GLM 只在稀疏层发一个 FFN 门,所以它的调度跳过 dense 前缀和 ATTN 槽。两边必须一致,否则在跑任何推理前就 abort。

不兼容组合:TP 不能和 SSD streaming、分布式模式、MTP drafting、CPU 后端同时启用(ds4_tp_validate_engine_options())。

形态二:CUDA 张量并行(单机多卡)

在单台 CUDA 服务器上,--cuda-tensor-parallel 把 DeepSeek V4 Flash 的张量和路由专家工作切到偶数块 GPU。它和上面的 Mac-to-Mac 模式互相独立:不用 --role、不用 RDMA、不走分布式层流水线。设备放置用普通的 --gpu-devices / --gpu-vram

设备顺序很关键。N 块卡时,前 N/2 个逻辑层是连续的"流水线层之家",后 N/2 个是它们的张量并行搭档。先列所有 home,再列所有 partner,且配对位置上是最亲近的 P2P 对。例如 8×L40S 用物理对 (0,1)(2,3)(4,5)(6,7),写成 0,2,4,6,1,3,5,7。每对存 50/50 的路由专家,词表头按行分片给参与输出的层(这些大张量不复制);dense 注意力、router、共享专家在每对内复制。

sh
./ds4-server --cuda --cuda-tensor-parallel \
  --gpu-vram auto \
  --gpu-devices 0,2,4,6,1,3,5,7 \
  --model "$MODEL" --ctx 100000 \
  --batched-session 16 --host 0.0.0.0

该模式目前要求 DeepSeek V4 Flash + 偶数多卡放置;GLM 5.2 在 CUDA 上改走普通的层放置(路由专家 Q4 等 TP 不兼容布局会在评估前被拒绝);DGX Spark 是单卡目标,不能--cuda-tensor-parallel

托管重启run-nvidia-tp-server.sh 包一层 --cuda-tensor-parallel server,进程崩溃后自动重启。配合小 Q4 批次的 TP 加速内核,单机多卡服务部署更稳。

相关概念

  • distributed-inference — 流水线并行(按层切片),与本文互补
  • session-batching — 张量并行常和会话批处理一起用于多用户服务
  • moe — 路由专家是切分的主要对象(占模型大部分空间)
  • ssd-streaming — 另一种突破单机内存的方式,与 TP 互斥

详见 Part 6 — 张量并行