<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>尚能学否</title>
        <link>https://blog.zjfwork.cc</link>
        <description>学点算点</description>
        <lastBuildDate>Thu, 29 Oct 2026 13:16:58 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en-US</language>
        <copyright>All rights reserved 2026, NotionNext</copyright>
        <item>
            <title><![CDATA[较难无痛的各种PO眼保健操：VPG TRPO PPO DPO GRPO ]]></title>
            <link>https://blog.zjfwork.cc/article/292bd5e1-d987-80d8-9687-c10aa152748e</link>
            <guid>https://blog.zjfwork.cc/article/292bd5e1-d987-80d8-9687-c10aa152748e</guid>
            <pubDate>Sat, 01 Nov 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-292bd5e1d98780d89687c10aa152748e"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2a1bd5e1d9878092bb61d027e88aefef" data-id="2a1bd5e1d9878092bb61d027e88aefef"><span><div id="2a1bd5e1d9878092bb61d027e88aefef" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a1bd5e1d9878092bb61d027e88aefef" title="Intro"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Intro</span></span></h2><div class="notion-text notion-block-2a1bd5e1d98780178cddce45c89809e1">本文旨在以或数学或物理或ML的「直觉」+ 少量关键位置的精确数学推导来描述我所理解的Policy Gradient系列常用于大模型后训练的RL算法。</div><div class="notion-text notion-block-2a1bd5e1d98780429f51db274ab3fe78">在学习本文资料之前，本人没有任何的强化学习背景，有一些不厉害的统计学与计算机科学背景。对于本文所引用的资料学习难度，对本人来说属于不伤脑的极限状态，偶发一些完全超出知识体系的内容就当语文书背了算了。</div><div class="notion-text notion-block-2a1bd5e1d98780b9a86bf262eb55a904">本文的主要知识脉络来源于OAI此教程（<a class="notion-link" href="https://spinningup.openai.com/en/latest/user/introduction.html" target="_blank" rel="noopener noreferrer">https://spinningup.openai.com/en/latest/user/introduction.html</a>）</div><div class="notion-text notion-block-2a1bd5e1d987805dae3bf0f64f2bc3b3">其他引用paper</div><div class="notion-text notion-block-2a1bd5e1d98780b2adc8c0e636d040f2">TRPO: <a class="notion-link" href="https://arxiv.org/pdf/1502.05477" target="_blank" rel="noopener noreferrer">https://arxiv.org/pdf/1502.05477</a></div><div class="notion-text notion-block-29abd5e1d98780089a53fff477d076a6">PPO: <a class="notion-link" href="https://arxiv.org/pdf/1707.06347" target="_blank" rel="noopener noreferrer">https://arxiv.org/pdf/1707.06347</a></div><div class="notion-text notion-block-29abd5e1d98780458bf1f2d347b7fa9d">DPO: <a class="notion-link" href="https://arxiv.org/pdf/2305.18290" target="_blank" rel="noopener noreferrer">https://arxiv.org/pdf/2305.18290</a></div><div class="notion-text notion-block-29abd5e1d98780d9a2e4cde7144dc8d9">GRPO: <a class="notion-link" href="https://arxiv.org/pdf/2402.03300" target="_blank" rel="noopener noreferrer">https://arxiv.org/pdf/2402.03300</a></div><div class="notion-blank notion-block-2a1bd5e1d98780449864f5886f8674d8"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2a1bd5e1d9878049a13ecf5b96d8be90" data-id="2a1bd5e1d9878049a13ecf5b96d8be90"><span><div id="2a1bd5e1d9878049a13ecf5b96d8be90" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a1bd5e1d9878049a13ecf5b96d8be90" title="Basement Problem in RL"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Basement Problem in RL</span></span></h2><blockquote class="notion-quote notion-block-2a1bd5e1d9878079a4daeabbe58f53d6"><div>强化学习的基本问题假设与符号约定见OAI教程，本文不再重复
