Liuyi Wen's Blog
搜索

Liuyi Wen's Blog

并行训练系列:2. 数据并行上篇(DP,DDP)
发表于2025-09-16|Parallelism
数据并行(DP) 思想:将模型复制到多个GPU上;在每个GPU上,对不同的micro batches执行前向/反向传播。 准备:在每个 GPU 上都拷贝一份完整的模型参数,将一个数据 batch 均分为多个 micro-batch,分别拷贝到不同 GPU 上(DP 分片); 前向传播/反向传播:每个 GPU 上对不同的 micro-batch 分别执行前向/反向传播,计算得到梯度 G; 聚合并下发梯度(All-Reduce): 每个 GPU 将本地梯度 G 发送给单个 GPU 做聚合(或者在不同的 GPU 上聚合梯度的某些部分);再将平均后的梯度下发到所有 GPU; 本地参数更新:所有 GPU 利用下发的梯度完成本地参数更新。 实现 DP 的经典框架为参数服务器:计算 GPU 称为 Worker,梯度聚合 GPU 称为 Server。 Worker 和 Server 是逻辑概念,分别可以对应一块或多块物理意义上的 GPU(当前讨论的基本都是对应一张 GPU...
RL 系列:2. 从 Bellman 算子的角度解释策略迭代/价值迭代
发表于2025-09-15|RL
看完策略迭代和价值迭代的定义后,我还是有点迷糊:为什么得到的策略一定会收敛呢?两种方法的本质区别是什么呢? 于是搜罗了一些更“数学”的解释,来阐明这个问题。 Bellman 算子 定义状态空间:\(S={\{s_1, s_2, ..., s_n \}}\);动作空间:\(A={\{a_1, a_2, ..., a_n \}}\) 贝尔曼期望方程: \[ V(s)=E_{a\sim\pi(a|s)}[r(s,a)+\gamma E_{s'\sim p(s'|s,a)}[V(s')]] \] 贝尔曼最优方程: \[ V(s)=\max_a(r(s,a)+\gamma E_{s'\sim p(s'|s,a)}[V(s')]) \] 根据以上方程,定义贝尔曼期望算子\(B_\pi\)和贝尔曼最优算子\(B_*\),分别代表对当前价值函数集\(V\)利用贝尔曼方程更新的操作: \[ B_\pi V(s)=E_{a\sim\pi(a|s)}[r(s,a)+\gamma...
RL 系列:1. Markov 决策过程
发表于2025-09-08|RL
本文旨在阐述基于 Markov 决策过程的强化学习原理,聚焦于关键公式(省去一些繁杂的数学推导),快速领会 RL 的核心理念。 RL 概述 强化学习的理念:Agent 根据 Environment 输出的 \(S_t\) 和 \(R_t\) 综合判断,产生当前步骤的动作 \(A_t\),放入 Environment 执行;Environment 根据 \(A_t\) 执行的结果,输出下一个状态 \(S_{t+1}\) 和当前动作带来的奖励 \(R_{t+1}\),返回给 Agent。 强化学习和监督学习的区别: RL 得到的时序数据不满足独立同分布; RL 无实时明确反馈当前 Action 是否正确,奖励信号延迟。(通过 rollout 过程从当前帧对 Action 进行采样,得到多个 observation, 每个 observe 对应一条 trajectory,即一个 State 和 Action 的序列 τ=(s0,a0,s1,a1,…);通过最终 reward 来观测当前 trajectory 是否合适) Markov...
并发系列:2. Go 的长连接
发表于2025-09-03|High Concurrency
TCP 连接的建立和关闭 绝大多数网络连接的建立都是基于 TCP 协议的,我们往往知道一个原则:建立 TCP 连接需要三次握手,其具体过程也是面试的一个常考点。那么“为什么 TCP 建立连接需要三次握手?”呢?这个问题很少深究。首先回顾一下建立连接的过程: TCP 连接是什么? 连接:用于保证可靠性和流控制的信息,包括 Socket、序列号和窗口大小。其中:Socket 由互联网地址标志符和端口组成;窗口大小主要用来做流控制;最后的序列号用于追踪通信发起方发送的数据包序号,接收方可以通过序列号向发送方确认某个数据包的成功接收。 TCP 所有的协议状态如下图: 建立 TCP 连接的三次握手 抽象成通俗语言就是: 你能听到吗? 我能听到,你听得到吗? 我也能听到。 第一次握手:SYN 报文:客户端随机初始化序列号 client_isn,放进TCP⾸部序列号段,然后把SYN置1。把SYN报⽂发送给服务端,表示 发起连接,之后客户端处于...
Go-内存分配器
发表于2025-07-18
内存分配器 内存空间包含两个重要区域:栈区和堆区。不同编程语言使用不同的方法管理堆区的内存,C++ 等编程语言会由工程师主动申请和释放内存,Go 以及 Java 等编程语言会由工程师和编译器共同管理,堆中的对象由内存分配器分配并由垃圾收集器回收。 设计原理 内存管理一般包含三个不同的组件,分别是用户程序(Mutator)、分配器(Allocator)和收集器(Collector);当用户程序申请内存时,它会通过内存分配器申请新内存,而分配器会负责从堆中初始化相应的内存区域。 分配方法 线性分配器 使用线性分配器时,只需要在内存中维护一个指向特定位置的指针;用户程序申请内存时,移动指针。然而,这不利于在内存被释放时重用内存。如下图中红色部分难以利用: 因为线性分配器需要与具有拷贝特性的垃圾回收算法配合,所以 C 和...
Go-调度器
发表于2025-07-17
Go-调度器 多个线程可以属于同一个进程并共享内存空间。因此它们也不需要内存管理单元处理上下文的切换,线程之间的通信是基于共享的内存进行的。 虽然线程比较轻量,但是在调度时也有比较大的额外开销。每个线程会都占用 1M 以上的内存空间,在切换线程时不止会消耗较多的内存,恢复寄存器中的内容还需要向操作系统申请或者销毁资源,每一次线程上下文的切换都需要消耗 ~1us 左右的时间1,但是 Go 调度器对 Goroutine 的上下文切换约为 ~0.2us,减少了 80% 的额外开销。 Go 语言的调度器通过使用与 CPU 数量相等的线程减少线程频繁切换的内存开销,同时在每一个线程上执行额外开销更低的 Goroutine 来降低操作系统和硬件的负载。 设计原理 包括以下几个版本: 单线程调度器:程序中只能存在一个活跃线程,由G-M模型组成; 单线程调度器 0.x...
并发系列:1. 自旋锁
发表于2025-07-14|High Concurrency
首先从乐观锁和悲观锁的设计思想开始。 乐观锁和悲观锁 悲观锁 悲观锁总认为最坏的情况可能会出现,即数据很可能会被其他人所修改,所以悲观锁在持有数据的时候总会把资源或者数据锁住,其他线程想要请求这个资源时阻塞,直到悲观锁释放资源(读写操作均加锁)。传统的关系型数据库里边就用到了很多悲观锁机制,比如行锁,表锁等,读锁,写锁等,均在做操作之前先上锁。悲观锁的实现往往依靠数据库本身的锁功能实现。 Java 中的 Synchronized 和 ReentrantLock 等独占锁(排他锁)也是一种悲观锁思想的实现,因为 Synchronzied 和 ReetrantLock 不管是否持有资源,它都会尝试去加锁。 一个悲观锁的运用场景: select * from student where name="cxuan" for update 这条 sql 语句从 Student 表中选取 name =...
Go-channel
发表于2025-07-11
Go-Channel Channel是Go的核心数据结构和Goroutine之间的通信方式,支持Go的高性能并发编程模型。 设计原理 不通过共享内存的方式通信,而是通过通信的方式共享内存,采用的并发模式为:CSP(通信顺序进程)。Goroutine 和 Channel 分别对应 CSP 中的实体和传递信息的媒介,Goroutine 之间会通过 Channel 传递数据。 怎么理解“不通过共享内存的方式通信,而是通过通信的方式共享内存”这句话呢? 前半句指通过 sync 包里的一些组件进行并发编程;后半句指使用 channel 进行并发编程。实际上,channel 的底层就是通过 mutex 来控制并发的。只是 channel 是更高一层次的并发编程原语,封装了更多的功能。 上图中的两个 Goroutine,一个会向 Channel 中发送数据,另一个会从 Channel 中接收数据,它们两者能够独立运行并不存在直接关联,但是能通过 Channel 间接完成通信。 FIFO Channel的收发操作遵循“先进先出”: 先从 Channel 读取数据的 Goroutine...
Go-上下文Context
发表于2025-07-09
上下文context 上下文context是Go中较独特的设计,其他编程语言中较为少见,主要用于在Goroutine之间传递请求的截止时间、取消信号和其他跨API边界的值。 context.Context是Go在1.7版本中引入的标准库接口,定义了4个待实现的方法: Deadline:返回 context.Context 被取消的时间,也就是完成工作的截止日期(如果Context设置了截止时间,则返回ok=true,deadline返回该时间;如果没有设置截止时间,则返回ok=false,deadline为空) Done:返回一个Channel(在当前工作完成或者上下文被取消后关闭),作为对Context关联函数的取消信号。当Channel关闭时,关联函数终止工作并返回。 多次调用 Done...
Transformer 系列:2. Attention机制,MHA,MQA 和 GQA
发表于2025-06-29|Transformer
Scaled Dot-Product Attention 只使用一个注意力头计算权重。 假设有输入序列\(X=(x_1, x_2,..., x_n)\),对于每个词\(x_i\)(维度为\(d\)),计算其与所有其他词的相关性,并赋予不同的权重,最后对这些信息加权求和,得到新的表示。 输入矩阵:\(X\in\mathbb{R^{n\times d}}\). \[ Attention(Q, K, V)=softmax(\frac{QK^{T}}{\sqrt{d_k}})V \] 这里,\(Q\in\mathbb{R^{n\times d_k}}, K\in\mathbb{R^{m\times d_k}, V\in\mathbb{R^{m\times d_v}}}\)。实质上,一个Attention层是:将\([n, d_k]\)的序列\(Q\)编码成一个新的\(n\times d_v\)序列。 从向量角度看: \[ Attention(q_t, K, V)=\sum_{s=1}^m...
123…5
avatar
Liuyi Wen
文章
44
标签
5
分类
9
Follow Me
公告
The Journey Is the Reward.
最新文章
深入 Parquet:从 Dremel 论文到列式存储的工程权衡2025-09-30
Transformer 系列:3. Encoder 和 Decoder 的架构2025-09-29
幂等性设计2025-09-28
从 TCP 粘包到分帧2025-09-26
并行训练系列:5. Megatron 之分布式环境初始化2025-09-25
分类
  • Database6
  • Distributed System1
  • High Concurrency2
  • Network1
  • OS3
  • Parallelism6
  • RL2
  • Transformer4
标签
Go C++ Web Platforms Display OOP KV Cache
归档
  • 九月 2025 11
  • 七月 2025 5
  • 六月 2025 1
  • 五月 2025 4
  • 四月 2025 7
  • 三月 2025 16
网站信息
文章数目 :
44
本站访客数 :
本站总浏览量 :
最后更新时间 :
©2019 - 2025 By Liuyi Wen
框架 Hexo 7.3.0|主题 Butterfly 5.3.5
搜索