神经网络层
前面几部分讲的是 candle-core:张量、后端、自动微分。这一部分讲建在它上面的 candle-nn(约 1 万行),也就是推理主线里 safetensors 那条路的前半段:权重从文件到张量,张量组成层,层在生成时怎么缓存过去的键和值。candle-nn 不定义模型,具体模型在 candle-transformers,见模型。GGUF 和量化权重走的是另一条路,见量化。
- VarBuilder:模型按名字和形状要权重,
VarBuilder把前缀拼上、交给后端;后端可以是VarMap(训练时新建)、mmap 的 safetensors、npz、PyTorch.pth;名字或形状不对时的报错原文;to_dtype和get_unchecked对 dtype 的理解不一致。 - safetensors 与 mmap:8 字节长度、JSON 头、原始数据;
MmapedSafetensors只在建立时解析头部,取张量时 CPU 和 Metal 上都复制一次,不是零拷贝;实测 SmolLM2 的加载时间、RSS 和 Metal 显存,以及 BF16 转 F32 的代价。 - 常用层:
Linear的权重和 PyTorch 一样是[out, in];softmax_last_dim、rms_norm、layer_norm、rope是每个设备一个内核的融合算子,都不记反向;和拼出来的版本对比数值和时间;CPU 上 BF16 的 softmax 在长行上算错。 - KV 缓存与注意力:
KvCache预分配再slice_set,ConcatKvCache每步cat,还有滚动、散列、交错几种;增长策略;quantized_llama用自己的cat;attention/里 CPU flash attention 的在线 softmax,只有 Qwen3 和 SmolLM3 在用。
flowchart TB file["model.safetensors"] --> mm["MmapedSafetensors"] mm --> vb["VarBuilder pp get"] vb --> layers["Linear Embedding RmsNorm"] layers --> model["candle-transformers 模型"] model --> kv["KvCache 或 cat"] ops["ops 融合算子"] -.-> layers ops -.-> model
第一、二页是加载,第三页是前向时每层做什么,第四页是生成时的状态。四页的实验都在 M2 Max、macOS 27、rustc 1.99.0 上跑,用的是本地的 SmolLM2-135M-Instruct(model.safetensors,BF16)。
💬 关联讨论
发起讨论加载中...