建议先阅读此处Introduction的三个部分: <a class="notion-link" href="https://spinningup.openai.com/en/latest/spinningup/rl_intro.html" target="_blank" rel="noopener noreferrer">https://spinningup.openai.com/en/latest/spinningup/rl_intro.html</a></div></blockquote><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a1bd5e1d9878093a6abf471fc76f921"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A598f461c-ce95-4e3e-a9fa-ba813e16435b%3Aimage.png?table=block&amp;id=2a1bd5e1-d987-8093-a6ab-f471fc76f921&amp;t=2a1bd5e1-d987-8093-a6ab-f471fc76f921" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a1bd5e1d98780eb9892ffc9104890e9">强化学习讨论的是一个跟交互有关的问题。</div><div class="notion-text notion-block-2a1bd5e1d9878009a5cbdce4747fb842">以下围棋为例，Agent（棋手），Environment（对手）。从棋手本人视角，根据盘面（ <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span> ）思考下一个落子的地方（ <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>），对手会根据新的盘面落子；对手落子完毕，对棋手本人，会获得一个新的盘面（ <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>）。而如果这个时候有一个围棋上帝，他算尽了所有的盘面，告诉棋手刚刚的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>给他带来了多少胜率的增加（ 假设就是胜利结局除以总结局的比例，只是其中一种 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的表达方式 ）；那么经过足够多的训练数据后，理论上就拥有了一个输入 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，能够输出正确的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，以获得更高的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的模型；输入 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，输出 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的模型就叫做策略模型policy或者 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>； </div><div class="notion-text notion-block-2a1bd5e1d987801eae95e5ec8ba24ae0">Policy Gradient的方法就是通过建模这个学习过程，然后通过找出梯度向量来提升目标函数。</div><div class="notion-text notion-block-2a1bd5e1d98780fe8da7f852bb7e2ddf">其中，有一些可以前置思考的点</div><div class="notion-text notion-block-2a1bd5e1d98780c0aa26d5ce72321c53">（1） <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>这样的值从样本数据中获得的跟「ground truth」也许非常遥远。比如战争游戏等带有迷雾/信息不全特征的interaction loop，我们只能获得一个观察（observation），是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的一个在低维空间上的投影。而 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，在真实世界里，甚至是不可能获得的，只能通过一类统计函数，想方设法表达出来。当然，如果有围棋上帝，那么他可以通过minimax树的计算来表达棋手的落子跟最佳点的落子之间的胜率差，这可以认为是一种「ground truth」。</div><div class="notion-text notion-block-2a1bd5e1d987808fad55fc74fb9bbad7">（2）没想好</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2a1bd5e1d987802c8d0cf4036a1fa3db" data-id="2a1bd5e1d987802c8d0cf4036a1fa3db"><span><div id="2a1bd5e1d987802c8d0cf4036a1fa3db" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a1bd5e1d987802c8d0cf4036a1fa3db" title="VPG：Vanilla Policy Gradient"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">VPG：Vanilla Policy Gradient</span></span></h2><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2a3bd5e1d98780cd91f0e188a139e2e9" data-id="2a3bd5e1d98780cd91f0e188a139e2e9"><span><div id="2a3bd5e1d98780cd91f0e188a139e2e9" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a3bd5e1d98780cd91f0e188a139e2e9" title="J函数的定义"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">J函数的定义</span></span></h3><div class="notion-text notion-block-2a3bd5e1d98780d9aa23edc5efcacf7a">用语文话来说就是，在Policy Gradient的框架下，我们求解的目标是获得一个在样本数据下的最优策略 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是环境的状态空间， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是action空间。训练必须要有监督信号，有一个标量函数定义 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的好坏，这个函数就是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>。</div><div class="notion-text notion-block-2a3bd5e1d98780a2b259f18651705d0f">类比下围棋，一盘棋谱是有一个轨迹（ <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>）生成的，轨迹的元素是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，即状态→行动→新状态loop的过程。这个轨迹可以视为对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的一次采样。对于某一个特定的轨迹来说，从 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>采样出来的概率是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>；同时 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>由每一次action决策与环境状态转移概率的连乘共同决定。即：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3bd5e1d98780ffbdc2c3f3cf2cb88c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A963ae27c-bf8e-41e4-b826-795a4cb92b03%3Aimage.png?table=block&amp;id=2a3bd5e1-d987-80ff-bdc2-c3f3cf2cb88c&amp;t=2a3bd5e1-d987-80ff-bdc2-c3f3cf2cb88c" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a3bd5e1d98780d48ff3d238033fd831">每一条完整的轨迹，我们都可以通过一些不同的统计函数对其定义reward，也就是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>。</div><div class="notion-text notion-block-2a3bd5e1d98780358eb3de0311be0137">从整体样本空间的角度，评价具体的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的好坏，就是对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>依 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span> 概率分布的期望，即 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>。</div><div class="notion-text notion-block-2a3bd5e1d987807982e7c43372ccecdb">下棋来说，就是AI下棋，一盘下得很臭，两盘下得很好，如何评估？首先，随机性来源于自身的策略 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>存在采样（模型输出分布，随机采样根据分布决定action），以及 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>也有随机性。下得臭的棋局对AI来说，他的出现概率是可计算的，而下得好的棋局同样。因此，同样是两胜一负，如果一个策略函数 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>生成臭棋的概率小，另一个 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>生成臭棋的概率大；在同样的三个reward计算中， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>就是远好于对方的策略。公式来说就是
</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3bd5e1d987804fb7f8dfe7967ba879"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A46d78411-a73c-4331-a741-ed7b58bdebfb%3Aimage.png?table=block&amp;id=2a3bd5e1-d987-804f-b7f8-dfe7967ba879&amp;t=2a3bd5e1-d987-804f-b7f8-dfe7967ba879" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a3bd5e1d987800d9be8d15dc0165314">再换一句话，我们可以认为，环境是客观存在的一种概率分布，这种客观包括状态转移，以及对状态的奖励。Policy Gradient的行为是在客观存在的奖励体系中，找出一个贴合奖罚分布的决策机制，使得采用高奖励的动作概率更高，低奖励的动作概率更低。</div><div class="notion-blank notion-block-2a3bd5e1d98780c59518e4d114440f3a"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2a3bd5e1d98780bf926aece2797b8b4d" data-id="2a3bd5e1d98780bf926aece2797b8b4d"><span><div id="2a3bd5e1d98780bf926aece2797b8b4d" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a3bd5e1d98780bf926aece2797b8b4d" title="J函数对 的梯度"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">J函数对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的梯度</span></span></h3><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a1bd5e1d98780ceaad0ec26c1b0ec12"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A70e83089-216d-4edd-833b-954ecb3a4dae%3Aimage.png?table=block&amp;id=2a1bd5e1-d987-80ce-aad0-ec26c1b0ec12&amp;t=2a1bd5e1-d987-80ce-aad0-ec26c1b0ec12" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a3bd5e1d987803b9209ce54b4948625">原始Policy Gradient的精华就是以上的推导过程。</div><div class="notion-text notion-block-2a3bd5e1d98780bb9792cd9e30ab7e75">其中我认为最重要的是第三步，使用Log-derivative trick，将「概率分布的梯度」转换为「概率和log概率分布的梯度的乘积」。</div><div class="notion-text notion-block-2a3bd5e1d987807e8a03c4379812061e">首先，这一步是统计、机器学习中的常用技巧，来源于求导的基本公式</div><div class="notion-text notion-block-2a3bd5e1d987805ca031c3a06e1382e6"><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></div><div class="notion-text notion-block-2a3bd5e1d987800eb587c0c3fe9c7289"><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是我们的老朋友了，几乎所有的机器学习模型都是在学习log likelihood的梯度。</div><div class="notion-text notion-block-2a3bd5e1d9878085973be99fffdaf70d">除了数值计算上的便利，这一变换更深远的意义在于，在原始公式中的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的求导，是一个混合环境概率的连乘公式。而环境概率这一值，我们大多数情况下是无法获得的。而取了log之后，将连乘转变为连加，将与 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>无关的项变成了单独的项，不再是必须得系数。再取梯度后，这些讨人厌的不知道怎么找的数据都消失了。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3bd5e1d987803d9f39cdfda14fe17a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A9c6dc248-1b2c-412f-868d-05e6c7d1a4a2%3Aimage.png?table=block&amp;id=2a3bd5e1-d987-803d-9f39-cdfda14fe17a&amp;t=2a3bd5e1-d987-803d-9f39-cdfda14fe17a" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3bd5e1d98780f6b28af58062fafb5c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A97dbb6f1-34c8-4056-a0d2-48d53eb2fa1d%3Aimage.png?table=block&amp;id=2a3bd5e1-d987-80f6-b28a-f58062fafb5c&amp;t=2a3bd5e1-d987-80f6-b28a-f58062fafb5c" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a3bd5e1d98780c3b3aecfedba75f12b">从这个公式出发， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>就是log策略概率的梯度的和，可以通过样本计算到得的。</div><div class="notion-blank notion-block-2a3bd5e1d98780c8ae28e30dbebb65ce"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-2a3bd5e1d98780b399dbea28c362e1e4" data-id="2a3bd5e1d98780b399dbea28c362e1e4"><span><div id="2a3bd5e1d98780b399dbea28c362e1e4" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a3bd5e1d98780b399dbea28c362e1e4" title="降低variance的过程"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">降低variance的过程</span></span></h3><div class="notion-text notion-block-2a3bd5e1d98780c1a9c1d33e60dbdbe6">从统计性质上说，上文得到的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的梯度的无偏估计的一种，评价梯度的好坏除了无偏是一个必要条件外，稳定性/收敛速度也是很重要的。这就需要降低梯度的variance来提高迭代效率。</div><div class="notion-blank notion-block-2a3bd5e1d9878079a596fa9acce4443b"> </div><div class="notion-text notion-block-2a3bd5e1d9878026a0d6e75b33d17ab3">第一个显然的insight是对于 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，原始定义是整条链路的reward之和，也就是以下的公式。这显然不合理，我们不能用过去发生的奖励来“鼓励”之后执行的决策。举个例子，围棋手布局下得很好，前序的state让他有了很大的优势；中期打了个大勺让对手差点反败为胜。棋局最终是赢的， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的绝对值，不会特别地小，但这不能反应这局棋在前后期决策质量上的分布差异。前序的action我们应该给它很高的reward，后序的臭棋我们应该给它很低的reward，而不是被前序“平均”掉，认为后序手其实“还行”。这样模型就不会在这局棋中学坏。换言之，我们要学习的是单纯地根据state做出action的平均后果，而不是如何复现整个的轨迹。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3bd5e1d98780c69d9dfa7ca49c22e8"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:480px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ad1b124a7-97c7-49ee-a132-e863fc5bc52d%3Aimage.png?table=block&amp;id=2a3bd5e1-d987-80c6-9d9d-fa7ca49c22e8&amp;t=2a3bd5e1-d987-80c6-9d9d-fa7ca49c22e8" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3bd5e1d987805581c3ee719ef35a5c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Af632c77c-328e-430e-8c75-7123a7f5a1f8%3Aimage.png?table=block&amp;id=2a3bd5e1-d987-8055-81c3-ee719ef35a5c&amp;t=2a3bd5e1-d987-8055-81c3-ee719ef35a5c" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a3bd5e1d98780cf884bd4532e970e89">修改后的梯度公式，赋予了奖励系数时序性，避免了奖励的后向“泄露”。同时，在数学上可以证明，该梯度的期望依然是无偏的，而且variance更小。</div><div class="notion-blank notion-block-2a3bd5e1d987800096f4ef7492553985"> </div><div class="notion-text notion-block-2a3bd5e1d98780b9882ec2278a56dd8e">第二点，沿着这个路径，我们会发现，梯度的variance的来源就是奖励系数，这个跟 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>无关的常量。前文说到，奖励本身存在一定的概率性和可能的由计算定义带来的方差。减去一个跟 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>无关的，只跟 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>有关的函数，就可以减少方差。而可以证明 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的最优选择是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，即后序的奖励和的期望。这个证明我不会，但结论是需要引入一个模型预估 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，也就是PPO里常说的critic Model；而 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>函数就是reward model。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a3bd5e1d98780fcbc60da475d1f5fa8"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Af6074a7c-4c98-4c94-a0f6-cd3dc6be5a40%3Aimage.png?table=block&amp;id=2a3bd5e1-d987-80fc-bc60-da475d1f5fa8&amp;t=2a3bd5e1-d987-80fc-bc60-da475d1f5fa8" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-2a3bd5e1d987803ca5c6de1d0c21ddbf"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2a3bd5e1d987801ea607f28a54e34e4b" data-id="2a3bd5e1d987801ea607f28a54e34e4b"><span><div id="2a3bd5e1d987801ea607f28a54e34e4b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a3bd5e1d987801ea607f28a54e34e4b" title="TRPO: Trust Region Policy Optimization"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">TRPO: Trust Region Policy Optimization</span></span></h2><div class="notion-text notion-block-2a3bd5e1d9878066b051f166d92886c9">TRPO的标准形式是长这样的：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a6bd5e1d98780ecbc75e37c2618727e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ac5277314-a693-41a2-94e6-4c274d621184%3Aimage.png?table=block&amp;id=2a6bd5e1-d987-80ec-bc75-e37c2618727e&amp;t=2a6bd5e1-d987-80ec-bc75-e37c2618727e" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-2a6bd5e1d987801da3d7f71a7d86ad87"> </div><div class="notion-text notion-block-2a6bd5e1d98780e48ca9f0776699a3b2">TRPO中的TR（Trust Region）来自公式中 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的KL散度的约束。文中定义这样一个约束，通过一系列证明和推导（暂时不大看得懂）以确保对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的更新，能够使得performace function（文中是类似J函数的一个目标）的值是增加的。</div><div class="notion-blank notion-block-2a6bd5e1d9878008b0eddddacc73ab63"> </div><div class="notion-text notion-block-2a6bd5e1d98780b39fc3f51119546dcf">而从新定义的目标函数 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，是在梯度上和原始形式等价的，称为surrogate objective function的形式。也是通过一系列看不太懂的过程中推导出来的。</div><div class="notion-text notion-block-2a6bd5e1d9878019b1b6d5ffd7273609">其实第一次看到 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的形式是在deepseek的paper中关于GRPO的论述。当时硬看公式的一个理解是跟“学习率”相似的一个值。而这个学习率是一个分布，通过对优势函数的提升比例的分布来学习到更好的策略。这样相比原始形式，对了一个“对比”的含义，确保了“总的来说，在 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的邻域”内，比老策略好。</div><div class="notion-blank notion-block-2a6bd5e1d98780bd9ca1ec9e670b53f0"> </div><div class="notion-text notion-block-2a6bd5e1d987808f8a16c95c4a4733f1">TRPO的求解是又一个比较复杂的问题。这里面运用了三个基本的数学技巧（1）泰勒展开（2）拉格朗日对偶法，求强对偶问题的解 （3）共轭梯度法求海森矩阵。最终求得了一个更新 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的近似解析解。</div><div class="notion-blank notion-block-2a6bd5e1d987802c8e9de49c7ea1fa90"> </div><div class="notion-text notion-block-2a6bd5e1d98780dcaf2cfd9c667d7f46">（1）泰勒展开</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a6bd5e1d987804da034cc3a54c66635"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A9b597b48-868a-4e02-bf31-6df5314952e4%3Aimage.png?table=block&amp;id=2a6bd5e1-d987-804d-a034-cc3a54c66635&amp;t=2a6bd5e1-d987-804d-a034-cc3a54c66635" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a6bd5e1d987804eb377dd29d8239b5d"><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></div><div class="notion-text notion-block-2a6bd5e1d98780258a0fe4ef070c9309">KL divergence的展开第一项为0，应该展开到第二项，因此引入了KL divergence对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的二阶梯度信息，即Hessian Matrix。</div><div class="notion-text notion-block-2a6bd5e1d987809bb72cf747b4f47998">近似展开后，问题形式变换成以下：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a6bd5e1d98780da80efe20b842dd403"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ad5f64c0a-1a87-4224-aaf5-8aea60831e11%3Aimage.png?table=block&amp;id=2a6bd5e1-d987-80da-80ef-e20b842dd403&amp;t=2a6bd5e1-d987-80da-80ef-e20b842dd403" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a6bd5e1d987802ebf7ec329cbb3837e">（2）拉格朗日对偶</div><div class="notion-text notion-block-2a6bd5e1d98780a9b81adeb20e584aaf">在解凸问题时的常用手段，得到 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的解析解</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a6bd5e1d98780098c30c360d40a911a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:682px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A64dfb90d-9b4d-404e-be4f-dcb9b1ade3d6%3Aimage.png?table=block&amp;id=2a6bd5e1-d987-8009-8c30-c360d40a911a&amp;t=2a6bd5e1-d987-8009-8c30-c360d40a911a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a6bd5e1d9878001b462cc00fae7476b">（3）共轭梯度法</div><div class="notion-text notion-block-2a6bd5e1d98780759b3dc446d94de8d9">由于直接求解 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>参数量的平方。因此引入共轭梯度法来迭代求解 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>替代值。</div><div class="notion-blank notion-block-2a6bd5e1d98780babb80c23140655f69"> </div><h4 class="notion-h notion-h3 notion-h-indent-1 notion-block-2a6bd5e1d9878016a36feced533c4a9f" data-id="2a6bd5e1d9878016a36feced533c4a9f"><span><div id="2a6bd5e1d9878016a36feced533c4a9f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a6bd5e1d9878016a36feced533c4a9f" title="最终算法"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">最终算法</span></span></h4><div class="notion-blank notion-block-2a6bd5e1d98780619e7ffc01230e07bb"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a6bd5e1d9878024b272c28f97565c7a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ab3b2402f-6cc3-44db-9283-5ee54e3e42ee%3Aimage.png?table=block&amp;id=2a6bd5e1-d987-8024-b272-c28f97565c7a&amp;t=2a6bd5e1-d987-8024-b272-c28f97565c7a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a6bd5e1d98780e5a9bef0ac75d69c9f">最终的TRPO Algorithm如上。</div><div class="notion-text notion-block-2a6bd5e1d987802bb437defc175b7a7d"><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是从样本中计算的策略梯度，与VPG是一样的。其中 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>；Q值从样本的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>中来，V函数从样本的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>中来。</div><div class="notion-text notion-block-2a6bd5e1d98780b2bfb2d584cd7c9103"><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是通过共轭梯度法求解到的替代求解 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的近似值。</div><div class="notion-text notion-block-2a6bd5e1d98780e2b445c64f96a244dc"><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的更新中，相比解析解的公式，增加了一个调节超参 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，是因为解析解是近似地从泰勒展开而来，需要可调节的参数调整方差。</div><div class="notion-text notion-block-2a6bd5e1d9878022bc4ddb9ef790e7b8"><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>即 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的参数，是一个MSE问题。</div><div class="notion-blank notion-block-2a6bd5e1d98780ec93a1e1b9b7dcaf0e"> </div><div class="notion-blank notion-block-2a6bd5e1d987806ba9bee627da678773"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2a6bd5e1d9878016aa84c74b555708f5" data-id="2a6bd5e1d9878016aa84c74b555708f5"><span><div id="2a6bd5e1d9878016aa84c74b555708f5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a6bd5e1d9878016aa84c74b555708f5" title="PPO：Proximal Policy Optimization"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">PPO：Proximal Policy Optimization</span></span></h2><div class="notion-text notion-block-2a6bd5e1d98780129324f2f8c1860f08">PPO在我看来是VPG和TRPO两者结合的一个经验公式。没有太多的数学道理，简单实用。重新定义了目标函数，看似复杂其实非常简洁，就是在TRPO目标函数的基础上，加上了clip + min的裁剪。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a7bd5e1d987804db2a4ce65b20b2409"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A7d184bfd-d78b-4ed3-9d70-e96d1cd8017b%3Aimage.png?table=block&amp;id=2a7bd5e1-d987-804d-b2a4-ce65b20b2409&amp;t=2a7bd5e1-d987-804d-b2a4-ce65b20b2409" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a7bd5e1d987809a85b8d6dae3aa8007">TRPO的理论看似高深美妙，但实用有以下缺陷：实现复杂；需要计算二阶梯度信息。</div><div class="notion-text notion-block-2a7bd5e1d98780069070e1f89763487e">从过往经验来看，漂亮的理论都胜不过Adam这样的一阶方法。可能就是一阶方法小步快跑比较“有机会”鲁棒，而最优化方法对数据/分布的假设太强，容易在实践中被打破。</div><div class="notion-blank notion-block-2a7bd5e1d98780c59fa1fe0174e266ac"> </div><div class="notion-text notion-block-2a7bd5e1d98780a8b59cfaa4327fafba">PPO从公式来说，就是将新旧策略的概率比，控制在 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>]之间。物理含义是，如果新策略距离旧策略太远，他“提升过多”或“降低过多”的奖励，就会被减少权重。</div><div class="notion-blank notion-block-2a7bd5e1d98780e9a8c3e56eb3778902"> </div><div class="notion-text notion-block-2a7bd5e1d9878074965bffb8af74ac5a">KL Divergence是一种偏硬的正则措施，且为了求解KLD，二阶泰勒展开会引入二阶导。clip并不在更新结果上限制新旧 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的分布距离，而是在奖励的监督信号上对「过分的更新」做惩罚。同时，PPO的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>相比 TRPO的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，提供了更容易理解的超参物理量。</div><div class="notion-blank notion-block-2a7bd5e1d98780f7beaed0fa43a72ba2"> </div><div class="notion-text notion-block-2a7bd5e1d98780949920fd9dc4e7c7a0">另外，一阶SGD方法也提供一个便利。在TRPO中，我们一个网络只能解决一个问题，需要通过解析解更新Policy Network，需要通过 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的MSE估计 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>作为降方差的baseline。一阶方法可以通过混合的多头loss，同时给Policy Network和Reward Model提供梯度。即：</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a7bd5e1d987805a8513edfd4fc02d91"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A9c23d49b-07ea-45f7-adf7-0000e71838e0%3Aimage.png?table=block&amp;id=2a7bd5e1-d987-805a-8513-edfd4fc02d91&amp;t=2a7bd5e1-d987-805a-8513-edfd4fc02d91" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2a7bd5e1d98780f8950ee2b4c6a58275">下图为PPO-Clip Algorithm</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a7bd5e1d987800480e8d8bd6f96751a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ac98d3c86-40c9-4c94-8175-034646817976%3Aimage.png?table=block&amp;id=2a7bd5e1-d987-8004-80e8-d8bd6f96751a&amp;t=2a7bd5e1-d987-8004-80e8-d8bd6f96751a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-2a7bd5e1d98780e48d4cd507e4c17208"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2a7bd5e1d98780e0912ad4623805517f" data-id="2a7bd5e1d98780e0912ad4623805517f"><span><div id="2a7bd5e1d98780e0912ad4623805517f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2a7bd5e1d98780e0912ad4623805517f" title="DPO: Direct Preference Optimization"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">DPO: Direct Preference Optimization</span></span></h2><div class="notion-text notion-block-2a7bd5e1d987801e9acfddd4eec71ca3">DPO的Direct体现在，他没有采用Policy Optimization这一套强化学习的建模；这个PO其实不是PO。而是在大模型后训练上引入了类似对比学习的框架。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2a7bd5e1d987801e90e2ccb6ae167aaf"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Adba01e9d-6971-4b92-ad3f-cf779ac88ae3%3Aimage.png?table=block&amp;id=2a7bd5e1-d987-801e-90e2-ccb6ae167aaf&amp;t=2a7bd5e1-d987-801e-90e2-ccb6ae167aaf" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2afbd5e1d98780f486f1d2c7330dced0">DPO的公式非常直观，也有明确的物理含义</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2afbd5e1d98780bc94fcf540f9bc9a7e"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A2362f0d8-d692-488a-8bb4-ce57e58c7ee8%3Aimage.png?table=block&amp;id=2afbd5e1-d987-80bc-94fc-f540f9bc9a7e&amp;t=2afbd5e1-d987-80bc-94fc-f540f9bc9a7e" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2afbd5e1d98780529a95e59dd118f309">忽略paper中一大堆论证过程，从「直觉」上来说。</div><div class="notion-text notion-block-2afbd5e1d98780098852f29efd72b69d">公式中的第一项相当于 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></div><div class="notion-text notion-block-2afbd5e1d98780cc8d9dc9053622c143">A和B的含义是win/lose数据在待优化策略上的比特信息，两者相减是一种类KL散度的度量；最大化A-B或最小化B-A，就是梯度的来源。</div><div class="notion-text notion-block-2afbd5e1d9878042ad74df9ca2b24e5c">为什么不直接优化比特信息的二重差分，而是还要套一层sigmoid变成概率？</div><div class="notion-text notion-block-2b5bd5e1d987805ba7abf3b57d084a6a">其中一个角度是，我们拿到的label是一个偏好分布坍缩后的真值，并不是比特信息的能量差。第二个角度上sigmoid函数的梯度能够防止数值优化上的问题。二者从底层来说似乎是一致的，指向了人类偏好的选择服从统计物理中的玻尔兹曼分布。或者GPT告诉我这叫做「二能级系统的占据概率公式」。</div><div class="notion-blank notion-block-2b6bd5e1d98780879cb0e0fe53ed5894"> </div><div class="notion-text notion-block-2b5bd5e1d9878028a15dd3f445422001">而从数据收集/数据质量的维度考虑，相比Reward数据，DPO所需的数据在单人评估上，潜在标准更加一致；监督信号的噪声更小，数据更易收集。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-2b5bd5e1d9878025bbaee5a1429ca47b" data-id="2b5bd5e1d9878025bbaee5a1429ca47b"><span><div id="2b5bd5e1d9878025bbaee5a1429ca47b" class="notion-header-anchor"></div><a class="notion-hash-link" href="#2b5bd5e1d9878025bbaee5a1429ca47b" title="GRPO:  Group Relative Policy Optimization"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">GRPO:  Group Relative Policy Optimization</span></span></h2><div class="notion-blank notion-block-2b6bd5e1d9878047b435ce4f4a57a199"> </div><div class="notion-text notion-block-2b5bd5e1d987803fa094e9a2fafd2599">回到PPO的算法问题，我们收集到了一个带人类评分的偏好数据集，如：</div><div class="notion-text notion-block-2b5bd5e1d987802cab66dba629b8f102">第一，数据集制作需要时间，第二数据集的是在同一个Policy（LLM）上求解的，算法又要考虑新策略与旧策略的距离度量不宜过大。</div><div class="notion-blank notion-block-2b6bd5e1d98780f7b213d7f3c46eb154"> </div><div class="notion-text notion-block-2b6bd5e1d987808292afd7a4ec14989c">GRPO提出了一个在一类任务上的无需打标的更加on-policy的策略梯度方法。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2b6bd5e1d9878030a18bcfc8993d404f"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ab2d19bf6-d4f5-41de-94d1-475a8849b268%3Aimage.png?table=block&amp;id=2b6bd5e1-d987-8030-a18b-cfc8993d404f&amp;t=2b6bd5e1-d987-8030-a18b-cfc8993d404f" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-2b7bd5e1d98780739658ffc39e6eb20d"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:310px;max-width:100%;flex-direction:column"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A8e2e388e-c5b6-4b25-846e-d4a7fff90937%3Aimage.png?table=block&amp;id=2b7bd5e1-d987-8073-9658-ffc39e6eb20d&amp;t=2b7bd5e1-d987-8073-9658-ffc39e6eb20d" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-2b7bd5e1d98780859446d6076254de97">其中，总的来说GRPO的surrogate object形式与PPO是一致的。在样本数量上，对单个Prompt上做了扩展。PPO是在原始策略上，用一个prompt( <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span> )，生成response（ <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>），交给人类打分（ <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>）；GRPO是，用一个prompt( <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>)，采样生成 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span> 个response( <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>)，每个输出交给规则打分（ <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>）。同时参与训练的reward，不再是PPO中 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的绝对值，而是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>相对同源response组的归一化相对值。</div><div class="notion-text notion-block-2b7bd5e1d98780c6bfc9ecee62ff90cc">从两个「直觉」角度解析。第一，组内相对优势就是「提拔」模型求解空间中，「做对」的部分，提高其相对优势的概率分布；第二点，相比类PPO的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的优势函数，计算的是「某一个动作」发生时的「样本观测到的动作-状态奖励」 - 「预测状态奖励」；而GRPO计算的优势函数是「G个动作」分别发生时 「样本观测到的动作-状态奖励」- 「样本观测到的状态奖励」。从learning的可解释上，就是样本变多+预估环节变少，非常有利于学习。</div><div class="notion-text notion-block-2b7bd5e1d98780b295fae4ca025a8bc9">此类方法只能运用在有「解」的数据中，答案形式如选择题，简单填空等可以work。</div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[GPU分布式训练缩写眼保健操：PP、DP、DDP、MP、ZeRO、FSDP]]></title>
            <link>https://blog.zjfwork.cc/article/288bd5e1-d987-8010-ae92-f80a4bfc8237</link>
            <guid>https://blog.zjfwork.cc/article/288bd5e1-d987-8010-ae92-f80a4bfc8237</guid>
            <pubDate>Tue, 28 Oct 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-288bd5e1d9878010ae92f80a4bfc8237"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><blockquote class="notion-quote notion-block-288bd5e1d9878017a82fd4947fd4ed43"><div>学习的第一步是让眼睛先熟悉</div></blockquote><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-292bd5e1d9878085b172f86fb0031329" data-id="292bd5e1d9878085b172f86fb0031329"><span><div id="292bd5e1d9878085b172f86fb0031329" class="notion-header-anchor"></div><a class="notion-hash-link" href="#292bd5e1d9878085b172f86fb0031329" title="分布式计算的几个原生问题"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">分布式计算的几个原生问题</span></span></h2><div class="notion-text notion-block-292bd5e1d9878086ae22e171ee429637">在谈论分布式计算或大规模服务系统时，可能会谈论这几个问题</div><ol start="1" class="notion-list notion-list-numbered notion-block-292bd5e1d987808288e7f95f7382160e" style="list-style-type:decimal"><li>扩展的方向：纵向或横向</li><ol class="notion-list notion-list-numbered notion-block-292bd5e1d987808288e7f95f7382160e" style="list-style-type:lower-alpha"><li>纵向扩展：比如一个复杂的业务系统，将其按功能和开发形式，一分为二，这是纵向扩展；纵向扩展后，微服务系统A和系统B，可以分开地考虑自己的迭代，部署方式，资源增长形式等问题。又比如TP数据库，做MYSQL分库分表的垂直拆分，将多写的表与多读的表，或按业务的性质划分不同的实例也是一种纵向扩展。纵向扩展的思想是分而治之，不同的问题分开看待，消耗了一定的团队/硬件资源，但清晰了权责，缩小了问题的边界。</li><li>横向扩展：把同一个问题切分成identity的若干个变小的问题。比如上述微服务系统A，是计算密集型应用，计算紧张时，可以部署若干套。输入的请求划分成若干份；若干份资源 对应 若干份请求，问题和解决方案被切分成更小等价的局部。再说TP数据库，MYSQL做分表分表的水平拆分，假设用户表的规模对单个实例来说压力过大，则可以通过路由的形式，拆分成N个等价的实例。AP系统更不用说，横向扩展是基本结构；计算100w个数字的avg，拆分成100个计算实例，分别计算1w个数的avg，将100个结果做合并，mapreduce的过程即横向扩展。</li></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-292bd5e1d98780578c89cb089ab08b5c" style="list-style-type:decimal"><li>shard与replica</li><ol class="notion-list notion-list-numbered notion-block-292bd5e1d98780578c89cb089ab08b5c" style="list-style-type:lower-alpha"><li>Shard是横向扩展的概念，表明横向扩展成几份，称呼shard数，做sharding，sharding集群等名词</li><li>Replica是在横向扩展基础上衍生出的高可用需求。在无状态系统里做sharding，不需要考虑这个问题，节点之间是完全一致的。在有状态系统里做sharding需要考虑冗余，典型地如分布式存储系统。在有状态系统里，看似横向扩展的shardA和shardB，在支持的计算和存储的类型这些元信息上一致，但存储的内容本身就是一种有状态：对用户A的统计和用户B的统计计算过程一致，但用户A的结果绝不可能替代用户B。因此系统需要冗余来提供可用性，冗余本身也是一种并行度。计算100w个用户的avg，这100w个用户shard成10份，先拆分成10个负责10w用户的子任务；每个shard有3个replica，每个shard的计算任务，理论上“有机会”纵向扩展成3个计算3w用户的子任务。做不做这件事看系统的特性去论证收益。</li></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-292bd5e1d98780e8a1d7f87c64ed1a37" style="list-style-type:decimal"><li>通信模式与一致性：P2P or Master-Slave</li><ol class="notion-list notion-list-numbered notion-block-292bd5e1d98780e8a1d7f87c64ed1a37" style="list-style-type:lower-alpha"><li>做了sharding，做了replica，replica之间的数据就会产生一致性要求，即N份理论上要求一致的数据，如何保持一致？</li><li>一种模式是Master-Slave，典型如Raft/Paxos等分布式协议，通过选举投票机制确定“话事人”/Master，话事人执政期间，数据一切以Master为主。代价是大多数工作需要由master承接，承担“业务”的开销与“管理”的开销大头。优点是对于一致性来说，可靠且高效。</li><li>一种是P2P模型，replica之间没有一个明确的master角色，靠互通有无来决定是否有新数据。如果“外部人”不等他们同步，则只能取到不一定可靠的数据，数据还可能被回滚。但如果“外部人”愿意等待，数据最终会一致，此为最终一致性。代价就是不可靠，低效，好处是对每个节点的性能要求比较平均。</li></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-292bd5e1d987809cbee8de9d0e48d67c" style="list-style-type:decimal"><li>纵向系统里的流与批</li><ol class="notion-list notion-list-numbered notion-block-292bd5e1d987809cbee8de9d0e48d67c" style="list-style-type:lower-alpha"><li>spark或者starrocks或者flink的分布式引擎做的是通过分析任务，先纵向拆分，再在纵向切分好的子任务里确定如何横向扩展。区别在于spark一类的批系统是按阶段（stage）在时间轴上串行执行的。而flink一类的流系统是按数据的流动在时间轴上并行执行的。</li><li>打个比方，spark系统的数据是快照性质的，集合当前数据的一个计算；就像修100km长的路，建设局是一段一段去修，有的路段难度小，用了100人的团队，有的地方难度大，需要用1000人，但不会在修下一段时，上一段的团队，资源还占着不放。而flink更像一个维护公路运作的团队，100km的路，每10km分为一个服务小组，不知道什么时候有多少车车会来，不可能等车来了再去组建团队，更不可能去现修马路。</li><li>微批：在flink大行其道之前，spark生态利用其完善的计算生态去完成流的计算，批的拆分就是流，从宏观层面不能说错误。</li></ol></ol><ol start="5" class="notion-list notion-list-numbered notion-block-295bd5e1d98780729674f4c7b8d6609f" style="list-style-type:decimal"><li>存算分离 vs 存算一体</li><ol class="notion-list notion-list-numbered notion-block-295bd5e1d98780729674f4c7b8d6609f" style="list-style-type:lower-alpha"><li>TP系统存算一体较多，AP系统存算分离较多。存算一体：性能好适合实时计算；存算分离：性能较差，但存储可以单独考虑成本与规模，计算有机会弹性扩容，如spark与hdfs，redshift等。</li><li>在GPU计算里，”存“可以看做显存或内存，而不是磁盘存储。</li></ol></ol><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-292bd5e1d98780579fc4ddacd61ba7c1" data-id="292bd5e1d98780579fc4ddacd61ba7c1"><span><div id="292bd5e1d98780579fc4ddacd61ba7c1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#292bd5e1d98780579fc4ddacd61ba7c1" title="PP: Pipeline Parallelism &amp; GPipe"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">PP: Pipeline Parallelism &amp; GPipe</span></span></h2><div class="notion-text notion-block-288bd5e1d9878027be03ed757acb8464">Gpipe: <a class="notion-link" href="https://arxiv.org/pdf/1811.06965" target="_blank" rel="noopener noreferrer">https://arxiv.org/pdf/1811.06965</a></div><div class="notion-text notion-block-292bd5e1d98780588335fb86371e6342">GPipe的研究大的方向是把模型纵向切分，第二个是运用了微批，第三个小优化是运用了re-materialization的技巧。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-292bd5e1d987806da9b3eb62acdd32e1"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A9791e4f3-2ab1-4c7e-8539-8fb89ae97d14%3Aimage.png?table=block&amp;id=292bd5e1-d987-806d-a9b3-eb62acdd32e1&amp;t=292bd5e1-d987-806d-a9b3-eb62acdd32e1" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-292bd5e1d987804fbf27d0edcbd8f81d">其概念，如论文中最重要的图所示，没有太多需要解释的地方，即把模型按串行的层序切分成K个部分，每个部分放进一个理论上的“加速设备”上。层间通过通信，交换必要的信息；如激活值，如梯度等。</div><div class="notion-text notion-block-292bd5e1d98780b584cedbb784192a16">Naive的串行方式由此引入了一个问题，在figure(b)部分所示，”Device i” 计算时，其他K-1个部分是空闲的。因此引入了micro-batch的概念，将整体的mini-batch，分成M份，“流动地”推进计算。这样有两个好处，一是计算设备的空闲时间减少了，另一个是单位时间内，mini-batch的逻辑大小可以成倍增加，有助于训练的收敛和稳定性。</div><div class="notion-text notion-block-292bd5e1d98780ed835ede22e4c5eac0">第三点的优化是re-materialization。在单个设备内，假设存在若干层网络（平均是#L/#K），计算梯度所需的input，可以缓存下来，也可以不缓存。大多数情况下GPU分布式系统是memory-bound与network-bound的，计算能力是溢出的。因此不缓存下来，节省了内存消耗同时不增加通信开销，是一种很好的策略。类比spark，就是RDD的lineage机制，但那是为了节省因不可靠设备导致的开销，出发点不同。PagedAttention中也提及了内存淘汰的re-compuation策略，一种普遍的时间换空间的策略。</div><div class="notion-blank notion-block-292bd5e1d9878091adb2dada3ce86273"> </div><div class="notion-text notion-block-292bd5e1d987807cbb0afb63451cb940">一个遗留的问题是，如何处理“跨样本的，依赖batch内全局信息”的计算，如batch norm。文中是这么描述的。</div><div class="notion-text notion-block-292bd5e1d987809caa84ebe4b2f01afc">也就是说，使用了micro-batch内的数据来做mini-batch的统计量的一个预估。从逻辑上是会影响计算结果的，从统计意义上，我认为是无损的。因为文中给的实验，batch_size少说在十万级别。</div><div class="notion-blank notion-block-292bd5e1d9878091b050e846315bcfc7"> </div><div class="notion-text notion-block-292bd5e1d98780b88705c8bb0c1be84d">另一个问题：Pipeline Parallelism能否像spark计算一个，分stage（layer）计算完成，再加载下一层的模型推理。当然，实现上是完全可行的。但与spark task相比，加载模型的权重对比加载next stage这样的计算图程序，需要的内存加载大得多，中间结果（activations, optimizer states）也大得多。</div><div class="notion-blank notion-block-292bd5e1d9878006af40ff8b87ed809f"> </div><div class="notion-blank notion-block-292bd5e1d98780d1b754d5bdabdad3a2"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-292bd5e1d98780e881afd20ac06f920a" data-id="292bd5e1d98780e881afd20ac06f920a"><span><div id="292bd5e1d98780e881afd20ac06f920a" class="notion-header-anchor"></div><a class="notion-hash-link" href="#292bd5e1d98780e881afd20ac06f920a" title="TP: Tensor Parallelism  via Megatron-lm"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">TP: Tensor Parallelism  via Megatron-lm</span></span></h2><div class="notion-text notion-block-292bd5e1d98780e993f8d02194c555a3">纵向扩展面临的几个问题：(1) 纵向切分网络需要做“规划” (2) 切分的均衡性有一定考验，且最坏情况时，单层也许超过单卡的内存，使得进行。</div><div class="notion-text notion-block-292bd5e1d98780dc868fc17853193a62">Megatron-lm提出的是横向扩展的方案，即我们应当如何横向切分权重矩阵为等价的若干个小矩阵，什么时候做聚合数据等问题。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-292bd5e1d9878097bac6ded64d7f4e00"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A772cd972-7177-478c-b877-fd3d7285d76f%3Aimage.png?table=block&amp;id=292bd5e1-d987-8097-bac6-ded64d7f4e00&amp;t=292bd5e1-d987-8097-bac6-ded64d7f4e00" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-292bd5e1d9878016ba1aec791d8b8bb1">如图所述，(a) 描述的是一个两层MLP + GeLU + Dropout，应当如何切分矩阵。第一层权重A按列切分，每台设备获取全量的X与sharding分片的矩阵做乘法。分片的乘法结果，与第二层权重B，按行切分后继续相乘，随后聚合结果。至于为什么A和B两层的权重切分方式不同，以及三层MLP应该怎么做，在另一篇文章中有说明。<span class="notion-link-mention"><a href="https://blog.zjfwork.cc/article/27cbd5e1-d987-8014-adc6-ce73e83a05f9" target="_blank" rel="noopener noreferrer" class="notion-link-mention-link"><img class="notion-link-mention-icon" src="https://blog.zjfwork.cc/favicon.ico"/><span class="notion-link-mention-title">blog.zjfwork.cc</span></a><div class="notion-link-mention-preview"><article class="notion-link-mention-card"><img class="notion-link-mention-preview-thumbnail" alt="blog.zjfwork.cc" referrerPolicy="same-origin"/><div class="notion-link-mention-preview-content"><p class="notion-link-mention-preview-title">blog.zjfwork.cc</p><p class="notion-link-mention-preview-description"></p><div class="notion-link-mention-preview-footer"><img class="notion-link-mention-preview-icon" src="https://blog.zjfwork.cc/favicon.ico" referrerPolicy="same-origin"/><span class="notion-link-mention-preview-provider"></span></div></div></article></div></span></div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-292bd5e1d98780f593b3c26ca3f02e2a"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Afe2123a3-4ab8-49d7-9a5e-8f82af0fa1b0%3Aimage.png?table=block&amp;id=292bd5e1-d987-80f5-93b3-c26ca3f02e2a&amp;t=292bd5e1-d987-80f5-93b3-c26ca3f02e2a" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-292bd5e1d9878047b29bd3e76939ed6a">（b）描述了在原始transformer self-attention中是怎么横向扩展的。考虑self-attention，有head_size的概念，head_size影响softmax的范围。如果按naive的思路，将attention head横向切分，则会导致softmax的计算需要跨节点，v的计算也需要跨节点。因此合理的策略是，将同一个attention head放在一台机器上，使其有能力完成一个local的self-attention计算。这也是横向扩展，只是sharding by的维度不同，(a)中描述的mlp是sharding by column or row，(b)中描述的是将attention head视为一个整体，sharding by attention head。</div><div class="notion-blank notion-block-292bd5e1d98780b5b070f247a8e736e3"> </div><div class="notion-text notion-block-292bd5e1d98780a380ebd4b6b7ad84ab">以上方法称为tensor parallelism，是model parallelism的一种。pipeline parallelism也是model parallelism的一种。</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-292bd5e1d987806db97cf939edf7a101" data-id="292bd5e1d987806db97cf939edf7a101"><span><div id="292bd5e1d987806db97cf939edf7a101" class="notion-header-anchor"></div><a class="notion-hash-link" href="#292bd5e1d987806db97cf939edf7a101" title="DP， DDP: Data Parallelism and Distributed Data Parallelism"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">DP， DDP: Data Parallelism and Distributed Data Parallelism</span></span></h2><div class="notion-text notion-block-293bd5e1d98780e1b7f9e71bf571e73d">DP，如《<a class="notion-link" href="https://arxiv.org/pdf/2006.15704" target="_blank" rel="noopener noreferrer">PyTorch Distributed: Experiences on Accelerating
