Golang内存管理

设计原则 现在我们来看 Go 中另一重要的关键组件:内存分配器。 Go 的内存分配器基于 Thread-Cache Malloc (tcmalloc) ,tcmalloc 为每个线程实现了一个本地缓存, 区分了小对象(小于 32kb)和大对象分配两种分配类型,其管理的内存单元称为 span。 我们不再介绍更多 tcmalloc 的具体细节,因为 Go 的内存分配器与 tcmalloc 存在一定差异。 这个差异来源于 Go 语言被设计为没有显式的内存分配与释放, 完全依靠编译器与运行时的配合来自动处理,因此也就造就了内存分配器、垃圾回收器两大组件。 我们知道,在计算机领域中,无外乎时间换空间、空间换时间。统一管理内存会提前分配或一次性释放一大块内存, 进而减少与操作系统沟通造成的开销,进而提高程序的运行性能。 支持内存管理另一个优势就是能够更好的支持垃圾回收,这一点我们留到垃圾回收器的章节中进行讨论。 主要结构 Go 的内存分配器主要包含以下几个核心组件: heapArena: 保留整个虚拟地址空间 mheap:分配的堆,在页大小为 8KB 的粒度上进行管理 mspan:是 mheap 上管理的一连串的页 mcentral:收集了给定大小等级的所有 span mcache:为 per-P 的缓存。 其中页是向操作系统申请内存的最小单位,目前设计为 8KB。 每一个结构虽然不都像是调度器 M/P/G 结构那样的大部头,但初次阅读这些结构时想要理清他们之间的关系还是比较麻烦的。 传统意义上的栈被 Go 的运行时霸占,不开放给用户态代码;而传统意义上的堆内存,又被 Go 运行时划分为了两个部分, 一个是 Go 运行时自身所需的堆内存,即堆外内存;另一部分则用于 Go 用户态代码所使用的堆内存,也叫做 Go 堆。 Go 堆负责了用户态对象的存放以及 goroutine 的执行栈。 Arena heapArena Go 堆被视为由多个 arena 组成,每个 arena 在 64 位机器上为 64MB,且起始地址与 arena 的大小对齐, 所有的 arena 覆盖了整个 Go 堆的地址空间。 ...

December 2, 2020 · 6 min · 1078 words · Me

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