Sep 6, 2026 · 2713 words · 6 mins
起因 # CS336 的 training loop 里,loss.backward() 和 optimizer.step() 挨在一起。前者计算 gradient,后者更新 parameter;但 gradient 存在哪里、什么时候清零、optimizer 还维护什么状态,需要分开看。于是结合 MIT 6.S191 的 Lecture 1,把一次训练迭代重新过了一遍。
Sep 5, 2026 · 2607 words · 6 mins
推理任务能放下,为什么训练任务放不下 # 上一篇讨论了模型调度中的 Capacity Constraint:一组模型到底能不能同时放进一张 GPU。
Sep 3, 2026 · 6012 words · 12 mins
起因 # 这是 CS336 系列的又一篇。
之前那篇讨论了 FLOPs 到 Latency 之间的鸿沟:FLOPs 相同的两个 GEMM,latency 可能差几倍甚至十几倍。那篇文章的核心结论是 FLOPs 是 workload metric,不是 performance metric,并且引入了 Arithmetic Intensity 和 Roofline Model 作为分析工具。
Aug 27, 2026 · 6243 words · 13 mins
起因 # 最近在做 CS336(Language Modeling from Scratch)的 Transformer 实现,代码里反复出现这种写法:
1rearrange(X, "... seq (heads d) -> ... heads seq d", heads=self.num_heads) 第一次看到时,它甚至比 x.view(...).transpose(...) 更加陌生——至少后者你知道它是 PyTorch 原生 API。
Aug 26, 2026 · 6437 words · 13 mins
起因 # 我们的线上推理系统中存在大量模型——MLP、GNN、MoE,以及它们的各种组合。这个 workload 有几个重要特点:
单张 GPU 上可能同时存在多个模型; 很多模型的 architecture 相同或者高度相似; 模型会随着业务时间轴不断上线、下线和切换; 模型切换过程对 latency 比较敏感。 随着模型数量增加以及动态上下线越来越频繁,我们逐渐观察到两个问题:GPU memory fragmentation,以及 model loading / switching latency。
Aug 26, 2026 · 4556 words · 10 mins
起因:一个来自运维同事的问题 # 前阵子运维同事找到我,大意是:
“我们现在训练特征大部分还是 NumPy / Parquet。最近看到 Lance,说是一个更适合 AI 训练、推理的数据格式。我们为什么没有用 Lance?”
Aug 23, 2026 · 4765 words · 10 mins
起因:GPU 没吃满,但不是算力问题 # 最近组里有同学训练模型时,最直接的感受是:GPU utilization 上不去,step time 里总有一段在等数据。
Aug 21, 2026 · 5776 words · 12 mins
起因 # 以前在商汤做 CV 的时候,有一段时间在做目标检测模型的 INT8 量化。目标很直接:降低 inference latency,减少 model memory 和 bandwidth,同时利用 INT8 hardware throughput。
Aug 19, 2026 · 6632 words · 14 mins
起因 # 上一篇讨论模型显存时,我直接用了一张表:
dtype bytes / param FP32 4 FP16 / BF16 2 INT8 ~1 当时关注的是 peak memory model,所以这张表只是作为 parameter memory 的输入,没有展开。
Aug 17, 2026 · 5253 words · 11 mins
起因 # 上一篇讨论了模型调度中的 Performance Constraint:一个模型放到 GPU 上以后,到底跑多快?
这一篇讨论另一个最基础的约束:Capacity Constraint。
Aug 15, 2026 · 3136 words · 7 mins
起因 # 最近在做 CS336(Language Modeling from Scratch)的 resource accounting 作业,里面要求逐个列出 Transformer forward pass 中所有的 matmul,然后按 \(2MKN\) 计算 FLOPs。
Aug 13, 2026 · 3497 words · 7 mins
起因 # 最近在学 Stanford CS336(Language Modeling from Scratch),做 tokenizer 作业时,第一次在测试代码里见到了 pytest.mark.xfail。
具体是这段:
1@pytest.mark.xfail( 2 reason="Tokenizer.encode is expected to take more memory than allotted (1MB)." 3) 4def test_encode_memory_usage(): 5 """ 6 We expect this test to fail, since Tokenizer.encode is not expected to be memory efficient. 7 """ 8 tokenizer = get_tokenizer_from_vocab_merges_path( 9 vocab_path=VOCAB_PATH, 10 merges_path=MERGES_PATH, 11 ) 12 with open(FIXTURES_PATH / "tinystories_sample_5M.txt") as f: 13 contents = f.read() 14 _ = _encode(tokenizer, contents) 我当时第一反应是困惑:既然作者明确知道 encode 会超过 1MB,为什么不直接写成 assert memory > 1MB?或者干脆删掉?为什么要提交一个「预期会失败」的测试?
Aug 9, 2026 · 5555 words · 12 mins
起因 # 机缘使然,最近在工作中接触到了 MoE(Mixture of Experts)。
有意思的是,我接触到的用法,和现在大模型里的 MoE 长得完全不一样。
Dec 17, 2023 · 2486 words · 5 mins
背景 # 公司内部的基于torch的toolbox在某个版本之后,结果发生了偏移。通过一系列排查,发现当导入cupy和torch的顺序不同时,计算结果会有所差异。 也就是说,如下两段代码会导致模型训练等环节得到不同的计算结果。
Jan 16, 2023 · 233 words · 1 min
记录在 Bazel 工程中引入 ONNX Runtime 预编译包时的动态库、头文件与依赖配置。
Aug 6, 2022 · 430 words · 1 min
背景 # 2022年惊讶的发现,当时竟然没有写关于softmax的笔记,因此来补充一下。
proto # 还是先看proto
Jan 23, 2021 · 1797 words · 4 mins
迫于生计,从今天开始学习推荐系统相关的内容,先来读一篇推荐系统领域的综述 Toward the next generation of recommender systems: a survey of the state-of-the-art and possible extensions
由于目前的工作其实偏向推荐系统的 serving、训练的开发,因此这些 paper 可能都是粗读,也不会把 paper 中的内容逐句翻译,而是找出我认为最为重要的一些概念加以记录。
Sep 18, 2020 · 559 words · 2 mins
前言 # 偶然发现了 torch2trt 的模型转换方案,思路是直接将pytorch op映射到TensorRT的python api. 在pytorch进行每个op forward的时候,tensorrt也相应往network上添加op. 这里会先涉及torch2trt的使用,后面会补充这个转换工具的代码学习
Sep 8, 2020 · 3101 words · 7 mins
写在前面 # 主要是需要在 jetson nano 上做模型转换,来记录下踩的坑。 目前有两条路径,一条是我们现有的转换路径,也就是 pytorch->onnx(->caffe)->trt 的路径。 在这条路径上踩了比较多的坑,最终暂时放弃,最直接的原因是 cudnn8.0 升级接口发生改动,编译 caffe 遇到较多问题。 这里其实仍然采用了两条平行的路径,一条是直接在 nano 上构建环境,另外一种是基于 docker(包括构建交叉编译环境用于加快编译速度)。
Jun 30, 2020 · 30 words · 1 min
caffe做部署是YYDS!
blob
layer
net
激活函数
卷积
reshape
slice
loss function
reduce
eltwise
argmax