Data Parallel Training</a>》一文中所说：</div><div class="notion-text notion-block-292bd5e1d98780f880fbc7af008765a3">DP的思想很直观，一个模型的版本训练速度是确定的，那么理论上多部署一些模型就可以加速。但加速不是免费的，是边际效用递减的，因为最终若干个模型replica之间需要通信来保持参数的一致。</div><div class="notion-text notion-block-293bd5e1d98780ccb251f387ae8ed0c9">思考几个场景：（1）单机单卡（2）单机多卡（3）多机多卡。前两者在本机内通信，后者通过网络通信，需要考虑的网络开销不是一个数量级。DDP主要的工作是在确保分布式正确性的前提下，加速梯度通信。</div><div class="notion-blank notion-block-293bd5e1d9878082a463ed4fb9b25d38"> </div><div class="notion-text notion-block-293bd5e1d987800d9a8cf8f6cbcbc746">pytorch DDP主要通过NVDIA的NCCL提供的”collective communication primitives”实现多模型实例之间的梯度同步。文中主要提及有以下几个特性</div><div class="notion-text notion-block-293bd5e1d98780578bebf1c92323ee81">（1）通过NCCL的ring all-reduce tree-all reduce， 从通信模型上减少了通信压力。相比master-slave结构的，更类似p2p的通信协议。</div><div class="notion-text notion-block-293bd5e1d987809f97b3e64f2bf6f350">（2）bucketing gradients</div><div class="notion-text notion-block-293bd5e1d98780979adff58614229fb8">通过实验证明，对于tensor数据的通信，nccl等通信库，少量多次 vs 大量少次，批量的总体性能表现更好。因此通信时机策略上会偏好梯度计算的过程中，累积足够的数据后再通信。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-293bd5e1d98780b6a55cccb39364c601"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A6e9556db-b431-4008-a43d-212acd562927%3Aimage.png?table=block&amp;id=293bd5e1-d987-80b6-a55c-ccb39364c601&amp;t=293bd5e1-d987-80b6-a55c-ccb39364c601" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-293bd5e1d987802481a8d4f0342add76">（3）overlapping communication with computation</div><div class="notion-text notion-block-293bd5e1d987801497acd5d969ab6244">文中论述了在GPU/CPU上完整计算一次反向传播的消耗时间，与all reduce一次梯度的时间在同一个数量级，意味着可以设计一种并行策略，将梯度ready的单位划分成更小的粒度，在计算梯度时，已经全部ready的梯度单位则可以先行开启all-reduce。这一部分的时间收益几乎是免费的。</div><div class="notion-text notion-block-293bd5e1d98780ed8149f298e037fe41">（4）skipping synchronization</div><div class="notion-text notion-block-293bd5e1d98780bfb85dd4c821354011">是一种防止死锁的策略，与性能无关</div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-292bd5e1d987807580eed9f1d3d47c7f" data-id="292bd5e1d987807580eed9f1d3d47c7f"><span><div id="292bd5e1d987807580eed9f1d3d47c7f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#292bd5e1d987807580eed9f1d3d47c7f" title="ZeRO: "><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">ZeRO: </span></span></h2><div class="notion-text notion-block-293bd5e1d9878025ad4bc4f6047f517a">ZeRO paper中声明了一个关于Megatron-lm的性能实验，以表述了一个问题，Tensor Parallelism的方法在单机多卡中可行，而多机多卡需要网络通信时，则硬件利用率很低。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-295bd5e1d98780c39349ea5cf38115e6" data-id="295bd5e1d98780c39349ea5cf38115e6"><span><div id="295bd5e1d98780c39349ea5cf38115e6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#295bd5e1d98780c39349ea5cf38115e6" title="ZeRO的insights"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">ZeRO的insights</span></span></h3><div class="notion-text notion-block-294bd5e1d98780da8bbfdf7fd2b75e75">简单类比CPU分布式系统里的存算一体或存算分离，DP和MP都属于存算一体的特征；参数所在的机器就是负责其前向计算，后向计算和参数更新的机器。</div><div class="notion-text notion-block-295bd5e1d987806288bdfa82648491f9">（1）单纯DP中，参数被复制N份，每一完整复制品所在的机器负责一部分的数据，进行前向计算，后向计算，all-reduce后更新参数。单纯MP中，参数被切割成M份，每一份独特的分片所在的机器，负责所有数据对当前分片矩阵的前向计算，后向计算，结果同步与更新参数。</div><div class="notion-text notion-block-295bd5e1d98780bdabb5f838f368b476">（2）DP的存算一体，带来了成倍的固定显存消耗，同时也限制了模型能塞进单卡的显存尺寸 ；MP的存算一体，虽然解除了显卡尺寸的限制，但MP alone的训练策略，无法对数据并行训练；DP + MP的模式，模型尺寸的限制因素从单卡变成了集群的显存总和，但要除以DP的并行度，因为集群的整体显存随着DP并行度线性增长。</div><div class="notion-text notion-block-295bd5e1d9878033ac00c3f0e06b07d1">（3）从存算分离的角度，模型/优化器状态/梯度这三者主要的显存占用（存），从全局而言，只需要一份。而计算则多多益善。这样，存算分离后，只要整个集群的整体显存塞得下单份模型的模型/优化器状态/梯度这三者，理论上就能达到了当前总显存大小下，能训练的最大模型（不考虑offload策略）。</div><div class="notion-text notion-block-295bd5e1d98780d3974bdfd7f8fcd8ac">（4）那么代价是什么，代价就是通信。ZeRO需要论证，在存算分离之后带来的计算/通信过程的改变，会让“算”与“存”的交互的额外时间开销不仅不会增加总体物理训练时间，反而会成倍加速。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-295bd5e1d9878066a0f7cf01b5426a2c" data-id="295bd5e1d9878066a0f7cf01b5426a2c"><span><div id="295bd5e1d9878066a0f7cf01b5426a2c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#295bd5e1d9878066a0f7cf01b5426a2c" title="ZeRO的方法与结果"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">ZeRO的方法与结果</span></span></h3><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-299bd5e1d987809c9275ecde19f95c4c" data-id="299bd5e1d987809c9275ecde19f95c4c"><span><div id="299bd5e1d987809c9275ecde19f95c4c" class="notion-header-anchor"></div><a class="notion-hash-link" href="#299bd5e1d987809c9275ecde19f95c4c" title="1. ZeRO-DP"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. ZeRO-DP</span></span></h4><div class="notion-text notion-block-299bd5e1d9878028a9c2d0dea10a7c2e">DP是很好的在充分利用Flops的情况下加速训练的手段，DP的问题就是memory的利用效率与单卡的限制。通过显存占用的分析，将其分为三个对象与三个ZeRO的stage:</div><div class="notion-text notion-block-299bd5e1d987806a8217d22f876b73c7">（1） Optimizer States: 如Adam中的Momentum与Variance；而文中讨论Mixed-Precision设置下，优化器需要存储三个值，fp32版本的参数，M与V。因此在文中K = 4 * 3 = 12。Stage1是将这一部分分布在集群的所有GPU上，即每个分片存储 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>。 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>是数据并行度，在单纯ZeRO-DP里可以认为是GPU的数量。
（2）stage2/stage3继续扩展，将fp16版本的“负责存储”梯度与参数的状态分片。</div><div class="notion-text notion-block-299bd5e1d9878049bb4ffbfb01fa4cae">（3）在ZeRO-DP里，分片的是“状态”，是“存储”，计算则是每块GPU都会计算完整的模型过程，因此 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>就是GPU的数量，就是一个mini-batch分多少个micro-batch的数量。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-295bd5e1d987802fbefdd0ba2fe0d3c6"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A73777469-feea-4275-861b-bbaa5f0521aa%3Aimage.png?table=block&amp;id=295bd5e1-d987-802f-befd-d0ba2fe0d3c6&amp;t=295bd5e1-d987-802f-befd-d0ba2fe0d3c6" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-text notion-block-295bd5e1d9878010aca2c01e11a97a21">实验表明，在单机内，ZeRO与Megatron-lm的方法差距并不十分大（实现ZeRO的复杂度比Megatron-lm大很多）。当TP方法需要跨节点时，ZeRO在计算利用率上有数倍的提升。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-295bd5e1d98780d4bbded776309bebaa"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Adba37d54-cefa-42dd-a171-3aaca1037c5d%3Aimage.png?table=block&amp;id=295bd5e1-d987-80d4-bbde-d776309bebaa&amp;t=295bd5e1-d987-80d4-bbde-d776309bebaa" alt="notion image" loading="lazy" decoding="async"/></div></figure><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-295bd5e1d9878051b1a4eb452ec5bdf1"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A08680a41-b932-4161-82f2-a025fb75598b%3Aimage.png?table=block&amp;id=295bd5e1-d987-8051-b1a4-eb452ec5bdf1&amp;t=295bd5e1-d987-8051-b1a4-eb452ec5bdf1" alt="notion image" loading="lazy" decoding="async"/></div></figure><h4 class="notion-h notion-h3 notion-h-indent-2 notion-block-295bd5e1d98780149b67eb60d1c606a1" data-id="295bd5e1d98780149b67eb60d1c606a1"><span><div id="295bd5e1d98780149b67eb60d1c606a1" class="notion-header-anchor"></div><a class="notion-hash-link" href="#295bd5e1d98780149b67eb60d1c606a1" title="2. ZeRO-R"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. ZeRO-R</span></span></h4><div class="notion-text notion-block-299bd5e1d98780a499def606d83f70bd">除优化器外，剩余的内存占用问题主要是(1) 激活值的存储（activations） (2) 算子的中间值等（temporary buffers）以及由此引发的external memory fragmentation（如Partitioned Attention中讨论的问题）。</div><div class="notion-blank notion-block-299bd5e1d9878028bc32dffb3a7fd278"> </div><div class="notion-text notion-block-299bd5e1d98780e9b077df788a904394">（1）激活值</div><div class="notion-text notion-block-299bd5e1d9878092badef8acf053d91e">激活值的理论集群显存占用在分布式训练中跟三个要素有关，①sequence length   ②模型大小，层数与hidden size ③batch_size。前两者取决于模型训练的需求，后者主要影响训练速度。在单纯ZeRO-DP中，一份计算对应一份GPU，因此一份GPU对应一份micro-batch的激活值显存占用，并没有什么sharding的空间。因此ZeRO-R中需要引入MP的概念，在基于ZeRO-DP的一个计算组内（一整份的计算和一个分片的“状态”的逻辑单位），再次横向拆分。接着一整份计算对应的激活值，就可以被MP degree降低占用。举个例子，同样16卡的双机集群，可以设置DP=16，也可以设置DP=8, MP=2或DP=2, MP=8，取决于内存与通信占用分布与训练速度之间的取舍。</div><div class="notion-text notion-block-299bd5e1d98780258a9ee26f3d604789">同时，在一个DP组内，activation也不会layer by layer存储，而是使用activation checkpoint策略，采样sqrt(L) 层存储，其他层在需要时recompute，以此减少模型配置带来的显存增长。</div><div class="notion-text notion-block-299bd5e1d98780f2bd4bd5f49f9ec46a">（2）temporary buffers与external memory fragmentation</div><div class="notion-text notion-block-299bd5e1d987801b9b2be89ab11a6c4c">文中没有细说，大意是通过连续内存管理等工程方式降低了浪费。</div><div class="notion-blank notion-block-299bd5e1d98780efb996d03088bb31eb"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-299bd5e1d98780f0be69c01e44ca2f0f" data-id="299bd5e1d98780f0be69c01e44ca2f0f"><span><div id="299bd5e1d98780f0be69c01e44ca2f0f" class="notion-header-anchor"></div><a class="notion-hash-link" href="#299bd5e1d98780f0be69c01e44ca2f0f" title="ZeRO的通信量分析"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">ZeRO的通信量分析</span></span></h3><blockquote class="notion-quote notion-block-299bd5e1d987800387b6cca66f884a13"><div>设模型参数量为 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></div></blockquote><ol start="1" class="notion-list notion-list-numbered notion-block-299bd5e1d987806b919ef17f0e4c7422" style="list-style-type:decimal"><li>ZeRO-DP</li><ol class="notion-list notion-list-numbered notion-block-299bd5e1d987806b919ef17f0e4c7422" style="list-style-type:lower-alpha"><li>以单纯DP为baseline， 单纯DP在计算出local的梯度后，对分布式的梯度做all-reduce。ring all-reduce为其通信量最佳实现，分为ring reduce-scatter + all gather两阶段。两阶段分别的单机通信量为 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，和为 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>。具体过程说明可见<a class="notion-link" href="https://andrew.gibiansky.com/blog/machine-learning/baidu-allreduce/" target="_blank" rel="noopener noreferrer">https://andrew.gibiansky.com/blog/machine-learning/baidu-allreduce/</a></li><li><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>与 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，其过程均为先对partition的元素做reduce-scatter，后进行all gather，因此通信量是一致的。</li><li>对于 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>，额外的过程是需要拉取一个 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的参数量，因此通信量是 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-299bd5e1d9878046af28c39ad6a33b34" style="list-style-type:decimal"><li>ZeRO-R</li><ol class="notion-list notion-list-numbered notion-block-299bd5e1d9878046af28c39ad6a33b34" style="list-style-type:lower-alpha"><li>以单纯MP为baseline，对比activation partition带来的额外通信量</li><li>结论是10%左右，计算需要考虑多种因素较为复杂。</li></ol></ol><div class="notion-blank notion-block-299bd5e1d98780ee990bc180383f7156"> </div><div class="notion-blank notion-block-299bd5e1d98780a8ba89e12dc3c1f51a"> </div><div class="notion-blank notion-block-299bd5e1d98780ebaf7cd89508e9664b"> </div><div class="notion-blank notion-block-299bd5e1d98780078f0dc1afd730b70e"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-299bd5e1d987807eba58f5dd819276f2" data-id="299bd5e1d987807eba58f5dd819276f2"><span><div id="299bd5e1d987807eba58f5dd819276f2" class="notion-header-anchor"></div><a class="notion-hash-link" href="#299bd5e1d987807eba58f5dd819276f2" title="FSDP： Fully Sharded Data Parallel"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">FSDP： Fully Sharded Data Parallel</span></span></h2><blockquote class="notion-quote notion-block-29abd5e1d98780d19ddff99a32b60eb1"><div><a class="notion-link" href="https://arxiv.org/abs/2304.11277" target="_blank" rel="noopener noreferrer">https://arxiv.org/abs/2304.11277</a>
fsdp是zero stage3在pytorch中的一个实现
The FSDP algorithm is motivated by the ZeroRedundancyOptimizer technique from DeepSpeed but with a revised design and implementation that is aligned with the other components of PyTorch.</div></blockquote><div class="notion-blank notion-block-29abd5e1d98780688b00cdb5d43ab472"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-29abd5e1d987805d81f6e775dc1e07ee" data-id="29abd5e1d987805d81f6e775dc1e07ee"><span><div id="29abd5e1d987805d81f6e775dc1e07ee" class="notion-header-anchor"></div><a class="notion-hash-link" href="#29abd5e1d987805d81f6e775dc1e07ee" title="1. FSDP Unit"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">1. FSDP Unit</span></span></h3><div class="notion-text notion-block-29abd5e1d9878001ba00e76f63f84df1">ZeRO paper中并没有提到，应该如何partition states，以什么方式partition。
Naive地，我想有几种可能性（1）对参数全局编号，分段partition；显然这不是很好的方式，会造成forward时layer by layer加载时的分片网络热点。（2）全局编号，hash partition；分散了layer by layer的热点通讯。但在元数据管理上显得比较单薄，比如在加载策略上，我们在无法做更多的工作，按矩阵加载 - 计算 - 释放的方式显然会容易存在computation和communication的bubble。其他还要考虑self-attention/MLP等计算内容上的不同。</div><div class="notion-text notion-block-29abd5e1d98780c8bac0f98b9ec0dcf3">如果我们能在使用时表达一种元数据，表明A和B两个参数的单位是一组，我希望这一组同时拉取/同时释放，帮助训练引擎“掌握”更多的对训练中模型的理解。
FSDP提供了一个新的概念，unit，同一unit中的参数拥有相同的生命周期。这样我们可以将较小的layer的通信fusion在一起，从而摊销通信的overhead。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-29abd5e1d98780fbbaf7fa5d26afe401"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A42037034-85d3-4913-bccb-035db432589a%3Aimage.png?table=block&amp;id=29abd5e1-d987-80fb-baf7-fa5d26afe401&amp;t=29abd5e1-d987-80fb-baf7-fa5d26afe401" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-29abd5e1d987808f914cf3d250fb9648"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-29abd5e1d9878089b1bfe2b6e9e15522" data-id="29abd5e1d9878089b1bfe2b6e9e15522"><span><div id="29abd5e1d9878089b1bfe2b6e9e15522" class="notion-header-anchor"></div><a class="notion-hash-link" href="#29abd5e1d9878089b1bfe2b6e9e15522" title="2. Hybrid Sharding"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">2. Hybrid Sharding</span></span></h3><div class="notion-text notion-block-29abd5e1d98780e4aceed1777b85b4c1">类比分布式数据库，ZeRO只提供了一种sharding=N, replica=1的策略；而FSDP提出了Hybrid Sharding的概念，sharding states允许存在replica，以适配hardware的locality。提供了一种在模型size扩展和通信量增加之间中间参数调节方案。即假设模型的大小没有大到超过一台物理机的显存size，但又希望有多机并行训练，显然通过全局的ZeRO satge3 shard会增加网络延迟。因此，在计算上依然是以单卡做一个DP，在存储分片上，一台物理机保留一个完整副本，物理机之间为replica；可以将参数通信保持在单个硬件内完成。</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-29abd5e1d987800a83f4f3b1d9f5cb03"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A3ea2f7f2-f4b3-4afd-a675-24d99d0b37dc%3Aimage.png?table=block&amp;id=29abd5e1-d987-800a-83f4-f3b1d9f5cb03&amp;t=29abd5e1-d987-800a-83f4-f3b1d9f5cb03" alt="notion image" loading="lazy" decoding="async"/></div></figure><div class="notion-blank notion-block-29abd5e1d98780a9830af2c9c9cea382"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Megatron-LM中GEMM的推导]]></title>
            <link>https://blog.zjfwork.cc/article/27cbd5e1-d987-8014-adc6-ce73e83a05f9</link>
            <guid>https://blog.zjfwork.cc/article/27cbd5e1-d987-8014-adc6-ce73e83a05f9</guid>
            <pubDate>Wed, 08 Oct 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-27cbd5e1d9878014adc6ce73e83a05f9"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-289bd5e1d9878067b4bddeee8fd07750" data-id="289bd5e1d9878067b4bddeee8fd07750"><span><div id="289bd5e1d9878067b4bddeee8fd07750" class="notion-header-anchor"></div><a class="notion-hash-link" href="#289bd5e1d9878067b4bddeee8fd07750" title="问题定义："><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">问题定义：</span></span></h3><div class="notion-text notion-block-289bd5e1d987801d8ecaf3b0424f9c4c">有 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></div><div class="notion-text notion-block-289bd5e1d98780b9be34d627d9371525">寻找一种适当的切分 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>的方式与数据流程，可以得出等价的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>以及 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></div><div class="notion-blank notion-block-289bd5e1d98780969771e750c94db254"> </div><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-289bd5e1d9878029b698d6dde79549a8" data-id="289bd5e1d9878029b698d6dde79549a8"><span><div id="289bd5e1d9878029b698d6dde79549a8" class="notion-header-anchor"></div><a class="notion-hash-link" href="#289bd5e1d9878029b698d6dde79549a8" title="前向传播的讨论"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">前向传播的讨论</span></span></h3><ul class="notion-list notion-list-disc notion-block-289bd5e1d9878010a19ae00864f4991c"><li>Feature1: 按列拆分 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li><ul class="notion-list notion-list-disc notion-block-289bd5e1d9878010a19ae00864f4991c"><li>权重矩阵按列拆分时，权重矩阵的列方向数据是完整的，要在一个block上计算完整结果矩阵的数据，则要求 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span> 矩阵在行方向上是”完整“的。因此对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>矩阵同样做列拆分是无意义的。这一点从矩阵维度的代数表达上也成立，即我们要求 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span> 跟 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span> 计算时，列维度必须是embed_size。</li><li>若将 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>按行拆分，即<span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>, 则将 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>分布在一块设备上时，只能计算出1/4的数据。</li><li>因此，必须将 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>通信到所有的设备上，使用完整的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>与按列拆分的 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>进行矩阵乘法。即： <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li></ul></ul><ul class="notion-list notion-list-disc notion-block-289bd5e1d98780a3aaf5dbec0218cc7b"><li>Feature2: 按行拆分 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li><ul class="notion-list notion-list-disc notion-block-289bd5e1d98780a3aaf5dbec0218cc7b"><li>同样地，对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>按行拆分或全复制（不改变列维度），不符合矩阵乘法的要求，不具备意义。</li><li>将 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>按列拆分时，即 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>, 可得 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li><ul class="notion-list notion-list-disc notion-block-289bd5e1d987809fb295fbf64716ccc4"><li>可见，行拆分的权重特点是，输入可拆分，输出再聚合计算；而列拆分权重则是输入全复制，输出无计算</li></ul></ul></ul><ul class="notion-list notion-list-disc notion-block-289bd5e1d98780f19db0eaa495786fb5"><li>因此，矩阵乘法分片的两种基本形式是</li><ul class="notion-list notion-list-disc notion-block-289bd5e1d98780f19db0eaa495786fb5"><ol start="1" class="notion-list notion-list-numbered notion-block-289bd5e1d987804ab3e5fe694eaa2f46" style="list-style-type:decimal"><li>权重按列分片，输入广播，输出同步拼接</li></ol><ol start="2" class="notion-list notion-list-numbered notion-block-289bd5e1d98780af8832d3bd02ad2b96" style="list-style-type:decimal"><li>权重按行分片，输入按列分片，输出同步相加</li></ol></ul></ul><ul class="notion-list notion-list-disc notion-block-28bbd5e1d987801688c4ee0584d9ddf2"><li>Feature3: 按列拆分 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>后，输出内容的设备分布为按列分布，利用这个特性，也可以进行第二次乘法运算（也可以穿插若干有row locality的运算，如softmax/layer norm等）。简单过程如下</li><ul class="notion-list notion-list-disc notion-block-28bbd5e1d987801688c4ee0584d9ddf2"><li>重新定义 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li><li>第一次运用列拆分分布式乘法后可得，  <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li><li>第二次运用行拆分分布式乘法后可得， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li></ul></ul><h3 class="notion-h notion-h2 notion-h-indent-0 notion-block-289bd5e1d98780fdb26ae83501a001b5" data-id="289bd5e1d98780fdb26ae83501a001b5"><span><div id="289bd5e1d98780fdb26ae83501a001b5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#289bd5e1d98780fdb26ae83501a001b5" title="反向传播"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">反向传播</span></span></h3><ul class="notion-list notion-list-disc notion-block-289bd5e1d9878042b641f316bfa3e65e"><li><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li></ul><ul class="notion-list notion-list-disc notion-block-289bd5e1d98780e09f82c52dc02f2fd6"><li><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>按列拆分时， <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li><ul class="notion-list notion-list-disc notion-block-289bd5e1d98780e09f82c52dc02f2fd6"><li><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li></ul></ul><ul class="notion-list notion-list-disc notion-block-28bbd5e1d987803fb10ef803c0096280"><li>同理对 <span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span>按行拆分</li><ul class="notion-list notion-list-disc notion-block-28bbd5e1d987803fb10ef803c0096280"><li><span role="button" tabindex="0" class="notion-equation notion-equation-inline"><span></span></span></li></ul></ul><ul class="notion-list notion-list-disc notion-block-28bbd5e1d987807c85e4c60b8b6bc6c1"><li>二者梯度在分布设备上分别计算即可，无需聚合</li></ul><div class="notion-blank notion-block-27cbd5e1d9878082bcdef9cd6d20797b"> </div><div class="notion-blank notion-block-292bd5e1d987801bba4fca12b7c91e2b"> </div></main></div>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Paged Attention&Orca Paper笔记与解读]]></title>
            <link>https://blog.zjfwork.cc/article/26cbd5e1-d987-80ee-940b-dbbd13a7c3e7</link>
            <guid>https://blog.zjfwork.cc/article/26cbd5e1-d987-80ee-940b-dbbd13a7c3e7</guid>
            <pubDate>Fri, 12 Sep 2025 00:00:00 GMT</pubDate>
            <content:encoded><![CDATA[<div id="notion-article" class="mx-auto overflow-hidden "><main class="notion light-mode notion-page notion-block-26cbd5e1d98780ee940bdbbd13a7c3e7"><div class="notion-viewport"></div><div class="notion-collection-page-properties"></div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-273bd5e1d9878092b8b5f2a0c1aa51a7" data-id="273bd5e1d9878092b8b5f2a0c1aa51a7"><span><div id="273bd5e1d9878092b8b5f2a0c1aa51a7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#273bd5e1d9878092b8b5f2a0c1aa51a7" title="序"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">序</span></span></h2><div class="notion-text notion-block-273bd5e1d9878023a867ca62ac0da6a0">正如PagedAttention Paper开篇第一句话所说</div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-273bd5e1d98780328230d15cd2e16ab5"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A2003dd0d-8710-4dbc-b366-408797221d69%3Aimage.png?table=block&amp;id=273bd5e1-d987-8032-8230-d15cd2e16ab5&amp;t=273bd5e1-d987-8032-8230-d15cd2e16ab5" alt="notion image" loading="lazy" decoding="async"/></div></figure><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-26ebd5e1d98780ba882dd7011471d638" data-id="26ebd5e1d98780ba882dd7011471d638"><span><div id="26ebd5e1d98780ba882dd7011471d638" class="notion-header-anchor"></div><a class="notion-hash-link" href="#26ebd5e1d98780ba882dd7011471d638" title="ORCA: A Distributed Serving System for
Transformer-Based Generative Models"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">ORCA: A Distributed Serving System for
Transformer-Based Generative Models</span></span></h2><div class="notion-text notion-block-26ebd5e1d98780c09a4be0af1be4e21b">Paper地址：<a class="notion-link" href="https://www.usenix.org/system/files/osdi22-yu.pdf" target="_blank" rel="noopener noreferrer">https://www.usenix.org/system/files/osdi22-yu.pdf</a>
会议视频：<a class="notion-link" href="https://www.youtube.com/watch?v=Ob9PPLxETYU&amp;t=1s" target="_blank" rel="noopener noreferrer">https://www.youtube.com/watch?v=Ob9PPLxETYU&amp;t=1s</a></div><div class="notion-blank notion-block-26ebd5e1d987803f8003db16f41c694f"> </div><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-26ebd5e1d987809cb2fbda0a0e2b1bec"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A4213a003-6265-49bb-9496-3fac8867aea2%3Aimage.png?table=block&amp;id=26ebd5e1-d987-809c-b2fb-da0a0e2b1bec&amp;t=26ebd5e1-d987-809c-b2fb-da0a0e2b1bec" alt="notion image" loading="lazy" decoding="async"/></div></figure><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-272bd5e1d987807c86d3ca3f4127c0f5" data-id="272bd5e1d987807c86d3ca3f4127c0f5"><span><div id="272bd5e1d987807c86d3ca3f4127c0f5" class="notion-header-anchor"></div><a class="notion-hash-link" href="#272bd5e1d987807c86d3ca3f4127c0f5" title="Orca的目标问题"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Orca的目标问题</span></span></h3><div class="notion-text notion-block-272bd5e1d98780879aace17b6e7fd588">在CPU计算系统中对计算资源的管理，以OLTP，OLAP系统分类讨论。OLTP系统，典型以http/rpc等服务来说，一般以线程池为硬件计算资源在操作系统中的映射，随即典型以golang、python的asyncio、erlang otp等M:N类协程调度机制组织。典型的OLTP的服务应用中一般不存在直接利用CPU SIMD的场景，协程/线程之间的计算是不做合并的。在OLAP系统中，使用SIMD就比较常见，如Spark/Doris等“矢量化”计算的场景；因为OLAP的计算一般任务比较复杂且容易并行化，调度系统的职责就是将其切成“小块”的同质化运算，如对一批同类型的数据做同一聚合函数。但OLAP的计算隔离性一般也以task/query为维度隔离，不同的任务之间是争抢的关系。这类OLAP系统可以使用如k8s分布式虚拟化CPU，来将计算资源切分成小块，提供最大化调度的机会。</div><div class="notion-text notion-block-272bd5e1d98780558ecbc3efc6858767">在GPU计算系统中，最大的区别是，并行化本身这件事，是运行在硬件上的。本质差别是什么？本质是单个CPU的执行是线性的，因此CPU单位的所谓并行，是用软件层的调度塞满CPU的执行流水线。任何形式的CPU调度，无论是线程池/虚拟化，都是为了安排好空闲等待的任务不去占用CPU。而GPU的执行任何时候都是批量的。因此如果GPU计算的最小“请求”单位，无法在单次计算中填满GPU，那当前批次的计算就是浪费的。于是，GPU调度的系统需要去跨请求，寻求在整体系统层面的最大化利用。</div><div class="notion-text notion-block-272bd5e1d987805b841fe63705a855e9">总的来说，Orca或其他llm serving system的课题之一就是如何合并请求来最大化GPU的单次计算，提升吞吐量/降低延时。</div><div class="notion-text notion-block-272bd5e1d987809aaf48fe02ba784ccd">Naive地来说，假设我们的baseline是一个非常朴素的，等待一批，处理一批的系统，他存在哪些问题以及有什么优化手段？这个Orca和vLLM讨论的核心命题。</div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-272bd5e1d987808a8d54d358917c2ba7" data-id="272bd5e1d987808a8d54d358917c2ba7"><span><div id="272bd5e1d987808a8d54d358917c2ba7" class="notion-header-anchor"></div><a class="notion-hash-link" href="#272bd5e1d987808a8d54d358917c2ba7" title="Orca的Solution"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Orca的Solution</span></span></h3><div class="notion-text notion-block-26ebd5e1d98780cca921fcef23f47782">batching策略上的几个挑战：
（1）以请求为最小颗粒调度时，调度的粒度不对齐；存在早结束（ealy-finished）和晚到等待（late-joining）的请求。</div><ul class="notion-list notion-list-disc notion-block-26ebd5e1d9878008a22bcb2c4df417f8"><li>早结束；意味着一个batch的请求时长 跟随max_output_length的请求一起结束，延长了所有请求的完成时间</li></ul><ul class="notion-list notion-list-disc notion-block-26ebd5e1d987808ca148c44aeecb5bf0"><li>晚到等待：意味着下一个batch的请求，其等待时间也是上一个batch中最长请求的完成时间。</li></ul><ul class="notion-list notion-list-disc notion-block-26ebd5e1d98780c98ec2f06531828b52"><li>因此假设是naive的batching思路，“集合一批，处理一批”，latency取每一批中的最长请求为基本单位，且存在计算资源的闲置和内存的空占。</li></ul><ul class="notion-list notion-list-disc notion-block-26ebd5e1d98780389005d596093bcf95"><li>iterative-level的思路也很简单，自回归本身即循环调度f(x)，因此不必以request为最小颗粒，而是可以以一批对f(x)的调度为batching；那就可以将输出长度为n的请求和长度为m的请求视作(m+n)次调度，当某请求完成时，即退出调度；新的请求可以进入调度。</li></ul><div class="notion-text notion-block-26ebd5e1d987807ca7b6c98819dab998">（2）在解决1的基础上，使用iterative-level，即遇到第二个问题，tensor对齐</div><ul class="notion-list notion-list-disc notion-block-26ebd5e1d98780148cedda6a7159998d"><li>在训练或request-granularity的推理中，计算之所以可以batching，是因为self-attention计算框架约定了[batch_size, max_token_length, hidden_size]这样的tensor shape。此处可以分别做一个讨论，在问题框架上，将推理prefill和decode by step。</li><ul class="notion-list notion-list-disc notion-block-26ebd5e1d98780148cedda6a7159998d"><li>prefill阶段的naive batching可以认为是将token长度简单的padding到max_token_length可以解决</li><li>decode by step阶段，应用简易的kv cache思想，q是当前新增token的一维矩阵，多个请求batching，q的数量可以放置在batch维度中，设置为[n, 1, hidden_size]；K, V为前序token缓存二维矩阵，其shape为 [n, ?, hidden_size] —— 在iterative-level的调度中，K, V的长度不尽相同；若推理时，仍然按照潜在可能的max_token_length对齐，内存空间的使用依然是按照潜在最长输出占用。</li></ul></ul><ul class="notion-list notion-list-disc notion-block-26ebd5e1d98780fd867ecdaeb027c7cc"><li>当然latency上有优化，允许已完成的请求退出，允许等待的请求开始。理想的状况是，一个bacth中的多个请求，内存占用与真实的序列长度线性增长。</li></ul><ul class="notion-list notion-list-disc notion-block-26ebd5e1d98780308bf8e280074a48f7"><li>selective-batching：思考batch_size维度在计算上存在的意义，先不考虑multi-head这个因素。同一个batch内，除了scaled-dot attention的QK计算需要行列交互，其他的计算如MLP，softmax，layer norm——更不用说element-wise，都是在行内的操作。因此若假设两个长度不一的请求（两段prompt），假设长度为s1, s2；在原始计算框架下需要合并成两个batch，[2, max(s1, s2), hidden_size]；而在selective-batching方法中，可以合并成[1, s1 + s2, hidden_size]。在non-request-aware operation中，可以当做一个请求处理；在执行attention时，再拆成两个请求（也许是[2, max(s1, s2), hidden_size]）。</li></ul><ul class="notion-list notion-list-disc notion-block-272bd5e1d987800aba2fe780c86264b6"><li>selective-batching不仅可以合并同样在prefill阶段的不同长度请求，在另一个方面也让prefill阶段和decode by step阶段可以合并计算；prefill阶段的输入是长度为任意s的用户promot；decode by step阶段输入是长度为1的last token配合有状态的kv cache manager。在计算时，系统只需要在attention时，能够区分(1) 不同请求的划分 （2）不同请求的阶段 - 决定是否需要查询kv cache参与计算。</li></ul><ul class="notion-list notion-list-disc notion-block-272bd5e1d98780cc98cfe22ec037f1c6"><li>🤔思考：在selective-batching的框架下，是否需要考虑[X, hidden_size]的形状对GPU计算效率的影响。X可能会变得远大于hidden_size。</li></ul><div class="notion-text notion-block-272bd5e1d98780b5afafcea5af6fbebb">（3）Orca scheduling algorithm: iterative-level和selective-batching解决了“颗粒”和“颗粒“细化后的合并问题；下一个Orca讨论的命题就是，面对N个request产生的M个iteration全集里，在时刻t的由（requtest_i, iteration_j）组成的request pool里，每一个调度计算时，如何选择的出一个集合执行计算的问题。</div><ul class="notion-list notion-list-disc notion-block-272bd5e1d9878038bcdae5af767e0d63"><li>Orca遵循先进先出（文中称FCFS，first come first serve）的原则；对请求到达时间排序，并以内存资源为优先的瓶颈，填充资源</li><ul class="notion-list notion-list-disc notion-block-272bd5e1d9878038bcdae5af767e0d63"><li>n_rsrv可以理解为KV cache使用的连续内存空间；每个request的prefill被执行时，会扣除request.max_token这么大的资源预占（这也是paged attention要解决的问题）；而因为按到达序排序，因此prefill之后的请求会稳定地出现在之后批次的serve batch里，直到请求结束，占用的KV cache slots被释放。</li><li>PagedAttention主要优化的问题，即KV cache的生命周期管理与分布方式 &amp; 具体地与decoding algo结合的使用场景。</li><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-272bd5e1d98780c79f1fea073c829633"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3A89d11937-450b-44f1-ba42-8c021bc8e189%3Aimage.png?table=block&amp;id=272bd5e1-d987-80c7-9f1f-ea073c829633&amp;t=272bd5e1-d987-80c7-9f1f-ea073c829633" alt="notion image" loading="lazy" decoding="async"/></div></figure></ul></ul><div class="notion-text notion-block-272bd5e1d9878025b058c3faec292e27">（4）paper中讨论的分布式并行方式（intra/inter-layer），我感觉不在重点讨论范围。本文更关键的思路还是如何通过调度原语（split or merge），分配计算资源。</div><div class="notion-blank notion-block-272bd5e1d987809cbcf5c0ad4808fff6"> </div><div class="notion-blank notion-block-26ebd5e1d98780d2b6daffa4b59ceb0d"> </div><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-26ebd5e1d9878070a3ace7f5b232feca" data-id="26ebd5e1d9878070a3ace7f5b232feca"><span><div id="26ebd5e1d9878070a3ace7f5b232feca" class="notion-header-anchor"></div><a class="notion-hash-link" href="#26ebd5e1d9878070a3ace7f5b232feca" title="Efficient Memory Management for Large Language
Model Serving with PagedAttention"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">Efficient Memory Management for Large Language
Model Serving with PagedAttention</span></span></h2><div class="notion-text notion-block-272bd5e1d9878028a5dbd866a607cf97">paper地址：<a class="notion-link" href="https://arxiv.org/pdf/2309.06180" target="_blank" rel="noopener noreferrer">https://arxiv.org/pdf/2309.06180</a></div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-272bd5e1d9878030b17cca852be501b6" data-id="272bd5e1d9878030b17cca852be501b6"><span><div id="272bd5e1d9878030b17cca852be501b6" class="notion-header-anchor"></div><a class="notion-hash-link" href="#272bd5e1d9878030b17cca852be501b6" title="PagedAttention的目标问题"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">PagedAttention的目标问题</span></span></h3><div class="notion-text notion-block-272bd5e1d987802c9d44de003c0ecb80">基于Orca这样解决了调度Batching问题的系统基础上，还有哪些地方的优化可以提升系统整体的吞吐量和延时？</div><div class="notion-text notion-block-272bd5e1d9878090a055d15711a3636e">Insight：Orca系统中最显眼的“浪费”是在处理batching请求时，batch中的每个request都占用了request.max_token大小的显存用于存放KV cache；且该占用的生命周期是整个request存在的期间。直观上，显存的利用率是比较低的。</div><div class="notion-text notion-block-272bd5e1d98780369c62fb55dcc1d070">若引入一种机制，使得request占用的显存尽量贴近当前真实使用的大小，那么同样大小的GPU memory就大概率会允许更多的request进入当前batch（假设batch大小对计算不是瓶颈），从而在memory-bound假设的系统中吞吐量会上升，延时会降低。</div><div class="notion-text notion-block-272bd5e1d9878082a9c5c78e4ee8859d">此外Orca中还有一类“隐藏问题”没有被提及，LLM的decoding算法不总是基于贪心的单一线性路径，单一线性路径下token generation path是唯一的；若使用beam search这样的多分支搜索，如何管理KV cache的临时存储与释放？Naive的方法是在beam search时，每一个可能的N条路径都预占一份len == request.max_tokens的KV cache且需要在“路径”被淘汰时释放，在“路径”被扩展时copy，这显然是不可行的。因此执行beam search时，在KV cache管理上需要允许引用公共前缀与独立分叉的申请与释放。这样势必导致KV cache在至少一个路径上是不连续。于是是否KV cache一定要存放在连续显存中，成为了一个疑问。</div><div class="notion-blank notion-block-273bd5e1d9878072bd5be30aca3a2150"> </div><h3 class="notion-h notion-h2 notion-h-indent-1 notion-block-272bd5e1d987806d9d0fe17d95fa1313" data-id="272bd5e1d987806d9d0fe17d95fa1313"><span><div id="272bd5e1d987806d9d0fe17d95fa1313" class="notion-header-anchor"></div><a class="notion-hash-link" href="#272bd5e1d987806d9d0fe17d95fa1313" title="PagedAttention的方法"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">PagedAttention的方法</span></span></h3><div class="notion-text notion-block-273bd5e1d9878091b115f4e1fa981e4e">引用文中Abstract的描述</div><blockquote class="notion-quote notion-block-273bd5e1d987809fb11cf556e7319609"><div>On top of it, we build vLLM, an LLM serving system that achieves (1) near-zero waste in KV cache memory and (2) flexible sharing of KV cache within and across requests to further reduce memory usage.</div></blockquote><div class="notion-text notion-block-272bd5e1d98780c49b4ce9518be6960a">一句话描述：模拟操作系统的虚拟内存，在KV cache需要时才实际占用显存。</div><div class="notion-text notion-block-272bd5e1d98780c7a2f3c465622614f5">随之而来的几个问题</div><ol start="1" class="notion-list notion-list-numbered notion-block-272bd5e1d9878046ae32f7c790505eaa" style="list-style-type:decimal"><li>如何定义一页/一块（page or block）</li><ol class="notion-list notion-list-numbered notion-block-272bd5e1d9878046ae32f7c790505eaa" style="list-style-type:lower-alpha"><ul class="notion-list notion-list-disc notion-block-273bd5e1d98780389b34de493032460d"><li>OS VMM模块管理的是一一映射的对等概念，虚拟内存与物理内存单位都是byte，只是按一定的page size划分；无论OS层面运行什么样的软件，one page就是4kb/8kb/16kb等整数。而vLLM的管理对象是KV cache，是一个有具体的计算含义的变长实体。具体来说，一个Transformer-based的模型有attention layer count, hidden_size, head_size，其他还有一些算法变体等参数会影响单个token的KV Cache到底多大。此外无论如何，单个token的所有KV cache放在一起过于巨大（100kb~10MB之间），理应有一个“切割”的思考，按类（K or V）切 or 按层切 or 两个维度都切分，也是一个因素。</li></ul></ol></ol><ol start="2" class="notion-list notion-list-numbered notion-block-272bd5e1d98780cb9310ed3beab17d42" style="list-style-type:decimal"><li>如何trade off非连续的KV cache存放机制与实际计算时内存连续的要求</li><ol class="notion-list notion-list-numbered notion-block-272bd5e1d98780cb9310ed3beab17d42" style="list-style-type:lower-alpha"><ul class="notion-list notion-list-disc notion-block-273bd5e1d9878025923fe232dc2fd7f3"><li>当KV cache以物理上非连续的方式在逻辑数据结构中被索引时，前序token的KV矩阵就不再是可以直接被GPU矩阵乘法计算的对象；不像Orca中申请max_tokens为基数的连续内存方便。</li></ul></ol></ol><ol start="3" class="notion-list notion-list-numbered notion-block-272bd5e1d9878070bc8afa3f5e4fac1a" style="list-style-type:decimal"><li>HBM不足时，evict策略是什么</li><ol class="notion-list notion-list-numbered notion-block-272bd5e1d9878070bc8afa3f5e4fac1a" style="list-style-type:lower-alpha"><ul class="notion-list notion-list-disc notion-block-273bd5e1d98780948651d9dbe69f7208"><li>Orca的连续内存策略能够“悲观”地保证进入bacth的请求，有足够的内存资源能够完成选中的请求；但虚拟内存的方式，只在申请物理内存时，“乐观”地事后知晓物理内存分配不足；（1）若没有evict策略，直接请求失败，则会导致类似惊群或死锁的问题，请求集体失败，集体重试，再集体失败（2）若有evict策略，调度系统逐出一些潜在低效的占用，那么有若干个问题：evict的时机是什么，慢介质是什么，选择策略是什么，数量怎么决定</li></ul></ol></ol><ol start="4" class="notion-list notion-list-numbered notion-block-272bd5e1d98780c8a282ed3b0a045792" style="list-style-type:decimal"><li>如何与类似beam search的搜索路径配合，复用的策略</li></ol><div class="notion-blank notion-block-276bd5e1d987808f894aee839f5f713e"> </div><div class="notion-text notion-block-276bd5e1d98780afb293f6e85c3b4ef4">问题1：以token为单位，定义one block的token size(block size)；K V分开存放；异构模型size不同如何解决，文中并未提到。</div><div class="notion-text notion-block-276bd5e1d98780ffa0a9c182fcf7e4cd">问题2：分块计算当前q向量与K的乘积，并开发相应的cuda kernel进行优化；且vllm是一个分布式系统，以local compute为计算策略是显然的。这里会涉及到较多细节且复杂的模型并行通信原语。</div><div class="notion-text notion-block-276bd5e1d98780c495a1cf3df9ae4a78">问题3：此处文中提出了两种逐出介质，并在消融实验中声称各有优劣</div><ul class="notion-list notion-list-disc notion-block-277bd5e1d98780a88a6fedfd1581199f"><li>引入sequence group的概念，意即完成一个请求所带来的需要KV cache，根据解码算法不同，一个request会产生一到多条推理sequence; 本文采用了all or nothing的策略，在sequence group的维度上，要么逐出sequence group的所有的KV cache，要么不逐出任何一块。因为vLLM假设不存在一种有收益的场景叫做，部分KV cache存在，可以先进行部分的计算。这种比iteration-level更为复杂的计算机制，超出了Orca/vLLM等最细粒度的框架假设。</li></ul><ul class="notion-list notion-list-disc notion-block-277bd5e1d987806897b1d029520d92aa"><li>解法一：逐出到CPU内存中；解法二：清除内容，后续重新计算，重新计算的速度是不慢的，重新获得kv cache就是经历一次新的prefill阶段；；需要考量内存显存带宽 pk 计算能力</li></ul><ul class="notion-list notion-list-disc notion-block-277bd5e1d9878015b49bc5356d141b8c"><li>请求调度的额外策略：当逐出发生时，系统就不再接受新的请求，直到先前被抢占的任务完成。这也是一个FCFS的原则（那么在被抢占任务完成前，系统是否有一段时间是跑不满的？）；文中讲到这获得了一个额外的特性，CPU RAM作为缓冲区，容量需求不会超过GPU HBM大小。</li></ul><div class="notion-text notion-block-276bd5e1d98780e7827cd42752153137">问题4：引入reference count + copy on write复用与释放内存</div><div class="notion-blank notion-block-277bd5e1d987805ead4fe2cb8f95b1e7"> </div><ul class="notion-list notion-list-disc notion-block-277bd5e1d987809d9de8cea693ac2bcf"><li>并行decoding采样。并行decoding采样定义：N个互不相关的随机采样序列以特定的随机参数运行。在这个场景下，request prompt是确定的N个sequence的prefix，token长度为L的prompt会产生至少向下取整(L/block_size)个完整的block，这些block在request生命周期中被每一个sequence的每一次generation复用；最后 &lt; block_size个prompt的KV cache填不满一页，会被copy N份用于后续采样的一部分。</li></ul><ul class="notion-list notion-list-disc notion-block-277bd5e1d9878081be8ff6dc26d9270f"><li>beam search采样过程中，更复杂的点在于，路径会动态地生成与销毁。prompt也是确定可以被多个sequence复用的；进行过程中对token产生的block进行引用计数；beam search with k的设定下，t时刻下，m（m≤k）条路径依赖来自t-1时刻产生的前缀，那么reference count记为m。在t+1时刻，m条路径会派生出m*k条新路径参与下一轮概率选择，其中有[0, k]个路径会生出，由此也会决定，在t时刻，reference count是[0, k]中的一个数字。若某block的reference count降为0，则释放。</li></ul><ul class="notion-list notion-list-disc notion-block-277bd5e1d98780baa6a4f6d5b6baf0b8"><li>这两类采样算法，在PagedAttention中的原理完全是一致的。通过reference count + copy on write实现了复用，区别只是fork和reference count的操作时机不同。前者的fork只存在第一个token生成时（若token length与block size是整数关系，则没有fork过程）；后者的fork在行进中随时会分叉。前者无需管理reference count；后者需要通过reference count管理释放时机。</li></ul><figure class="notion-asset-wrapper notion-asset-wrapper-image notion-block-277bd5e1d98780b8bdaadd433e99607c"><div style="position:relative;display:flex;justify-content:center;align-self:center;width:100%;max-width:100%;flex-direction:column;height:100%"><img style="object-fit:cover" src="https://www.notion.so/image/attachment%3Ae3976fb8-0363-453c-a111-794bb2534332%3Aimage.png?table=block&amp;id=277bd5e1-d987-80b8-bdaa-dd433e99607c&amp;t=277bd5e1-d987-80b8-bdaa-dd433e99607c" alt="notion image" loading="lazy" decoding="async"/></div></figure><h2 class="notion-h notion-h1 notion-h-indent-0 notion-block-277bd5e1d9878093a539e3e86dd86095" data-id="277bd5e1d9878093a539e3e86dd86095"><span><div id="277bd5e1d9878093a539e3e86dd86095" class="notion-header-anchor"></div><a class="notion-hash-link" href="#277bd5e1d9878093a539e3e86dd86095" title="总结"><svg viewBox="0 0 16 16" width="16" height="16"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a><span class="notion-h-title">总结</span></span></h2><div class="notion-text notion-block-277bd5e1d987806aad88cdff96471d5c">通过阅读Orca与Paged Attention Paper，大致了解了LLM serving中的一些基本问题。</div><div class="notion-text notion-block-277bd5e1d9878087857af31f997e1502">但偏insight，还需要在实现中寻找更多的技术细节。</div><div class="notion-text notion-block-277bd5e1d987800d955dc53f2e13c997">比如，vllm架构设计上是怎么样的，分为哪些模块；vllm管理分布式GPU是如何计算和通信的；哪些是kernel；block table是什么结构等</div></main></div>]]></content:encoded>
        </item>
    </channel>
</rss>