Golang逃逸分析

问题: golang函数传参是不是应该和c一样,尽量不要直接传结构体,而是要传结构体指针? 逃逸分析 逃逸分析指的是,在计算机语言编译器优化原理中,分析指针动态范围的方法,和编译器优化原理的指针分析和外形分析相关联。当变量(或者对象)在方法中被分配后,其指针有可能被返回或者被全局引用,这种现象就是指针(或引用)的逃逸(Escape)。 其实在java概念中有一个误解 — new出来的东西都在堆上,栈上存的是它的引用。 这句话在现代JVM上有问题,就是因为逃逸分析机制。简单来说,就是JVM的逃逸分析会在运行时(runtime)检测当前方法栈帧(frame)内new出来的对象的引用,是否被传出当前的栈帧。如果传出,就会发生逃逸,没有传出则不会。对于未发生逃逸的变量,则会直接在栈上分配内存。因为栈上内存由在函数返回时自动回收,而堆上的的内存需要gc去回收,如果程序中有大量逃逸的对象,那么势必会增加gc的压力。 1 2 3 4 5 6 7 8 9 10 public void test(){ List<Integer> a = new ArrayList<>(); a.add(1); // a 未逃逸,在栈上分配 } public List<Integer> test1(){ List<Integer> a = new ArrayList<>(); a.add(1); return a // 发生逃逸,因此分配在堆上 } 区别 不同于JVM运行时的逃逸分析,Golang的逃逸分析是在编译期完成。 golang的逃逸分析只针对指针。一个值引用变量如果没有被取址,那么它永远不可能逃逸。 go version go1.13.4 darwin/amd64 验证某个函数的变量是否发生逃逸的方法: go run -gcflags “-m -l” (-m打印逃逸分析信息,-l禁止内联编译) ...

November 23, 2020 · 4 min · 852 words · Me

Design Pattern: Overview

Design pattern Builder Pattern scenario:build complicated object 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 package msg type Message struct { Header *Header Body *Body } type Header struct { SrcAddr string SrcPort uint64 DestAddr string DestPort uint64 Items map[string]string } type Body struct { Items []string } // Message对象的复杂对象 type builder struct{ once *sync.Once msg *Message } // 返回Builder对象 func Builder() *builder{ return &builder{ once: &sync.Once{}, msg: &Message{Header: &Header{}, Body: &Body{}}, } } func (b *builder) WithSrcAddr(srcAddr string) *builder{ b.msg.Header.SrcAddr = srcAddr return b } //...... func (b *builder) WithHeaderItem(key, value string) *builder{ //map只初始化一次 b.once.Do(func(){ b.msg.Header.Items = make(map[string]string) }) b.msg.Header.Items[key] = value return b } func (b *builder) WithBodyItem(record string) *builder{ b.msg.Body.Items = append(b.msg.Body.Items, record) return b } func (b *builder) Build() *Message{ return b.msg } Test code 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 package test func TestMessageBuilder(t *testing.T) { // 使用消息建造者进行对象创建 message := msg.Builder(). WithSrcAddr("192.168.0.1"). WithSrcPort(1234). WithDestAddr("192.168.0.2"). WithDestPort(8080). WithHeaderItem("contents", "application/json"). WithBodyItem("record1"). WithBodyItem("record2"). Build() if message.Header.SrcAddr != "192.168.0.1" { t.Errorf("expect src address 192.168.0.1, but actual %s.", message.Header.SrcAddr) } if message.Body.Items[0] != "record1" { t.Errorf("expect body item0 record1, but actual %s.", message.Body.Items[0]) } } Abstract Factory Pattern ...

November 11, 2020 · 6 min · 1098 words · Me

math: true title: “昇腾超节点CloudMatrix384论文拆解” date: 2025-08-07T10:40:12+08:00 tags: [“AIInfra”, “ascend”] —math: true 6.19发布的CloudMatrix384论文拆解,从宏观到基础概念 核心指标和计算方式 TPOT (Time Per Output Token) 公式: $$TPOT= \frac{Decode总耗时}{生成Token数量}$$ 测量方式: 从第一个输出Token开始计时,到生成结束(含MoE通信/KV读取) 为什么重要: 直接决定用户体验(如Chatbot响应速度),论文要求 <50ms(严格模式<15ms) 深层意义: 反映系统通信+计算综合能力,EP320下TPOT=42ms证明UB网络突破MoE通信墙 计算效率 (Tokens/s per TFLOPS) 公式: $$计算效率=\frac {吞吐量(tokens/s)} {NPU峰值算力(TFLOPS)}$$​ 论文数据: 阶段 值 对比基准 Prefill 4.45 超NVIDIA H100+SGLang(3.8) Decode 1.29 超NVIDIA H800+DeepSeek(0.9) 为什么重要: 揭示硬件利用率,1.0以上表明软硬件协同极致优化 深层意义: Decode阶段1.29 → 昇腾910的Cube引擎利用率达 86%(传统GPU仅60%) 缓存访问延迟 (KV Cache Access Latency) 公式: $$延迟=TMMU_{查询}+TUB_{传输}+TDRAM_{读取}​$$ 论文数据: 场景 延迟 对比传统 本地HBM命中 0.2μs - 远程DRAM访问(UB) 1.5μs >10μs (PCIe+IB) 为什么重要: 长上下文推理中70%时间花在KV缓存访问 深层意义: UB统一内存将远程访问性能提升至近本地水平,支撑百万Token上下文。 专家并行扩展性 (EP Degree) 定义:单个MoE层可分布的专家数量 论文突破:EP320(每个昇腾Die托管1个专家) 支撑公式: $$可扩展性=\frac {UB总带宽}{单个专家通信需求}$$ $$EPmax=\frac {384×392GB/s} {8B/token×10^6token/s}=320$$ 为什么重要: EP>100时传统网络崩溃,EP320证明UB突破通信可扩展性极限 INT8量化收益 公式:$$ 加速比=\frac {FP16吞吐}{INT8吞吐}×精度保持率$$ 论文数据: 吞吐提升:1.8倍 精度损失:<0.5%(16个基准测试) 为什么重要: Decode阶段内存带宽减少50%,解决NPU的“内存墙”问题 QA辅助理解 为什么用TPOT而非QPS? TPOT剥离Batch Size影响,纯粹衡量单次生成效率 更直观反映SLA(用户感知的延迟) 为什么强调计算效率而非绝对吞吐? 排除工艺优势(7nm vs 5nm),聚焦架构创新价值 1.29 tokens/s/TFLOPS → 证明UB+LEP设计优于NVLink+GPU 为什么测量远程DRAM访问延迟? 验证内存池化的实际效果,这是打破“内存墙”的核心 1.5μs延迟 → 实现“全集群如单机”的硬件基础 超节点架构 三级网络平面的物理隔离 硬件隔离原理 ...

6 min · 1222 words · Me

math: true title: “[RL4LLM] 异步RL框架: Slime” date: 2025-08-07T17:10:12+08:00 tags: [“framework”, “LLM”, “RL”] series: [“rl4llm”] —math: true https://github.com/THUDM/slime 一个异步实现但是非完全异步的RL框架 总体架构 从源码模块划分,有三大核心模块: training(Megatron):主训练流程,负责模型参数更新。 rollout(SGLang + router):负责采样、奖励/验证生成,产生训练数据。 data buffer:桥接训练与采样,管理数据流、缓存与生成方式。 分布式调度:关于资源分配、actor启动、任务调度都由于Ray管理,支持异步训练和采样 插件机制:支持自定义buffer、模型、模型格式转换(mbridge) flowchart LR subgraph Ray[Ray 分布式调度] A1[Actor Group<br>训练 Actor] A2[Rollout Group<br>采样/生成 Actor] A3[Placement Group<br>资源分配] end subgraph Training[Training <Megatron>] T1[模型训练] T2[权重同步] T3[评估/保存] end subgraph Rollout[Rollout <SGLang+Router>] R1[采样/生成] R2[奖励模型] R3[过滤器] end subgraph Buffer[Data Buffer] B1[数据缓存] B2[数据流转] B3[Offload/Onload] end subgraph Plugins[插件机制] P1[Buffer 插件] P2[Model 插件] P3[mbridge 格式转换] end A1-->|训练数据|B1 A2-->|生成数据|B1 B1-->|数据流|A1 B1-->|数据流|A2 A1-->|权重同步|A2 A1-->|评估/保存|T3 A2-->|采样/奖励/过滤|R1 R1-->|奖励|R2 R1-->|过滤|R3 B1-->|插件扩展|P1 A1-->|模型扩展|P2 A1-->|格式转换|P3 A3-->|资源分配|A1 A3-->|资源分配|A2 各模块视角的关系图 slime/rollout 组件图 rollout 负责采样、奖励、过滤,支持多种采样/奖励/过滤策略。 ...

15 min · 3139 words · Me

math: true title: “[VeRL] Multi-Turn RL训练源码走读(1)” date: 2025-08-03T15:30:12+08:00 tags: [“framework”,“verl”,“sglang”] series: [“verl”] —math: true 该part主要聚焦相关模块初始化部分 还是以 verl 出发,分析其 end to end mutli-turn RL 训练的全过程。整体上,我希望覆盖所有重要的 class 以及函数,更细粒度的代码不再展开。 为了前后内容的一致性,基于 76f63cffa5 的 commit 进行分析。 虽然本文以分析 verl 的代码为主,写完之后我才意识到,系统设计问题是非常通用的。诸如“log probs 重计算”,“Rollout Engine 显存管理”等等系统设计,是各大 RL 框架都需要考虑的核心问题。 此外因为最近在学习SGLang的实现,本文的推理后端选择的是SGLang展开分析。 —math: true 整个训练的示意图如下,我们会具体展开每个部分。 flowchart LR subgraph W2["Initialize"] WP[Process Data] --> A direction TB D1[Data Prepare] --> A A[TaskRunner] --> B1[RayPPOTrainer] B1 --> Workers subgraph Workers["Workers"] direction TB WA[ActorRolloutWorker] --> WD[FSDP Engine] WB[CriticWorker] --> WD WC[RewardModelWorker] --> WD WD --> WE[SGLang Engine] end Workers --> C1[Hybrid Engine] end subgraph W3["Train Loop"] direction TB E[DataLoader] --> RolloutBox subgraph RolloutBox["Rollout"] F1[Prepare Data] --> F2[SGLang Async Rollout] F2 --> F3[Multi-turn Chat Process] end RolloutBox --> ExpBox subgraph ExpBox["Make Experience"] G1[Recompute Log Probs] --> G2[Compute Reward] G2 --> G3[Compute Advantage] end ExpBox --> UpdateBox subgraph UpdateBox["Train The Model"] H1[Load FSDP Model Weight] --> H2[Compute Gradient] H2 --> H3[Weights Update] H3 --> H4[Sync Weights] end UpdateBox --> E end W2 --> W3 数据预处理 以 GSM8K 为例,预处理脚本是 examples/data_preprocess/gsm8k_multiturn_w_tool.py。整个脚本只做了经典的 huggingface datasets mapping,核心逻辑如下: ...

27 min · 5620 words · Me