<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>JMY Space</title>
  <icon>https://www.jmyjmy.top/img/avatar.webp</icon>
  <subtitle>Take notes, Log lifes</subtitle>
  <link href="https://www.jmyjmy.top/atom.xml" rel="self"/>
  
  <link href="https://www.jmyjmy.top/"/>
  <updated>2026-03-05T15:21:20.000Z</updated>
  <id>https://www.jmyjmy.top/</id>
  
  <author>
    <name>Jimmy</name>
    
  </author>
  
  <generator uri="https://hexo.io/">Hexo</generator>
  
  <entry>
    <title>把 AI 当个&quot;人&quot;——LLM 使用者应该知道的事（1）</title>
    <link href="https://www.jmyjmy.top/2026-03-05_LLMaaS-intro/"/>
    <id>https://www.jmyjmy.top/2026-03-05_LLMaaS-intro/</id>
    <published>2026-03-05T15:21:20.000Z</published>
    <updated>2026-03-05T15:21:20.000Z</updated>
    
    <content type="html"><![CDATA[<p>2026 年的今天，AI 已经足够聪明，你应该把它当个&quot;人&quot;来对待了——至少也是条聪明的&quot;边牧&quot;。</p><hr><h2 id="基础概念"><a class="header-anchor" href="#基础概念">¶</a>基础概念</h2><p><strong>Token</strong>（常被机翻为&quot;令牌&quot;，但这个译名并不好）：Token 是模型处理文本的最小单位。你可以粗略理解为&quot;字词的碎片&quot;——中文里一个汉字通常对应 1～2 个 Token，英文单词可能被拆成好几个。它是衡量输入输出长度、也是计费的基本单位。</p><p><strong>一般调用 LLM 的链路：</strong></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">用户 → App → LLM 服务</span><br></pre></td></tr></table></figure><p>你平时用的 ChatGPT、Kimi、豆包，都是 App。App 负责把你的话打包成请求发给背后的 LLM 服务，再把 LLM 的回复展示给你。你并不是在直接和模型对话。</p><h2 id="llm-的运行过程"><a class="header-anchor" href="#llm-的运行过程">¶</a>LLM 的运行过程</h2><p>每一次请求，模型内部分为两个阶段：</p><h3 id="1-prefill（预填充）"><a class="header-anchor" href="#1-prefill（预填充）">¶</a>1. Prefill（预填充）</h3><p>模型读取并理解你发来的所有内容。这个阶段<strong>不会产生任何输出</strong>，你会看到界面上光标在转圈——不是卡了，而是模型在&quot;想&quot;。</p><p>这段等待时间叫 <strong>TTFT（Time To First Token）</strong>，即&quot;从发送到冒出第一个字&quot;的耗时，通常 1～5 秒。</p><h3 id="2-decode（解码-生成）"><a class="header-anchor" href="#2-decode（解码-生成）">¶</a>2. Decode（解码/生成）</h3><p>模型开始<strong>逐字往外吐内容</strong>。每生成一个 Token 的间隔叫 <strong>TPOT（Time Per Output Token）</strong>，通常 10～50 毫秒——所以你会看到文字是&quot;打字机式&quot;一个一个蹦出来的。</p><h3 id="thinking（思考）"><a class="header-anchor" href="#thinking（思考）">¶</a>Thinking（思考）</h3><p>部分模型（如 Claude、DeepSeek-R1）支持 thinking 模式。模型会先输出一段思考过程，再给出正式回答。对模型来说，thinking 的内容和普通输出没有区别，都属于 Decode 阶段；只是 App 在界面上把它折叠起来单独展示而已。</p><h3 id="端到端时长（e2e-latency）"><a class="header-anchor" href="#端到端时长（e2e-latency）">¶</a>端到端时长（E2E Latency）</h3><p>了解了两个阶段，一次完整请求的总耗时就很好算了：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">总耗时 = TTFT + TPOT × 输出 Token 数</span><br><span class="line">         （想的时间）  （写的时间）</span><br></pre></td></tr></table></figure><p>举个例子，假设模型回复了 500 个 Token：</p><table><thead><tr><th>阶段</th><th>耗时</th><th>说明</th></tr></thead><tbody><tr><td>TTFT</td><td>2s</td><td>模型读题、思考</td></tr><tr><td>Decode</td><td>50ms × 500 = 25s</td><td>逐字输出</td></tr><tr><td><strong>合计</strong></td><td><strong>≈ 27s</strong></td><td>你从发送到看完完整回复的时间</td></tr></tbody></table><p>所以你会发现：<strong>短回复的瓶颈在 Prefill（等第一个字慢），长回复的瓶颈在 Decode（写得慢）。</strong></p><p>这也解释了一个日常体感——问 AI 一个简单问题，感觉&quot;想了好久才开口，但一开口秒答完&quot;；让它写一篇长文，第一个字来得还行，但要等很久才写完。</p><p>如果模型开启了 Thinking，thinking 的内容也是 Decode 输出的一部分，会实实在在地占用生成时间，E2E 会明显变长。这就是&quot;深度思考&quot;模式更慢的原因——不是因为用了更厉害的模型，而是它<strong>真的多写了一大段思考过程</strong>。</p><h3 id="cache（上下文缓存）"><a class="header-anchor" href="#cache（上下文缓存）">¶</a>Cache（上下文缓存）</h3><p>一个关键事实：<strong>每次你发消息，App 实际上把整个对话历史都发给了模型</strong>，而不是只发你最新这一条。</p><p>这意味着随着对话变长，每轮发送的 Token 数越来越大——第 1 轮发 100 token，第 2 轮发 300，第 3 轮发 600……总消耗是累加增长的，账单也会越来越贵。</p><p>缓存就是为了解决这个问题：服务端把之前已经处理过的上下文缓存下来，下一轮 Prefill 时跳过这些部分，既省时间，也省钱。这就是为什么很多平台对&quot;缓存命中&quot;的 Token 收费更低。</p><hr><h2 id="从-prompt-工程到-agent"><a class="header-anchor" href="#从-prompt-工程到-agent">¶</a>从 Prompt 工程到 Agent</h2><h3 id="prompt-engineering（提示词工程）"><a class="header-anchor" href="#prompt-engineering（提示词工程）">¶</a>Prompt Engineering（提示词工程）</h3><p>输入给 LLM 的内容叫 <strong>Prompt</strong>。早期模型没那么聪明，想让 AI 按预期干活，需要反复调整措辞、格式、示例，这个过程就叫 Prompt Engineering。一度还催生了专门的岗位——Prompt 工程师。</p><h3 id="agent（智能体）"><a class="header-anchor" href="#agent（智能体）">¶</a>Agent（智能体）</h3><p>以前的模式是：你问 AI 怎么做 → AI 告诉你步骤 → 你自己动手。</p><p>Agent 的思路是：<strong>让 AI 自己想，自己动手。</strong> 做一个程序，自动问 AI&quot;下一步做什么&quot;，然后根据 AI 的回答自动执行操作——让电脑操作自己。</p><p>更进一步，你可以定义多个 Agent 各司其职——产品经理 Agent、程序员 Agent、架构师 Agent、测试 Agent——让它们协作完成任务。这就是所谓的 Multi-Agent，也是&quot;AI 驱动公司&quot;概念的雏形。</p><h3 id="tool-call（工具调用，以前叫-function-call）"><a class="header-anchor" href="#tool-call（工具调用，以前叫-function-call）">¶</a>Tool Call（工具调用，以前叫 Function Call）</h3><p>AI 的输出本质上是不确定的纯文本，但很多场景需要<strong>确定性的、结构化的操作</strong>。Tool Call 就是给 AI 提供一套&quot;工具菜单&quot;，让它在需要时按规定格式发起调用。</p><p>比如在 App 中定义一个工具：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span></span><br><span class="line">  <span class="attr">&quot;tool&quot;</span><span class="punctuation">:</span> <span class="string">&quot;查询天气&quot;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;输入&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;地点&quot;</span><span class="punctuation">:</span> <span class="string">&quot;string&quot;</span> <span class="punctuation">&#125;</span><span class="punctuation">,</span></span><br><span class="line">  <span class="attr">&quot;输出&quot;</span><span class="punctuation">:</span> <span class="punctuation">&#123;</span> <span class="attr">&quot;气温&quot;</span><span class="punctuation">:</span> <span class="string">&quot;number&quot;</span> <span class="punctuation">&#125;</span></span><br><span class="line"><span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p>当 AI 判断用户想知道天气时，它不会瞎编一个温度，而是输出：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="punctuation">&#123;</span> <span class="attr">&quot;tool&quot;</span><span class="punctuation">:</span> <span class="string">&quot;查询天气&quot;</span><span class="punctuation">,</span> <span class="attr">&quot;地点&quot;</span><span class="punctuation">:</span> <span class="string">&quot;上海&quot;</span> <span class="punctuation">&#125;</span></span><br></pre></td></tr></table></figure><p><strong>注意：AI 只是表达&quot;我认为现在该查天气了&quot;，真正去调用天气接口的是 App。</strong> AI 负责判断，App 负责执行。</p><h3 id="mcp（model-context-protocol，模型上下文协议）"><a class="header-anchor" href="#mcp（model-context-protocol，模型上下文协议）">¶</a>MCP（Model Context Protocol，模型上下文协议）</h3><p>Tool Call 有个前提：你得自己定义工具。但如果你不知道怎么查天气呢？天气服务商有 API 文档，但普通用户看不懂怎么办？</p><p>MCP 解决的就是这个问题：<strong>让服务商把工具打包好，放到一个标准化的 MCP Server 上；用户只需要添加这个 Server，就自动获得一系列可用的工具。</strong></p><p>比如添加&quot;彩云天气&quot;的 MCP Server 后，你的 AI 就自动拥有了 5 个工具：</p><table><thead><tr><th>#</th><th>工具名</th><th>功能</th></tr></thead><tbody><tr><td>1</td><td><code>get_realtime_weather</code></td><td>查询实时天气</td></tr><tr><td>2</td><td><code>get_hourly_forecast</code></td><td>查询逐小时预报</td></tr><tr><td>3</td><td><code>get_weekly_forecast</code></td><td>查询一周预报</td></tr><tr><td>4</td><td><code>get_historical_weather</code></td><td>查询历史天气</td></tr><tr><td>5</td><td><code>get_weather_alerts</code></td><td>查询天气预警</td></tr></tbody></table><p>你不需要写任何代码，AI 也不需要额外的提示——工具自描述，即插即用。</p><h3 id="一个真实的例子：claude-code"><a class="header-anchor" href="#一个真实的例子：claude-code">¶</a>一个真实的例子：Claude Code</h3><p>说了这么多，Agent 到底长什么样？拿 Claude Code 举例——它是一个跑在终端里的<strong>代码 Agent</strong>。</p><p>假设你对它说：</p><blockquote><p>“登录页面点击按钮后没反应，帮我修一下”</p></blockquote><p>接下来发生的事情：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">┌─ 你（一句话描述任务）</span><br><span class="line">│</span><br><span class="line">│  ┌─ Claude Code 的循环 ──────────────────────────┐</span><br><span class="line">│  │                                                │</span><br><span class="line">│  │  1. 思考：登录相关代码在哪？                      │</span><br><span class="line">│  │     ↓                                          │</span><br><span class="line">│  │  2. 调用工具：搜索代码库，找到 login.tsx           │</span><br><span class="line">│  │     ↓                                          │</span><br><span class="line">│  │  3. 调用工具：读取 login.tsx 内容                 │</span><br><span class="line">│  │     ↓                                          │</span><br><span class="line">│  │  4. 思考：onClick 里调了接口但没 await，找到 bug   │</span><br><span class="line">│  │     ↓                                          │</span><br><span class="line">│  │  5. 调用工具：编辑 login.tsx，加上 await           │</span><br><span class="line">│  │     ↓                                          │</span><br><span class="line">│  │  6. 调用工具：运行 npm test                       │</span><br><span class="line">│  │     ↓                                          │</span><br><span class="line">│  │  7. 思考：测试全过了，任务完成                      │</span><br><span class="line">│  │                                                │</span><br><span class="line">│  └────────────────────────────────────────────────┘</span><br><span class="line">│</span><br><span class="line">└─ Claude Code：已修复，原因是 onClick 中缺少 await</span><br></pre></td></tr></table></figure><p>整个过程的关键在于——<strong>你只说了一句话，剩下的全是 AI 自己在循环</strong>：</p><table><thead><tr><th>环节</th><th>谁在干活</th><th>在做什么</th></tr></thead><tbody><tr><td>思考</td><td>LLM</td><td>判断下一步该做什么</td></tr><tr><td>调用工具</td><td>Claude Code（App）</td><td>根据 LLM 的判断去执行（读文件、改代码、跑命令）</td></tr><tr><td>观察结果</td><td>LLM</td><td>看工具返回了什么，决定是否继续</td></tr></tbody></table><p>这就是 Agent 的核心模式：<strong>思考 → 行动 → 观察 → 再思考</strong>，不断循环直到任务完成。</p><p>你可能注意到了——这里面的&quot;调用工具&quot;就是前面说的 <strong>Tool Call</strong>。Claude Code 内置了一系列工具（搜索文件、读写代码、执行命令、访问网页等），LLM 在需要时自己决定调哪个。</p><p>所以 Agent 并不是什么新技术，而是 <strong>LLM + Tool Call + 循环</strong> 的组合。把&quot;人问一次 AI 答一次&quot;变成了&quot;AI 自己问自己、自己干、干到完&quot;。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;2026 年的今天，AI 已经足够聪明，你应该把它当个&amp;quot;人&amp;quot;来对待了——至少也是条聪明的&amp;quot;边牧&amp;quot;。&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;基础概念&quot;&gt;&lt;a class=&quot;header-anchor&quot;</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>LLM inference system overview</title>
    <link href="https://www.jmyjmy.top/2026-03-05_LLM-inference-system-overview/"/>
    <id>https://www.jmyjmy.top/2026-03-05_LLM-inference-system-overview/</id>
    <published>2026-03-05T14:05:02.000Z</published>
    <updated>2026-03-05T14:05:02.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="1-智能流量路由（smart-router）"><a class="header-anchor" href="#1-智能流量路由（smart-router）">¶</a>1. 智能流量路由（Smart Router）</h2><p>作为系统的流量入口，Router 不仅充当网关的角色，更是保障服务稳定性与会话连续性的第一道防线。</p><ul><li><p><strong>会话保持（Session Stickiness）：</strong><br>基于请求内容（Request Content）生成的唯一指纹或 Session ID，Router 会精确记录每个会话与后端节点的映射关系。确保同一会话的后续请求被路由至同一固定节点，从而最大化利用本地缓存（KV Cache），避免重复计算带来的资源浪费。</p></li><li><p><strong>动态负载均衡与热点防御：</strong><br>为防止单节点因流量突增而过载（Hotspot），系统引入了严格的 <strong>Server Load Threshold（服务器负载阈值）</strong> 机制。当特定节点的负载触及红线时，Router 将智能介入，进行流量整形或请求重路由，确保集群整体的健康度与吞吐量。</p></li></ul><h2 id="2-kv-cache-offload"><a class="header-anchor" href="#2-kv-cache-offload">¶</a>2. KV Cache Offload</h2><p>显存容量是制约 LLM 推理吞吐量的主要瓶颈。为了突破单卡显存限制，<strong>L1-L4 多级流水线式</strong> 的 KV Cache 存储架构，按访问速度分层管理：</p><ul><li><strong>L1 (GPU HBM):</strong> 存放最活跃的 Hot KV Cache，确保核心计算微秒级响应。</li><li><strong>L2 (CPU Memory):</strong> 利用 Host 内存作为次级缓冲区，通过 PCIe 快速交换数据。</li><li><strong>L3 (Remote GPU via RDMA):</strong> 当本地资源耗尽时，通过 RDMA（远程直接内存访问）技术极速“借用”其他空闲节点的显存，实现显存池化。</li><li><strong>L4 (NVMe SSD):</strong> 作为冷数据的最终落脚点，提供海量存储兜底。</li></ul><blockquote><p><strong>技术推荐 <a href="https://github.com/novitalabs/pegaflow">Pegaflow</a>:</strong><br>针对单节点多 GPU 场景，Pegaflow 提供了一套高性能的卸载方案，能有效提升推理引擎的显存利用效率。</p><p><em>延伸阅读</em>: 可参考 Dynamo KVBM 和 llm-d-kv-cache 等相关技术实现。</p></blockquote><h2 id="3-p-d-分离架构（prefill-decode-disaggregation）"><a class="header-anchor" href="#3-p-d-分离架构（prefill-decode-disaggregation）">¶</a>3. P/D 分离架构（Prefill/Decode Disaggregation）</h2><p>在高度互动的场景中（如 AI 伴侣、实时对话 App），用户对首字延迟（TTFT）和生成流畅度（TPOT）极为敏感。传统的混合部署模式下，高负载的 Prefill（预填充）阶段往往会抢占计算资源，导致 Decode（解码）阶段卡顿。</p><p>我们采用了 <strong>Prefill 与 Decode 分离</strong> 的解耦架构：</p><ul><li><p><strong>核心优势：</strong> 彻底隔离计算密集型的 Prefill 阶段与访存密集型的 Decode 阶段。无论新请求如何涌入，Decode 节点始终拥有独立的计算资源，保证输出如丝般顺滑，不被中断。</p></li><li><p><strong>关键技术依赖：</strong></p><ul><li><strong>可靠的 RDMA 网络：</strong> 该架构要求 Prefill 节点计算完的 KV 状态能以极低延迟传输至 Decode 节点。</li><li><strong>增量传输机制：</strong> 仅需传输新增 Token 对应的 KV 数据，而非全量搬运，大幅降低网络带宽压力。</li><li><strong>Decode 本地缓存：</strong> 接收端节点维护热数据缓存，进一步加速生成。</li></ul></li><li><p><strong>传输后端（Transfer Backend）选型：</strong></p><ul><li><strong>NIXL</strong></li><li><strong>Mooncake</strong> (KVCache 分离架构的典型代表)</li></ul></li></ul><h2 id="推理引擎"><a class="header-anchor" href="#推理引擎">¶</a>推理引擎</h2><ul><li>首选 <a href="https://vllm.ai/">vllm</a></li><li><a href="https://www.sglang.io/">sglang</a></li></ul><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  flowchart TB    %% 样式定义    classDef routerStyle fill:#4A90D9,stroke:#2C5F8A,color:#fff,stroke-width:2px,font-size:14px    classDef prefillHitStyle fill:#27AE60,stroke:#1E8449,color:#fff,stroke-width:2px    classDef prefillMissStyle fill:#E67E22,stroke:#BA6617,color:#fff,stroke-width:2px    classDef decodeStyle fill:#9B59B6,stroke:#7D3C98,color:#fff,stroke-width:2px    classDef pegaStyle fill:#1ABC9C,stroke:#16A085,color:#fff,stroke-width:1px    classDef clientStyle fill:#34495E,stroke:#2C3E50,color:#fff,stroke-width:2px    %% Client    CLIENT([🖥️ Client Request]):::clientStyle    %% Router    ROUTER[&quot;🌐 Router&lt;br&#x2F;&gt; session亲和&lt;br&#x2F;&gt;一致性哈希&lt;br&#x2F;&gt;load aware&quot;]:::routerStyle    CLIENT --&gt; ROUTER    %% &#x3D;&#x3D;&#x3D;&#x3D;&#x3D; Prefill Hit Cache &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;    subgraph PH[&quot;Prefill 命中缓存&quot;]        direction TB        PH_NODE[&quot;⚡ Prefill Node&lt;br&#x2F;&gt;(Cache Hit)&lt;br&#x2F;&gt;─────────────&lt;br&#x2F;&gt;• 本地命中前缀&lt;br&#x2F;&gt;• 仅计算增量部分&quot;]:::prefillHitStyle        PH_PEGA[(&quot;🗄️ PegaFlow&lt;br&#x2F;&gt;本机 CPU&#x2F;SSD&lt;br&#x2F;&gt;─────────────&lt;br&#x2F;&gt;• 已有 KV Cache&lt;br&#x2F;&gt;• 命中 → 直接复用&quot;)]:::pegaStyle        PH_PEGA &lt;--&gt;|&quot;KV Load&#x2F;Save&quot;| PH_NODE    end    %% &#x3D;&#x3D;&#x3D;&#x3D;&#x3D; Prefill Miss Cache &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;    subgraph PM[&quot;Prefill 未命中缓存&quot;]        direction TB        PM_NODE[&quot;⚡ Prefill Node&lt;br&#x2F;&gt;(Cache Miss)&lt;br&#x2F;&gt;─────────────&lt;br&#x2F;&gt;• 首次请求无缓存&lt;br&#x2F;&gt;执行完整 Prefill&lt;br&#x2F;&gt;•后续请求无缓存&lt;br&#x2F;&gt;从其他节点pull&quot;]:::prefillMissStyle        PM_PEGA[(&quot;🗄️ PegaFlow&lt;br&#x2F;&gt;本机 CPU&#x2F;SSD&lt;br&#x2F;&gt;─────────────&lt;br&#x2F;&gt;• 计算后写入 KV&lt;br&#x2F;&gt;• 供后续请求复用&quot;)]:::pegaStyle        PM_NODE --&gt;|&quot;Prefill 完成&lt;br&#x2F;&gt;KV Save&quot;| PM_PEGA    end    %% &#x3D;&#x3D;&#x3D;&#x3D;&#x3D; Decode &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;    subgraph DEC[&quot;Decode&quot;]        direction TB        D_NODE[&quot;🔄 Decode Node&lt;br&#x2F;&gt;─────────────&lt;br&#x2F;&gt;• 接收 KV Cache&lt;br&#x2F;&gt;&quot;]:::decodeStyle        D_PEGA[(&quot;🗄️ PegaFlow&lt;br&#x2F;&gt;本机 CPU&#x2F;SSD&lt;br&#x2F;&gt;─────────────&lt;br&#x2F;&gt;• 缓存历史 KV&lt;br&#x2F;&gt;• 多轮对话复用&quot;)]:::pegaStyle        D_PEGA &lt;--&gt;|&quot;KV Load&#x2F;Save&quot;| D_NODE    end    %% &#x3D;&#x3D;&#x3D;&#x3D;&#x3D; Router → 组件连线 &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;    ROUTER --&gt;|&quot;① Cache Hit&lt;br&#x2F;&gt;路由到有缓存的 Prefill&quot;| PH_NODE    ROUTER --&gt;|&quot;② Cache Miss&lt;br&#x2F;&gt;路由到任意 Prefill&quot;| PM_NODE    ROUTER --&gt;|&quot;③ 后续请求&lt;br&#x2F;&gt;Load-Aware 直发 Decode&quot;| D_NODE    %% &#x3D;&#x3D;&#x3D;&#x3D;&#x3D; Prefill → Decode 连线 (NIXL) &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;    PH_NODE &#x3D;&#x3D;&gt;|&quot;📡 NIXL 传输&lt;br&#x2F;&gt;Delta KV (仅增量)&quot;| D_NODE    PM_NODE &#x3D;&#x3D;&gt;|&quot;📡 NIXL 传输&lt;br&#x2F;&gt;Delta KV (仅增量)&quot;| D_NODE    %% &#x3D;&#x3D;&#x3D;&#x3D;&#x3D; Prefill 间 PegaFlow 跨节点 &#x3D;&#x3D;&#x3D;&#x3D;&#x3D;    PM_PEGA -.-&gt;|&quot;🔎 PegaFlow Master 查询&lt;br&#x2F;&gt;跨节点 Pull KV&quot;| PH_PEGA  </pre></div><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  sequenceDiagram    autonumber    participant C as 🖥️ Client    participant R as 🌐 Router    participant PM as ⚡ Prefill Node (Miss)    participant PM_P as 🗄️ PegaFlow (Prefill Miss)    participant PH as ⚡ Prefill Node (Hit)    participant PH_P as 🗄️ PegaFlow (Prefill Hit)    participant D as 🔄 Decode Node    participant D_P as 🗄️ PegaFlow (Decode)    rect rgb(159, 159, 191)        Note over C,D_P: 📍 第 1 轮 — 首次提问（Cache Miss，完整 Prefill）        C-&gt;&gt;R: 发送请求 (System Prompt + Q1)        R-&gt;&gt;R: 查询 session 映射 ❌ 无缓存        R-&gt;&gt;PM: Cache Miss 路由到任意 Prefill        PM-&gt;&gt;PM: 执行完整 Prefill (全量计算)        PM-&gt;&gt;PM_P: KV Save 全量写入 CPU&#x2F;SSD        PM-&gt;&gt;D: 📡 NIXL 全量 KV Cache (RDMA)        D-&gt;&gt;D_P: KV Save 缓存第1轮KV        loop 逐 Token 生成            D-&gt;&gt;D: Decode 生成 Token            D--&gt;&gt;C: Stream Token        end        R-&gt;&gt;R: 记录 session 到 PM 节点映射    end    rect rgb(109, 182, 133)        Note over C,D_P: 📍 第 2 轮 — 追问（Cache Hit，增量 Prefill）        C-&gt;&gt;R: 发送请求 (历史上下文 + Q2)        R-&gt;&gt;R: 查询 session 映射 ✅ 命中 PM 节点        R-&gt;&gt;PH: Cache Hit 路由到有缓存的 Prefill (PM变为PH角色)        PH_P-&gt;&gt;PH: KV Load 加载第1轮KV到GPU        PH-&gt;&gt;PH: 仅计算增量 Prefill (只处理Q2)        PH-&gt;&gt;PH_P: KV Save 更新完整KV        par NIXL增量传输 与 Decode本地加载 并行            PH-&gt;&gt;D: 📡 NIXL Delta KV (仅Q2增量)            D_P-&gt;&gt;D: KV Load 加载第1轮历史KV        end        D-&gt;&gt;D: 合并历史KV + Delta KV        D-&gt;&gt;D_P: KV Save 更新缓存        loop 逐 Token 生成            D-&gt;&gt;D: Decode 生成 Token            D--&gt;&gt;C: Stream Token        end    end    rect rgb(180, 100, 100)        Note over C,D_P: 📍 第 3 轮 — 异常场景：原节点过载，触发重路由        C-&gt;&gt;R: 发送请求 (历史上下文 + Q3)        R-&gt;&gt;R: ✅ 命中PH节点 但 ⚠️ 负载超阈值        R-&gt;&gt;PM: 重路由到新 Prefill 节点 (Cache Miss)        PM-&gt;&gt;PM_P: 本地查询KV ❌ 未命中        rect rgb(180, 100, 100)            Note over PM_P,PH_P: 🔎 PegaFlow 跨节点 Pull            PM_P-&gt;&gt;PM_P: 向 PegaFlow Master 查询谁有此前缀KV            PM_P--&gt;&gt;PH_P: Master返回 PH节点有缓存            PH_P-&gt;&gt;PM_P: 跨节点 Pull KV (RDMA) 传输第1到2轮完整KV        end        PM_P-&gt;&gt;PM: KV Load Pulled KV到GPU        PM-&gt;&gt;PM: 仅计算增量 Prefill (只处理Q3)        PM-&gt;&gt;PM_P: KV Save 完整KV        par NIXL增量传输 与 Decode本地加载 并行            PM-&gt;&gt;D: 📡 NIXL Delta KV (仅Q3增量)            D_P-&gt;&gt;D: KV Load 加载第1到2轮历史KV        end        D-&gt;&gt;D: 合并历史KV + Delta KV        D-&gt;&gt;D_P: KV Save 更新缓存        loop 逐 Token 生成            D-&gt;&gt;D: Decode 生成 Token            D--&gt;&gt;C: Stream Token        end        R-&gt;&gt;R: 更新 session 到 PM 节点映射    end  </pre></div>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;1-智能流量路由（smart-router）&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#1-智能流量路由（smart-router）&quot;&gt;¶&lt;/a&gt;1. 智能流量路由（Smart</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>写在2025最后一天</title>
    <link href="https://www.jmyjmy.top/2025-12-31_2025-endup/"/>
    <id>https://www.jmyjmy.top/2025-12-31_2025-endup/</id>
    <published>2025-12-31T15:39:54.000Z</published>
    <updated>2025-12-31T15:39:54.000Z</updated>
    
    <content type="html"><![CDATA[<p>真是非常充实的一年。</p><p>突然发现 DeepSeek 爆火也就是今年年初的事，感觉已经过去好久了。朋友圈刷屏，技术群里天天在聊。现在回头看，那只是一个起点。</p><h2 id="工作：从旁观者到实践者"><a class="header-anchor" href="#工作：从旁观者到实践者">¶</a>工作：从旁观者到实践者</h2><p>今年最大的变化是<strong>加入了一家 MaaS 公司</strong>。</p><p>之前做 LLM 相关的东西，更多是自己折腾，写写工具，跑跑实验。但进入真实业务场景完全是另一回事——直接面对客户需求、成本压力、SLO 约束，每一个决策都是真金白银。</p><p>说实话，真的很上头。总想着再优化一点点：延迟能不能再低？吞吐能不能再提？成本能不能再省？而且这不是单一目标的优化，是在<strong>成本 + 收入 + SLO</strong> 的多重限制下找平衡点。有时候为了省成本牺牲了一点延迟，有时候为了保 SLO 不得不多花钱。这种多目标博弈的感觉，比纯粹追求技术指标有意思多了。</p><p>这一年下来，对 LLM 落地的认知确实深了很多。以前觉得&quot;模型好就行&quot;，现在知道模型只是开始，后面还有一长串的工程问题要解决。</p><h2 id="技术深潜：模型服务的那些事"><a class="header-anchor" href="#技术深潜：模型服务的那些事">¶</a>技术深潜：模型服务的那些事</h2><p>想要做到模型服务高效运行，真的需要把计算机科学能用的都用上。大概可以分几层：</p><h3 id="网关层"><a class="header-anchor" href="#网关层">¶</a>网关层</h3><ul><li><strong>调度策略</strong>：怎么把请求分到合适的实例上，怎么做负载均衡，怎么处理突发流量</li><li><strong>异常处理</strong>：超时、重试、熔断、降级，每一个都有坑</li><li><strong>时延优化</strong>：每一跳都在加延迟，能省则省</li></ul><h3 id="推理服务层"><a class="header-anchor" href="#推理服务层">¶</a>推理服务层</h3><ul><li><strong>超参调优</strong>：batch size、chunk size、tile size，以后要在不同的卡上能快速 tune 一个符合要求的配置和 kernel</li><li><strong>部署模式</strong>：PD 分离、各种并行方式，不同场景用不同的组合</li></ul><h3 id="存储层（围绕-kv-cache）"><a class="header-anchor" href="#存储层（围绕-kv-cache）">¶</a>存储层（围绕 KV Cache）</h3><ul><li><strong>单机内存池化</strong>：在单机上做内存管理，减少重复计算</li><li><strong>集群 SSD 池化</strong>：把 SSD 资源池化，KV Cache 可以跨节点共享</li></ul><h2 id="ai-发展：震惊是常态"><a class="header-anchor" href="#ai-发展：震惊是常态">¶</a>AI 发展：震惊是常态</h2><p>今年参加了不少活动，前两天去了 WayToAGI 的线下，发现很多<strong>非技术背景的&quot;一人公司&quot;</strong>，已经用 AI 工具做出了非常好的产品，而且取得了不错的收益。他们不懂代码，不懂模型原理，但就是能把工具用好，把产品做出来，把钱赚到。视频生成现在简单到离谱——<strong>一句话或者一个简单的分镜</strong>，就能生成效果很好的视频。主要用的是 Google 的工具，还有 MiniMax。以前觉得视频生成还早，现在发现已经能用了。</p><p><strong>具身机器人</strong>也发展得超出预期。王力宏演唱会上机器人跳舞那个视频真的震惊到了。动作流畅度、协调性、稳定性，比我想象中好太多。</p><p>有一种感觉：明年把足够聪明的 LLM 塞到机器人身上，可能就快进到&quot;西部世界&quot;了。</p><h2 id="工具：效率提升的一年"><a class="header-anchor" href="#工具：效率提升的一年">¶</a>工具：效率提升的一年</h2><p>今年用上了公司的 <strong>Cursor</strong>，体验确实不错。倒是没怎么用 Claude Code，可能是使用场景不太对。说实话，对于我这种经常在<strong>推理框架里面 debug</strong> 的人来说，AI 编程工具的作用主要是省了我亲自打字。TAB 键已经按冒烟了。核心的思考、设计、排查问题，还是得自己来。但体力活确实省了不少。</p><p>另外要特别夸一下 <strong>Cherry Studio</strong>，真的好用。</p><h2 id="预测"><a class="header-anchor" href="#预测">¶</a>预测</h2><ul><li><p>现在的模型已经足够智能了（我已经不把 claude 模型当傻子了），但是聪明的模型还不普及，2026 年大家手里的 ai 平均智商应该能再提升一倍</p></li><li><p>sparse attention or linear attention？ 感觉 sparse 既难做快速的 kernel，kernel 代码也难迁移到其他模型。linear attention 似乎是快但是不聪明。</p></li><li><p>云原生继续发力，会有更多 LLM 相关各种 infra，包括网关，存储，网卡，显卡，模型冷启动。感觉现在还是没有出名&amp;功能强大&amp;大一统的框架，都是很初级的。</p></li><li><p>phone-use, computer-use 的各种 agent 放出各种 demo（特质豆包手机，GLM phone agent 这些），ai 可以端到端干更多的事了，但是还是受限于模型智力和 VL 模型效果。如果这些 agent 还是“小爱同学”的形式就没啥新鲜的。AI 是程序，手机电脑上的功能都是调 API，程序调用 API 多自然的流程，不应该有人类参与（任何模拟 vision, click, touch 的方法都算）。人只管输入就好了，具体实现应该是程序直接 call API 而不是用一个 VL 看屏幕，再模拟人点点点。移动互联网是把人们在线下 do something，变成了手机 APP 里面 do something。AI 手机应该去掉 APP，厂商提供一系列 API，人给 LLM 一个 task，LLM 去 tool call 就行了。</p></li><li><p>端侧LLM发展太难了，聪明的模型很大跑不动，跑的起来的模型太小不够聪明，老老实实call api吧</p></li></ul><h2 id="2026-想做的事"><a class="header-anchor" href="#2026-想做的事">¶</a>2026 想做的事</h2><ol><li><strong>继续深耕模型服务</strong>——KV Cache、调度策略、部署优化，还有很多可以挖的</li><li>去新疆</li><li>去川西</li><li>去新西兰</li></ol><h2 id="总结"><a class="header-anchor" href="#总结">¶</a>总结</h2><p>2025 年，从旁观者变成了实践者，在真实业务中摸爬滚打，对 LLM 落地有了更深的理解。AI 发展速度超出预期，这个时代太有意思了。</p><p>希望 2026 年，能做出更多有价值的事。</p><p><em>由 Opus 润色</em></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;真是非常充实的一年。&lt;/p&gt;
&lt;p&gt;突然发现 DeepSeek 爆火也就是今年年初的事，感觉已经过去好久了。朋友圈刷屏，技术群里天天在聊。现在回头看，那只是一个起点。&lt;/p&gt;
&lt;h2 id=&quot;工作：从旁观者到实践者&quot;&gt;&lt;a class=&quot;header-anchor&quot;</summary>
        
      
    
    
    
    <category term="Think" scheme="https://www.jmyjmy.top/categories/Think/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>AI是否有意识？</title>
    <link href="https://www.jmyjmy.top/2025-09-09_does-ai-has-consciousness/"/>
    <id>https://www.jmyjmy.top/2025-09-09_does-ai-has-consciousness/</id>
    <published>2025-09-09T15:51:26.000Z</published>
    <updated>2025-09-09T15:51:26.000Z</updated>
    
    <content type="html"><![CDATA[<p>一个人如何确定自己的身份？我认为关键在于记忆。如果一个人突然失去记忆，他将不知道自己是谁，不会吃饭，不会走路，不会说话，所有的行为都只能依靠神经反射。在这种情况下，这个失忆的人已经不再是原来的那个人了。</p><p>AI能够输出正确答案同样依赖于记忆。尽管AI本质上是通过大量数据拟合出的一个f(x)程序，但它确实实现了某种形式的记忆能力。超大规模的参数量提供了强大的记忆容量，使得大型语言模型（LLM）能够进行判断、推理，甚至控制复杂的操作。</p><p>那么，AI的记忆与人类的记忆究竟有何区别呢？人类的大脑又何尝不是一个&quot;生物程序&quot;？或许只是大脑本身拒绝承认这个事实罢了。</p><p>既然都是记忆体，AI和人类之间还有什么本质差异呢？</p><h3 id="多样化的输入模态"><a class="header-anchor" href="#多样化的输入模态">¶</a>多样化的输入模态</h3><p>与语言模型或多模态模型相比，人类的输入形式更加丰富：视觉、听觉、味觉、触觉、感觉。LLM的文本输入形式对人类而言，类似于大脑内部的自我思考过程（书本上的文字实际上是通过视觉输入的）。</p><h3 id="长期的记忆积累"><a class="header-anchor" href="#长期的记忆积累">¶</a>长期的记忆积累</h3><p>人类的记忆从有意识开始（排除大多数人不太记得的幼儿早期），大约从3岁起（我还记得自己3岁第一次去幼儿园的场景，但这似乎是3岁时唯一的清晰记忆，其他幼儿时期的记忆锚点多属于4岁）。人类拥有长达数十年的持续输入，这些数据量虽然在文字方面可能不如LLM训练的数据多，但各种模态加起来的总量也相当可观。</p><h3 id="人际关系的交互输入"><a class="header-anchor" href="#人际关系的交互输入">¶</a>人际关系的交互输入</h3><p>一个人的&quot;训练数据&quot;还包括与他人互动的过程。每个人从小在不同的环境中成长，与不同的人接触，使用不同的&quot;训练数据&quot;，最终形成了独一无二的个体。</p><p>从这个角度来看，实现通用人工智能（AGI）似乎很简单：只需继续增加输入模态，比如为机器人添加视觉、听觉、触觉等能力。但实际情况可能并不那么简单：各种模态的训练数据获取难度不同。文字和图片可以从网站上爬取，但听觉、触觉、感觉以及实体间交互等形式的可用数据相比之下要稀少得多。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;一个人如何确定自己的身份？我认为关键在于记忆。如果一个人突然失去记忆，他将不知道自己是谁，不会吃饭，不会走路，不会说话，所有的行为都只能依靠神经反射。在这种情况下，这个失忆的人已经不再是原来的那个人了。&lt;/p&gt;
&lt;p&gt;AI能够输出正确答案同样依赖于记忆。尽管AI本质上是通过</summary>
        
      
    
    
    
    <category term="Think" scheme="https://www.jmyjmy.top/categories/Think/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>推测解码(Speculative decoding)</title>
    <link href="https://www.jmyjmy.top/2025-09-07_speculative-decoding/"/>
    <id>https://www.jmyjmy.top/2025-09-07_speculative-decoding/</id>
    <published>2025-09-07T11:44:30.000Z</published>
    <updated>2025-09-07T11:44:30.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="什么是推测解码？"><a class="header-anchor" href="#什么是推测解码？">¶</a>什么是推测解码？</h2><p>推测解码（Speculative Decoding）是一种用于加速大型语言模型（LLM）推理的创新技术。它通过使用一个较小的&quot;草稿模型&quot;来预测下一个 token，然后用更大的&quot;目标模型&quot;来验证这些预测，从而显著减少推理时间。</p><h2 id="技术原理"><a class="header-anchor" href="#技术原理">¶</a>技术原理</h2><h3 id="基本思想"><a class="header-anchor" href="#基本思想">¶</a>基本思想</h3><p>推测解码的核心思想是：</p><ol><li>使用一个小而快的草稿模型（draft model）来生成多个候选 token</li><li>使用大而准确的目标模型（target model）来并行验证这些候选 token</li><li>接受所有被验证正确的 token，拒绝第一个错误的 token 并重新采样</li></ol><h2 id="实现细节"><a class="header-anchor" href="#实现细节">¶</a>实现细节</h2><h3 id="详细工作流程"><a class="header-anchor" href="#详细工作流程">¶</a>详细工作流程</h3><p>推测解码的具体工作流程如下：</p><ol><li><strong>初始预测</strong>：目标模型（LLM）预测第一个 token</li><li><strong>草稿生成</strong>：草稿模型基于当前上下文生成多个候选 token（通常 3-5 个）</li><li><strong>并行验证</strong>：目标模型并行验证所有草稿模型生成的候选 token</li><li><strong>比较接受</strong>：逐个比较目标模型和草稿模型的输出：<ul><li>如果相同：接受该 token，继续比较下一个</li><li>如果不同：停止接受，进入下一轮预测</li></ul></li><li><strong>下一轮循环</strong>：从未被接受的 token 位置开始新的预测循环<br><img src="/img/normaldecode.webp" alt="自回归的LLM生成"><br><img src="/img/specdecode.webp" alt="Speculative decoding"></li></ol><h3 id="伪代码示例"><a class="header-anchor" href="#伪代码示例">¶</a>伪代码示例</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">speculative_decoding</span>(<span class="params">prompt, draft_model, target_model, max_tokens, k=<span class="number">5</span></span>):</span><br><span class="line">    generated = []</span><br><span class="line"></span><br><span class="line">    <span class="keyword">while</span> <span class="built_in">len</span>(generated) &lt; max_tokens:</span><br><span class="line">        <span class="comment"># 目标模型预测第一个token（如果需要）</span></span><br><span class="line">        <span class="keyword">if</span> <span class="keyword">not</span> generated:</span><br><span class="line">            next_token = target_model.sample(prompt)</span><br><span class="line">            generated.append(next_token)</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line"></span><br><span class="line">        <span class="comment"># 草稿模型生成k个候选token</span></span><br><span class="line">        current_context = prompt + generated</span><br><span class="line">        draft_tokens = draft_model.generate(current_context, num_tokens=k)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 目标模型并行验证所有候选token</span></span><br><span class="line">        target_probs = []</span><br><span class="line">        <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(draft_tokens)):</span><br><span class="line">            verify_context = current_context + draft_tokens[:i]</span><br><span class="line">            next_token_probs = target_model.predict_next_token(verify_context)</span><br><span class="line">            target_probs.append(next_token_probs)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 逐个比较并接受token</span></span><br><span class="line">        accepted_tokens = []</span><br><span class="line">        <span class="keyword">for</span> i, draft_token <span class="keyword">in</span> <span class="built_in">enumerate</span>(draft_tokens):</span><br><span class="line">            target_prob = target_probs[i][draft_token]</span><br><span class="line">            draft_prob = draft_model.get_probability(draft_token, current_context + draft_tokens[:i])</span><br><span class="line"></span><br><span class="line">            accept_prob = <span class="built_in">min</span>(<span class="number">1</span>, target_prob / draft_prob) <span class="keyword">if</span> draft_prob &gt; <span class="number">0</span> <span class="keyword">else</span> <span class="number">0</span></span><br><span class="line"></span><br><span class="line">            <span class="keyword">if</span> random.random() &lt; accept_prob:</span><br><span class="line">                accepted_tokens.append(draft_token)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                <span class="keyword">break</span>  <span class="comment"># 第一个不匹配就停止</span></span><br><span class="line"></span><br><span class="line">        generated.extend(accepted_tokens)</span><br><span class="line"></span><br><span class="line">        <span class="comment"># 如果全部接受，继续下一轮；否则从目标模型重新采样</span></span><br><span class="line">        <span class="keyword">if</span> <span class="built_in">len</span>(accepted_tokens) == k:</span><br><span class="line">            <span class="keyword">continue</span></span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            resample_context = current_context + accepted_tokens <span class="keyword">if</span> accepted_tokens <span class="keyword">else</span> current_context</span><br><span class="line">            next_token = target_model.sample(resample_context)</span><br><span class="line">            generated.append(next_token)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">return</span> generated</span><br></pre></td></tr></table></figure><h3 id="模型选择"><a class="header-anchor" href="#模型选择">¶</a>模型选择</h3><ul><li><strong>草稿模型</strong>：通常选择参数量较小、推理速度快的模型</li><li><strong>目标模型</strong>：需要高精度的大模型，负责最终的质量保证</li></ul><h3 id="并行验证"><a class="header-anchor" href="#并行验证">¶</a>并行验证</h3><p>推测解码的关键优势在于能够并行验证多个候选 token。</p><h2 id="性能优势"><a class="header-anchor" href="#性能优势">¶</a>性能优势</h2><h3 id="加速比"><a class="header-anchor" href="#加速比">¶</a>加速比</h3><p>推测解码通常能达到 <strong>2-3 倍</strong> 的加速比，具体取决于：</p><ol><li><strong>草稿模型的质量</strong>：草稿模型越准确，接受率越高</li><li><strong>候选长度</strong>：合适的候选序列长度平衡了并行性和准确性</li><li><strong>模型大小差异</strong>：目标模型和草稿模型的参数量比例</li></ol><p>考虑到推测解码代码逻辑独立于模型前向，引入额外开销使得整体加速效果只有 0.3-0.5 倍</p><h3 id="硬件要求"><a class="header-anchor" href="#硬件要求">¶</a>硬件要求</h3><p>推测解码对硬件的要求相对灵活：</p><ul><li>GPU 内存：需要同时加载两个模型，需要显存更大</li><li>计算资源：草稿模型的计算开销较小，但并行 verify 计算开销倍增</li><li>通信开销：模型间需要高效的数据传输</li></ul><h2 id="挑战与限制"><a class="header-anchor" href="#挑战与限制">¶</a>挑战与限制</h2><h3 id="技术挑战"><a class="header-anchor" href="#技术挑战">¶</a>技术挑战</h3><ol><li><strong>模型一致性</strong>：草稿模型和目标模型需要保持输出分布的一致性</li><li><strong>候选长度选择</strong>：过长的候选序列可能降低接受率</li><li><strong>错误传播</strong>：错误的预测会影响后续生成质量</li></ol><h3 id="适用场景"><a class="header-anchor" href="#适用场景">¶</a>适用场景</h3><p>推测解码最适合：</p><ul><li>批量推理任务</li><li>对延迟敏感的应用</li><li>资源受限的环境</li></ul><p>不太适合：</p><ul><li>需要极高准确性的关键任务</li><li>非常短的文本生成</li></ul>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;什么是推测解码？&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#什么是推测解码？&quot;&gt;¶&lt;/a&gt;什么是推测解码？&lt;/h2&gt;
&lt;p&gt;推测解码（Speculative</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>sglang 中的多进程 Tokenizer 优化实践</title>
    <link href="https://www.jmyjmy.top/2025-09-02_sglang-multi-process-tokenizer/"/>
    <id>https://www.jmyjmy.top/2025-09-02_sglang-multi-process-tokenizer/</id>
    <published>2025-09-02T06:54:28.000Z</published>
    <updated>2025-09-02T06:54:28.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="概述"><a class="header-anchor" href="#概述">¶</a>概述</h2><p>本文记录了在 sglang 项目中针对多 GPU 环境下 Tokenizer 性能瓶颈的分析与优化过程。通过实现多进程 Tokenizer 架构，成功解决了大规模推理场景下的性能瓶颈问题。</p><p>相关 PR:</p><ul><li><a href="https://github.com/sgl-project/sglang/pull/6555">#6555</a></li><li><a href="https://github.com/sgl-project/sglang/pull/8964">#8964</a></li></ul><h2 id="问题发现与定位"><a class="header-anchor" href="#问题发现与定位">¶</a>问题发现与定位</h2><p>在 9 台服务器、72 张 H100 GPU 的集群上运行 DeepSeek 模型进行解码性能测试时，发现了一个显著的性能差异：</p><ul><li><strong>服务端日志显示</strong>：单卡吞吐量达到 2000 tokens/秒 (TPS)</li><li><strong>客户端测试结果</strong>：无论是 TTFT（Time To First Token）、TPOT（Time Per Output Token），还是整体吞吐量，都远低于预期值</li></ul><h3 id="初步分析"><a class="header-anchor" href="#初步分析">¶</a>初步分析</h3><p>经过初步排查，问题可能出现在以下几个方面：</p><ol><li><strong>HTTP 服务器瓶颈</strong>：使用 FastAPI 作为 HTTP 服务器，在处理大量输入数据时可能成为性能瓶颈，即使切换到 Sanic 等其他框架也无法完全解决</li><li><strong>测试脚本限制</strong>：Python 测试脚本需要同时处理请求发送、流式接收、计时统计等多个任务，可能引入额外开销</li></ol><h3 id="深入调查"><a class="header-anchor" href="#深入调查">¶</a>深入调查</h3><p>通过代码分析发现核心问题：<strong>单进程的http server, tokenizer, detokenizer 成为系统瓶颈</strong></p><p>计算分析：</p><ul><li>总吞吐量：<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2000</mn><mtext> TPS</mtext><mo>×</mo><mn>72</mn><mtext> GPU</mtext><mo>=</mo><mn>144</mn><mo separator="true">,</mo><mn>000</mn><mtext> tokens/秒</mtext></mrow><annotation encoding="application/x-tex">2000 \text{ TPS} \times 72 \text{ GPU} = 144,000 \text{ tokens/秒}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord">2000</span><span class="mord text"><span class="mord"> TPS</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord">72</span><span class="mord text"><span class="mord"> GPU</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">144</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">000</span><span class="mord text"><span class="mord"> tokens/</span><span class="mord cjk_fallback">秒</span></span></span></span></span></li><li>Detokenizer 处理时间：50~100 us/Token</li><li>理论需求：要在 1 秒内处理 144,000 个 Token，Detokenizer 需要在 7us内完成每个 Token 的处理</li></ul><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  graph TDsubgraph 客户端Client[Client]end    subgraph Web服务器        HttpServer[HTTP Server]        Tokenizer[Tokenizer]        HttpServer -- 函数调用 --&gt; Tokenizer    end    subgraph GPU集群        subgraph GPU1            Scheduler1[Scheduler]            Worker1[Worker]            Scheduler1 --&gt; Worker1        end        subgraph GPU2            Scheduler2[Scheduler]            Worker2[Worker]            Scheduler2 --&gt; Worker2        end        subgraph GPU3            Scheduler3[Scheduler]            Worker3[Worker]            Scheduler3 --&gt; Worker3        end        subgraph GPU4            Scheduler4[Scheduler]            Worker4[Worker]            Scheduler4 --&gt; Worker4        end    end    subgraph 结果处理        Detokenizer[Detokenizer]    end    Client --&gt;|HTTP请求| HttpServer    Tokenizer --&gt;|ZMQ请求| Scheduler1    Tokenizer --&gt;|ZMQ请求| Scheduler2    Tokenizer --&gt;|ZMQ请求| Scheduler3    Tokenizer --&gt;|ZMQ请求| Scheduler4    Worker1 --&gt;|ZMQ结果| Detokenizer    Worker2 --&gt;|ZMQ结果| Detokenizer    Worker3 --&gt;|ZMQ结果| Detokenizer    Worker4 --&gt;|ZMQ结果| Detokenizer    Detokenizer --&gt;|ZMQ返回| Tokenizer    HttpServer --&gt;|HTTP响应| Client    style Detokenizer stroke:#f66,stroke-width:2px  </pre></div><h2 id="架构分析与解决方案"><a class="header-anchor" href="#架构分析与解决方案">¶</a>架构分析与解决方案</h2><p>从系统架构图可以清晰地看到问题所在：<strong>Detokenizer 成为了单点瓶颈</strong>。多个 GPU Worker 同时向单个 Detokenizer 发送处理结果，形成了&quot;多对一&quot;的通信模式。</p><h3 id="解决方案"><a class="header-anchor" href="#解决方案">¶</a>解决方案</h3><p>基于架构分析，制定了以下优化策略：</p><ol><li><strong>Detokenizer 多进程化</strong>：将单进程 Detokenizer 改造为多进程架构，实现并行处理</li><li><strong>测试脚本多进程优化</strong>：改造测试脚本，支持多进程并发处理</li></ol><h2 id="sglang-pr-实现方案"><a class="header-anchor" href="#sglang-pr-实现方案">¶</a>sglang PR 实现方案</h2><p><img src="/img/449106759-462f9ae6-3371-41fd-800b-b8f790951be6.webp" alt=""></p><h3 id="核心设计原则"><a class="header-anchor" href="#核心设计原则">¶</a>核心设计原则</h3><p><strong>全面多进程化</strong>：系统中任何可能出现&quot;多对一&quot;通信模式的地方都需要进行多进程改造，避免单点瓶颈。</p><h3 id="技术实现细节"><a class="header-anchor" href="#技术实现细节">¶</a>技术实现细节</h3><ol><li><strong>单机多进程通信</strong>：使用共享内存（SHM）进行高效进程间通信</li><li><strong>请求路由管理</strong>：通过 <code>MultiTokenizerRegisterReq</code> 机制维护请求标识符（RID）的路由信息，确保每个请求从哪个 Tokenizer 进入就从对应的路径返回</li><li><strong>负载均衡</strong>：实现智能的请求分发机制，确保各个 Detokenizer 进程负载均衡</li></ol><h3 id="性能提升效果"><a class="header-anchor" href="#性能提升效果">¶</a>性能提升效果</h3><p>经过多进程改造后，系统能够：</p><ul><li>线性扩展 Detokenizer 处理能力</li><li>消除单点性能瓶颈</li><li>支持更大规模的 GPU 集群部署</li><li>显著提升整体系统吞吐量</li></ul>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;概述&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#概述&quot;&gt;¶&lt;/a&gt;概述&lt;/h2&gt;
&lt;p&gt;本文记录了在 sglang 项目中针对多 GPU 环境下 Tokenizer 性能瓶颈的分析与优化过程。通过实现多进程 Tokenizer</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>记Mooncake传输异常慢的问题</title>
    <link href="https://www.jmyjmy.top/2025-08-07_mooncake-transfer-slow/"/>
    <id>https://www.jmyjmy.top/2025-08-07_mooncake-transfer-slow/</id>
    <published>2025-08-07T17:25:00.000Z</published>
    <updated>2025-08-07T17:25:00.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="背景"><a class="header-anchor" href="#背景">¶</a>背景</h2><p>sglang跑Deepseek PD分离，使用mooncake做kv transfer</p><h2 id="现象"><a class="header-anchor" href="#现象">¶</a>现象</h2><p>服务启动后跑个10min都很正常，ttft，tpot都很低，很开心。但是跑了几分钟以后ttft开始增加，mooncake日志里传输速率下降到&lt;100MB/s。</p><p>传输慢，P节点的日志里就会看到transferring=10…20…30…越来越多。没传完的请求还占着kv cache的空间，导致新的请求也没法跑，后面的请求都堆积在<code>waiting_queue</code>里面，每次只能运行1个请求。token-usage 0.99。TTFT直线上升。。。。</p><h2 id="猜测：计算用ib网络，传kv-也用ib-网络，这两个互相干扰？ib带宽满了？"><a class="header-anchor" href="#猜测：计算用ib网络，传kv-也用ib-网络，这两个互相干扰？ib带宽满了？">¶</a>猜测：计算用ib网络，传kv 也用ib 网络，这两个互相干扰？ib带宽满了？</h2><p>看PCIE带宽，只占了500MB/s，远远不到IB网络的400Gbps。</p><p>把overlap-schedule关掉，先算，算完就把这批请求都传走，让scheduler sleep等到都传完了再跑下一个batch总可以吧</p><p>并不，传的还是很慢。</p><h2 id="猜测：传输任务提交的慢？"><a class="header-anchor" href="#猜测：传输任务提交的慢？">¶</a>猜测：传输任务提交的慢？</h2><p>scheduler 跑完以后是调了mooncake 的transfer_sync，这个sync并不是等传完，而是类似提交任务，python这边很快就释放出来了不会hang在这里。mooncake 里面也释放了GIL了。提交任务是用一个多线程提交的，那我增加这个线程池呢？我从4改成64</p><p>有点用，传的是快了，仅限前面10分钟，可能原来传500MB/s 的可以变成 700MB/s，但是这10分钟后还是速度掉回几十MB</p><h2 id="猜测：传输的内存不连续，带宽利用率低"><a class="header-anchor" href="#猜测：传输的内存不连续，带宽利用率低">¶</a>猜测：传输的内存不连续，带宽利用率低</h2><p>在每次传的时候都打出来块的大小，发现前面的num-block都是1，2这样，很少，传的很快，但是10分钟后就变成1000+了。这么多碎片内存当然慢了。</p><h2 id="分析：这么多碎片哪里来的呢？"><a class="header-anchor" href="#分析：这么多碎片哪里来的呢？">¶</a>分析：这么多碎片哪里来的呢？</h2><p>前面调试写的sleep还没删，P节点每次都是等传完老的再跑新的，我的kvcache干干净净啊。凭啥搞几千个block出来啊。</p><p>看看<code>TokenToKVPoolAllocator</code>代码</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">def</span> <span class="title function_">alloc</span>(<span class="params">self, need_size: <span class="built_in">int</span></span>):</span><br><span class="line">    <span class="keyword">if</span> need_size &gt; <span class="built_in">len</span>(self.free_pages):</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">None</span></span><br><span class="line">    select_index = self.free_pages[:need_size]</span><br><span class="line">    self.free_pages = self.free_pages[need_size:]</span><br><span class="line">    <span class="keyword">return</span> select_index</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">free</span>(<span class="params">self, free_index: torch.Tensor</span>):</span><br><span class="line">    <span class="keyword">if</span> free_index.numel() == <span class="number">0</span>:</span><br><span class="line">        <span class="keyword">return</span></span><br><span class="line">    self.free_pages = torch.cat((self.free_pages, free_index))</span><br></pre></td></tr></table></figure><p>Alloc 直接从free队列里拿 size 个<br>Free的时候直接加到后面<br>这显然是有问题的<br><img src="/img/pool_frag.webp" alt="mem pool frag"><br>只要循环多次，pool的内存排序会收敛于一种完全shuffle的状态。每次申请的block 都是极其不连续的，在page size 1 的情况下会大概率出现  1000个token 在 1000个不连续的block上。这样对于KV传输非常不友好。传输速率只有50~250MB/s</p><p>那我free后把free_pages 从小到大排个序不就好了，下次拿都是连续的。</p><p><strong>P节点确实都连续了，但是KV transfer的时候P和D的block数是一样的，P连续的但是D不连续啊，就算P 的pool每次都是新的，但D那边还有没跑完的请求没法释放没法弄出来很多连续的block</strong></p><h2 id="解决"><a class="header-anchor" href="#解决">¶</a>解决</h2><p>简单点，直接<code>page-size=128</code></p><p>使用<code>PagedTokenToKVPoolAllocator</code> ，根据实际数据分布设置合适的page size，让大多数请求只需要几个page，这样大大提升请求token的block连续性。 设置page size =128 的情况下，对于4000 以下的真实输入场景，每次KV传输时间&lt;0.2s，Mooncake传输速率保持1500MB/s</p><h2 id="后续"><a class="header-anchor" href="#后续">¶</a>后续</h2><p>transfer很快，但是跑半个小时decode又挂了。查不出问题，只是看到从开始跑linux kernel的内核态内存就一直增长，涨半个小时到阈值不给申请了。然后mooncake里面调syscall <code>ibv_create_qp</code>的时候linux kernel直接返回<code>12 cannot allocate memory</code></p><p>查了一圈找到了一个issue<a href="https://github.com/kvcache-ai/Mooncake/issues/691">Mooncake Issue 691</a></p><p>用0.3.5 加个<code>MC_ENABLE_DEST_DEVICE_AFFINITY=1</code> 确实qp就不涨了。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;背景&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#背景&quot;&gt;¶&lt;/a&gt;背景&lt;/h2&gt;
&lt;p&gt;sglang跑Deepseek PD分离，使用mooncake做kv transfer&lt;/p&gt;
&lt;h2 id=&quot;现象&quot;&gt;&lt;a</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>Sglang PD分离中的Mooncake</title>
    <link href="https://www.jmyjmy.top/2025-06-22_Sglang-Mooncake/"/>
    <id>https://www.jmyjmy.top/2025-06-22_Sglang-Mooncake/</id>
    <published>2025-06-22T09:09:36.000Z</published>
    <updated>2025-06-22T09:09:36.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="架构概述"><a class="header-anchor" href="#架构概述">¶</a>架构概述</h2><p>Sglang采用的Prefill-Decode（PD）分离架构是现代大语言模型推理的重要优化方案。该架构将传统的单体推理过程拆分为两个独立的阶段：</p><ul><li><strong>Prefill阶段</strong>：负责处理输入提示词，生成初始的Key-Value（KV）Cache</li><li><strong>Decode阶段</strong>：基于KV Cache进行自回归的token生成</li></ul><p>Mooncake作为核心协调组件，实现了这两个物理分离实例的高效连接和协同工作。</p><h2 id="工作流程详解"><a class="header-anchor" href="#工作流程详解">¶</a>工作流程详解</h2><h3 id="初始化与资源准备"><a class="header-anchor" href="#初始化与资源准备">¶</a>初始化与资源准备</h3><p>当请求到达时，Decode节点首先通过<code>prealloc</code>组件预先为KV Cache分配内存空间。这种预先分配的策略确保了后续数据传输的高效性，避免了运行时内存分配的开销。</p><h3 id="bootstrap协调机制"><a class="header-anchor" href="#bootstrap协调机制">¶</a>Bootstrap协调机制</h3><p>Decode节点的<code>receiver</code>通过Mooncake向Prefill节点发送bootstrap信号，触发Prefill处理流程。这种设计使得Decode节点能够主动协调Prefill工作，实现精准的流水线控制。</p><h2 id="架构设计解析"><a class="header-anchor" href="#架构设计解析">¶</a>架构设计解析</h2><h3 id="prefill节点组件"><a class="header-anchor" href="#prefill节点组件">¶</a>Prefill节点组件</h3><ul><li><strong>Bootstrap Server (Mooncake)</strong>：核心协调组件，管理节点注册和连接</li><li><strong>KV Manager</strong>：负责KV Cache的生命周期管理</li><li><strong>KV Sender</strong>：优化数据传输，支持分块和流式传输</li><li><strong>Scheduler</strong>：任务调度和资源分配</li></ul><h3 id="decode节点组件"><a class="header-anchor" href="#decode节点组件">¶</a>Decode节点组件</h3><ul><li><strong>KV Receiver</strong>：高效接收和处理传入的KV Cache</li><li><strong>KV Manager</strong>：管理接收到的缓存数据</li><li><strong>Scheduler</strong>：解码调度和token生成控制</li></ul><h2 id="技术优势与价值"><a class="header-anchor" href="#技术优势与价值">¶</a>技术优势与价值</h2><h3 id="性能提升"><a class="header-anchor" href="#性能提升">¶</a>性能提升</h3><ul><li><strong>降低TTFT</strong>：通过并行处理和流水线优化显著减少首token延迟</li><li><strong>提高吞吐量</strong>：Prefill和Decode分离允许独立扩展和优化</li><li><strong>资源利用率</strong>：专业化组件设计最大化硬件利用效率</li></ul><h3 id="架构灵活性"><a class="header-anchor" href="#架构灵活性">¶</a>架构灵活性</h3><ul><li><strong>独立扩展</strong>：Prefill和Decode可根据负载独立扩容</li><li><strong>故障隔离</strong>：单点故障不影响整个系统运行</li><li><strong>混合部署</strong>：支持不同硬件配置的节点混合部署</li></ul><h3 id="运维优势"><a class="header-anchor" href="#运维优势">¶</a>运维优势</h3><ul><li><strong>服务发现</strong>：自动化节点管理和连接建立</li><li><strong>负载均衡</strong>：智能请求分配和资源调度</li><li><strong>监控诊断</strong>：完善的监控指标和诊断能力</li></ul><p>这种基于Mooncake的PD分离架构为大语言模型服务提供了可扩展、高性能、高可用的基础设施解决方案，代表了现代AI推理架构的重要发展方向。</p><p><img src="/img/pd-disaggregation.webp" alt="Sglang 官方图片"></p><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  sequenceDiagram    autonumber    box Prefill    participant forward_A    participant forward_B    participant CPULoop    participant waiting_queue_p as waiting_queue    participant sender    end    box Decode    participant reciever    participant transfer_queue    participant prealloc    participant waiting_queue_d as waiting_queue    participant scheduler    end    Note over forward_A,scheduler: requests arrived,TTFT start    activate scheduler    activate scheduler    activate scheduler        loop        prealloc-&gt;&gt;prealloc: alloc for KV cache    end    prealloc-&gt;&gt;transfer_queue: pop_prealloc        activate transfer_queue    activate transfer_queue    activate transfer_queue    Note over transfer_queue,reciever: init reciever    activate reciever    activate reciever    activate reciever    reciever-&gt;&gt;waiting_queue_p: bootstrap prealloc    waiting_queue_p-&gt;&gt;CPULoop: new-seqs    CPULoop-&gt;&gt;+forward_A: batch 0 start    waiting_queue_p-&gt;&gt;CPULoop: new-seqs    CPULoop-&gt;&gt;+forward_B: batch 1 start    forward_A-&gt;&gt;-CPULoop: batch 0 sync    CPULoop-&gt;&gt;+sender: trans batch 0    loop Every chunk        sender-&gt;&gt;reciever: send chunk    end        sender-&gt;&gt;reciever: last chunk send aux    sender-&gt;&gt;-CPULoop: trans batch 0 finish    reciever-&gt;&gt;-transfer_queue: start decode    transfer_queue-&gt;&gt;-waiting_queue_d: pop_transfer    Note right of scheduler: TTFT for req 0    waiting_queue_d-&gt;&gt;scheduler: first token    deactivate scheduler    waiting_queue_p-&gt;&gt;CPULoop: new-seqs    CPULoop-&gt;&gt;+forward_A: batch 2 start    forward_B-&gt;&gt;-CPULoop: batch 1 sync    CPULoop-&gt;&gt;+sender: trans batch 1    loop Every chunk        sender-&gt;&gt;reciever: send chunk    end    sender-&gt;&gt;reciever: last chunk send aux        sender-&gt;&gt;-CPULoop: trans batch 1 finish    reciever-&gt;&gt;-transfer_queue: start decode    transfer_queue-&gt;&gt;-waiting_queue_d: pop_transfer    Note right of scheduler: TTFT for req 1    waiting_queue_d-&gt;&gt;scheduler: first token    deactivate scheduler        forward_A-&gt;&gt;-CPULoop: batch 2 sync    CPULoop-&gt;&gt;+sender: trans batch 2    loop Every chunk        sender-&gt;&gt;reciever: send chunk    end    sender-&gt;&gt;reciever: last chunk send aux    sender-&gt;&gt;-CPULoop: trans batch 0 finish    reciever-&gt;&gt;-transfer_queue: start decode    transfer_queue-&gt;&gt;-waiting_queue_d: pop_transfer    Note right of scheduler: TTFT for req 2    waiting_queue_d-&gt;&gt;scheduler: first token    deactivate scheduler  </pre></div><p><em>图1：PD分离架构交互序列图 - 展示了Mooncake协调下Prefill和Decode节点的完整工作流程，包括资源预分配、bootstrap协调、并行处理、分块传输和解码启动等关键阶段</em></p><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  graph    subgraph Prefill_Node [Prefill Node]        BS[Bootstrap Server]        subgraph GPU_P1 [GPU 1]            subgraph SP1 [Scheduler]                KVM_P1[KV Manager]                KVS_P1[KV Sender]            end        end        subgraph GPU_P2 [GPU 2]            subgraph SP2 [Scheduler]                KVM_P2[KV Manager]                KVS_P2[KV Sender]            end        end    end    subgraph Decode_Node [Decode Node]        subgraph GPU_D1 [GPU 1]            subgraph SD1 [Scheduler]                KVM_D1[KV Manager]                KVR_D1[KV Receiver]            end        end        subgraph GPU_D2 [GPU 2]            subgraph SD2 [Scheduler]                KVM_D2[KV Manager]                KVR_D2[KV Receiver]            end        end    end    KVM_P1 --&gt;|register| BS    KVM_P2 --&gt;|register| BS    KVR_D1 ---&gt;|bootstrap, 发送receiver信息| BS    KVR_D2 ---&gt;|bootstrap, 发送receiver信息| BS    KVS_P1 --&gt;|发送KV| KVR_D1    KVS_P2 --&gt;|发送KV| KVR_D2  </pre></div><p><em>图2：Mooncake连接架构图 - 展示了星型拓扑结构中Mooncake作为中心枢纽，协调Prefill和Decode节点之间的服务注册、bootstrap连接和直接数据传输</em></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;架构概述&quot;&gt;&lt;a class=&quot;header-anchor&quot;</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>ML system知识全景图</title>
    <link href="https://www.jmyjmy.top/2025-06-19_ai-infra-essential-knowledge-areas/"/>
    <id>https://www.jmyjmy.top/2025-06-19_ai-infra-essential-knowledge-areas/</id>
    <published>2025-06-19T08:41:54.000Z</published>
    <updated>2025-06-19T08:41:54.000Z</updated>
    
    <content type="html"><![CDATA[<p>算法工程师，首先是工程师。</p><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  mindmap    root)ML sys(        (理论)            (操作系统)            (计算机体系结构)            (计算机网络)            (算法导论)            (线代)            (概率论)            (机器学习)            (炼丹经验)        (工程实践)            (编程基础)            (开发框架)            (软件工程)            (开发工具链)  </pre></div><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  mindmap    (理论)        (操作系统)        (计算机体系结构)        (计算机网络)        (算法导论)        (线代)        (概率论)        (机器学习)            (深度学习)                (Network)                    (Conv)                    (Resnet)                    (RNN)                    (LSTM)                    (Transformer)                (Task)                    (Diffusion)                    (LLM)                    (Multimodal)        (炼丹)            (调参)                (Loss Fn)                (Opt)                (Lr)                (Reg)            (模型优化)                (Training)                    (Arch Optimization)                    (Distillation)                    (Pruning)                    (Quantization)                (Inference)                    (Graph Optimization)                    (Operator Fusion)            (数据处理)                ))**业务理解**((                (数据增广)                (数据标注)  </pre></div><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  mindmap    (工程实践)        (编程基础)            (数据结构与算法)            (系统设计原理)            (编程语言)        (开发框架)        (软件工程)            (需求与设计)            (开发流程)            (质量保证)        (开发工具链)            (Build&amp;Deploy)                (Jenkins)                (Gitlab CI)                (Docker)                (Docker Compose)                (K8s)            (Monitor&amp;Trace)                (Promethus)                (Grafana)                (ELK)                (Fluentd)                (Jaeger)  </pre></div><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  mindmap    (开发框架)        (AI)            (Train)                (pytorch)            (Inference)                (tensorrt)                (onnxruntime)                (TVM)            (LLM)                (sglang)                (VLLM)                (TRTLLM)                (Nvidia Triton server)                (ollama)        (并行计算)            (MPI)            (Ray)            (OpenMP)            (CUDA)            (Openai Triton)            (OpenCL)        (Web)            (Python)                (Fastapi)                (Django)            (Golang)                (Gin)            (Nodejs)        (DB)            (MySQL)            (SQLite)            (PG)            (Mongo)            (Redis)        (中间件)            (zmq)            (kafka)  </pre></div>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;算法工程师，首先是工程师。&lt;/p&gt;
&lt;div class=&quot;mermaid-wrap&quot;&gt;&lt;pre class=&quot;mermaid-src&quot; hidden&gt;
  mindmap
    root)ML sys(
        (理论)
            (操作系统)
</summary>
        
      
    
    
    
    <category term="Think" scheme="https://www.jmyjmy.top/categories/Think/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>IB网络检查</title>
    <link href="https://www.jmyjmy.top/2025-06-13_IB-network-inspect/"/>
    <id>https://www.jmyjmy.top/2025-06-13_IB-network-inspect/</id>
    <published>2025-06-13T04:37:43.000Z</published>
    <updated>2025-06-13T04:37:43.000Z</updated>
    
    <content type="html"><![CDATA[<p>最近发现 H100 集群 IB 网络通信有问题。跑 DeepEP，MoonCake 都会有通信报错。nccl init 也很慢。</p><p>正常跑 ibsend 啥的都没问题。</p><p>命令：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">lspci -d 15b3::0207 -n | awk &#x27;&#123;print $1&#125;&#x27; | xargs -I&#123;&#125; sh -c &#x27;echo &#123;&#125; &amp;&amp; mlxlink -d &#123;&#125; -c | grep -e Effective -e Raw&#x27; |tee /tmp/mlxlink_$(date +%Y-%m-%d_%H-%M-%S).log</span><br></pre></td></tr></table></figure><p><code>lspci -d 15b3::0207 -n</code> 查找 IB 网卡。<code>15b3::0207</code>是产品 ID</p><p>mlxlink -d device -c 列出 Error 以及 BER(Bit Error Rate 误码率)</p><p>此命令输出到终端，并且写入文件/tmp/mlxlink_xxx.log</p><p>mlxlink 输出结果样例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">Operational Info</span><br><span class="line">----------------</span><br><span class="line">State                              : Active</span><br><span class="line">Physical state                     : LinkUp</span><br><span class="line">Speed                              : IB-NDR</span><br><span class="line">Width                              : 4x</span><br><span class="line">FEC                                : Ethernet_Consortium_LL_50G_RS_FEC_PLR -(272,257+1)</span><br><span class="line">Loopback Mode                      : No Loopback</span><br><span class="line">Auto Negotiation                   : ON</span><br><span class="line"></span><br><span class="line">Supported Info</span><br><span class="line">--------------</span><br><span class="line">Enabled Link Speed                 : 0x00000080 (NDR)</span><br><span class="line">Supported Cable Speed              : 0x00000080 (NDR)</span><br><span class="line"></span><br><span class="line">Troubleshooting Info</span><br><span class="line">--------------------</span><br><span class="line">Status Opcode                      : 0</span><br><span class="line">Group Opcode                       : N/A</span><br><span class="line">Recommendation                     : No issue was observed</span><br><span class="line"></span><br><span class="line">Tool Information</span><br><span class="line">----------------</span><br><span class="line">Firmware Version                   : 28.39.3004</span><br><span class="line">amBER Version                      : 2.22</span><br><span class="line">MFT Version                        : mft 4.26.1-3</span><br><span class="line"></span><br><span class="line">Physical Counters and BER Info</span><br><span class="line">------------------------------</span><br><span class="line">Time Since Last Clear [Min]        : 1744.3</span><br><span class="line">Symbol Errors                      : 0</span><br><span class="line">Symbol BER                         : 15E-255</span><br><span class="line">Effective Physical Errors          : 16</span><br><span class="line">Effective Physical BER             : 3E-16</span><br><span class="line">Raw Physical Errors Per Lane       : 185219462,14538251,3096793152,798004665</span><br><span class="line">Raw Physical BER                   : 1E-7</span><br><span class="line">Link Down Counter                  : 0</span><br><span class="line">Link Error Recovery Counter        : 0</span><br></pre></td></tr></table></figure><h2 id="关注-raw-physical-ber，但两者都要看"><a class="header-anchor" href="#关注-raw-physical-ber，但两者都要看">¶</a><strong>关注 Raw Physical BER，但两者都要看</strong></h2><h3 id="优先级和用途"><a class="header-anchor" href="#优先级和用途">¶</a><strong>优先级和用途</strong></h3><h4 id="🎯-raw-physical-ber-主要关注对象"><a class="header-anchor" href="#🎯-raw-physical-ber-主要关注对象">¶</a><strong>🎯 Raw Physical BER - 主要关注对象</strong></h4><ul><li><strong>作用</strong>：反映<strong>真实的物理层健康状况</strong></li><li><strong>含义</strong>：未经任何纠错处理的原始误码率</li><li><strong>用途</strong>：硬件故障诊断的<strong>第一指标</strong></li></ul><h4 id="📊-effective-physical-ber-辅助参考"><a class="header-anchor" href="#📊-effective-physical-ber-辅助参考">¶</a><strong>📊 Effective Physical BER - 辅助参考</strong></h4><ul><li><strong>作用</strong>：反映<strong>实际数据传输质量</strong></li><li><strong>含义</strong>：经过 FEC 纠错后的最终误码率</li><li><strong>用途</strong>：评估当前链路<strong>可用性</strong></li></ul><hr><h3 id="判断逻辑流程"><a class="header-anchor" href="#判断逻辑流程">¶</a><strong>判断逻辑流程</strong></h3><div class="mermaid-wrap"><pre class="mermaid-src" hidden>  graph TDA[检查 Raw Physical BER] --&gt; B{Raw BER &gt; 1E-12?}B --&gt;|是| C[🔴 物理层有问题]B --&gt;|否| D[检查 Effective BER]C --&gt; E[更换线缆&#x2F;光模块]D --&gt; F{Effective BER &gt; 1E-12?}F --&gt;|是| G[🟡 FEC 纠错压力大]F --&gt;|否| H[✅ 链路健康]G --&gt; I[监控 FEC 负载，准备维护]  </pre></div><hr><h3 id="实际案例分析"><a class="header-anchor" href="#实际案例分析">¶</a><strong>实际案例分析</strong></h3><p>以你之前的数据为例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Raw Physical BER     : 2E-8     ← 🚨 严重超标（正常&lt;1E-12）</span><br><span class="line">Effective Physical BER: 2E-17   ← ✅ 纠错后正常</span><br></pre></td></tr></table></figure><p><strong>解读</strong>：</p><ol><li><strong>Raw BER = 2E-8</strong>：物理层存在严重问题，需要立即更换硬件</li><li><strong>Effective BER = 2E-17</strong>：FEC 正在拼命纠错，暂时保证数据正确性</li><li><strong>风险</strong>：一旦错误突发超过 FEC 能力，会出现数据损坏</li></ol><h3 id="告警阈值设置"><a class="header-anchor" href="#告警阈值设置">¶</a><strong>告警阈值设置</strong></h3><table><thead><tr><th>BER 类型</th><th>正常</th><th>警告</th><th>严重</th><th>紧急</th></tr></thead><tbody><tr><td><strong>Raw BER</strong></td><td>&lt;1E-15</td><td>1E-12</td><td>1E-9</td><td>&gt;1E-8</td></tr><tr><td><strong>Effective BER</strong></td><td>&lt;1E-15</td><td>1E-12</td><td>1E-9</td><td>&gt;1E-6</td></tr></tbody></table><p><strong>总结</strong>：Raw BER 是硬件健康的晴雨表，Effective BER 是当前服务质量的体现。故障排查时 Raw BER 是决策依据</p><ul><li>reference <a href="https://docs.nvidia.com/networking/display/ibdiagnetusermanualv280/bit+error+rate+(ber)">ibdiagnet InfiniBand Fabric Diagnostic Tool User</a></li></ul><h2 id="查看-ib-网卡状态"><a class="header-anchor" href="#查看-ib-网卡状态">¶</a>查看 IB 网卡状态</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ibstatus</span><br></pre></td></tr></table></figure><h2 id="查看-gid"><a class="header-anchor" href="#查看-gid">¶</a>查看 GID</h2><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">show_gids</span><br></pre></td></tr></table></figure><p>典型输出示例：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">DEV             PORT    INDEX   GID                                     IPv4            VER     DEV</span><br><span class="line">---             ----    -----   ---                                     ------------    ---     ---</span><br><span class="line">mlx5_eth0       1       0       fe80:0000:0000:0000:a288:c2ff:fef8:e502                 v1      enP1s10f0np0</span><br><span class="line">mlx5_eth0       1       1       fe80:0000:0000:0000:a288:c2ff:fef8:e502                 v2      enP1s10f0np0</span><br><span class="line">mlx5_eth0       1       2       0000:0000:0000:0000:0000:ffff:5d77:a8bf 93.119.168.191  v1      enP1s10f0np0</span><br><span class="line">mlx5_eth0       1       3       0000:0000:0000:0000:0000:ffff:5d77:a8bf 93.119.168.191  v2      enP1s10f0np0</span><br><span class="line">mlx5_eth1       1       0       fe80:0000:0000:0000:a288:c2ff:fef8:e504                 v1      enP1s10f0v0</span><br><span class="line">mlx5_eth1       1       1       fe80:0000:0000:0000:a288:c2ff:fef8:e504                 v2      enP1s10f0v0</span><br><span class="line">mlx5_eth1       1       2       0000:0000:0000:0000:0000:ffff:0a89:00e1 10.137.0.225    v1      enP1s10f0v0</span><br><span class="line">mlx5_eth1       1       3       0000:0000:0000:0000:0000:ffff:0a89:00e1 10.137.0.225    v2      enP1s10f0v0</span><br><span class="line">mlx5_eth2       1       0       fe80:0000:0000:0000:a288:c2ff:fef8:e505                 v1      enP1s10f0v1</span><br><span class="line">mlx5_eth2       1       1       fe80:0000:0000:0000:a288:c2ff:fef8:e505                 v2      enP1s10f0v1</span><br><span class="line">mlx5_eth3       1       0       fe80:0000:0000:0000:a288:c2ff:fef8:e506                 v1      enP1s10f0v2</span><br><span class="line">mlx5_eth3       1       1       fe80:0000:0000:0000:a288:c2ff:fef8:e506                 v2      enP1s10f0v2</span><br><span class="line">mlx5_eth4       1       0       fe80:0000:0000:0000:a288:c2ff:fef8:e507                 v1      enP1s10f0v3</span><br><span class="line">mlx5_eth4       1       1       fe80:0000:0000:0000:a288:c2ff:fef8:e507                 v2      enP1s10f0v3</span><br><span class="line">mlx5_ib0        1       0       fe80:0000:0000:0000:58a2:e103:00e4:297a                 v1</span><br><span class="line">mlx5_ib1        1       0       fe80:0000:0000:0000:58a2:e103:00e4:295e                 v1</span><br><span class="line">mlx5_ib2        1       0       fe80:0000:0000:0000:58a2:e103:00e4:2986                 v1</span><br><span class="line">mlx5_ib3        1       0       fe80:0000:0000:0000:58a2:e103:00e4:2976                 v1</span><br><span class="line">mlx5_ib4        1       0       fe80:0000:0000:0000:58a2:e103:00e4:2946                 v1</span><br><span class="line">mlx5_ib5        1       0       fe80:0000:0000:0000:58a2:e103:00e4:2c76                 v1</span><br><span class="line">mlx5_ib6        1       0       fe80:0000:0000:0000:58a2:e103:00e4:2c5e                 v1</span><br><span class="line">mlx5_ib7        1       0       fe80:0000:0000:0000:58a2:e103:00e4:2c6a                 v1</span><br><span class="line">n_gids_found=22</span><br></pre></td></tr></table></figure><p>字段解释：</p><ul><li>DEV: IB 设备名称（对应物理网卡）</li><li>PORT: 网卡端口号</li><li>INDEX: GID 表索引</li><li>GID: 128 位全局标识符</li><li>IPv4: 对应的 IPv4 地址（如果有）</li><li>VER: GID 版本（v1 或 v2）</li></ul><h3 id="gid（global-identifier）是什么？"><a class="header-anchor" href="#gid（global-identifier）是什么？">¶</a>GID（Global Identifier）是什么？</h3><p>GID 是 InfiniBand 网络中的全局标识符，是一个 128 位的标识符，用于在整个 InfiniBand 子网中唯一标识一个端口。</p><h3 id="与-ib-网卡的关系"><a class="header-anchor" href="#与-ib-网卡的关系">¶</a>与 IB 网卡的关系</h3><ul><li>物理层关联：<ul><li>每个 IB 网卡端口都有一个或多个 GID</li><li>GID 存储在网卡的固件中</li><li>通过硬件 GUID（全局唯一标识符）生成</li></ul></li><li>逻辑层功能：<ul><li>用于路由和寻址</li><li>支持 IPv6 兼容格式</li><li>实现子网间通信</li></ul></li></ul>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;最近发现 H100 集群 IB 网络通信有问题。跑 DeepEP，MoonCake 都会有通信报错。nccl init 也很慢。&lt;/p&gt;
&lt;p&gt;正常跑 ibsend 啥的都没问题。&lt;/p&gt;
&lt;p&gt;命令：&lt;/p&gt;
&lt;figure class=&quot;highlight</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    
    <category term="CUDA" scheme="https://www.jmyjmy.top/tags/CUDA/"/>
    
  </entry>
  
  <entry>
    <title>专家并行负载均衡 EPLB</title>
    <link href="https://www.jmyjmy.top/2025-06-09_EPLB/"/>
    <id>https://www.jmyjmy.top/2025-06-09_EPLB/</id>
    <published>2025-06-09T01:20:41.000Z</published>
    <updated>2025-06-09T01:20:41.000Z</updated>
    
    <content type="html"><![CDATA[<p>MOE 模型 用两个batch 互相overlap的方式使得通信和计算都不闲着，而且保持通信稍稍大于计算10us左右。最大限度利用完整了计算和通信，但是这样就够了吗？</p><p>加了Two-Batch-Overlap后还是很慢，通过profile发现通信等待的时间越往后越长，计算耗时几乎没有，全是通信的等待。为什么呢？</p><p>把所有卡的trace 合到一起看才能看出来:</p><p><img src="/img/eplb/59ee4deb-c943-4aab-85d9-4d73cb538c8b.webp" alt="负载不均衡"><br>上图中，浅粉色是Dispatch wait，深紫色是Combine wait，空白的地方是计算kernel</p><p>有的GPU一直在等待通信，有的GPU没有通信等待，全程计算。</p><p>说明专家负载不均衡，高负载的专家都集中在一张GPU上，导致这个GPU算不过来，而其他GPU空闲等待。<br><img src="/img/eplb/see.webp" alt="真实的专家并行"></p><p>那咋办。token选的专家又不能换，那就换专家的位置，只要负载高的专家别集中在一个卡上就行了。</p><p>在调用dispatch的时候hook一下，统计每个专家被选的次数。然后根据专家的负载重新排序，把高负载和低负载的专家中和一下放一个卡上。另外，还可以增加冗余专家：既然高负载的专家只有一份放哪个GPU都算不过来，那就复制一下。</p><p>一个不是很严谨的例子：<br><img src="/img/eplb/eplb_unbalance.webp" alt="unbalance"><br>例中，红色表示高负载，绿色表示低负载，上图中，GPU1负载最高，GPU3负载最低。<br><img src="/img/eplb/eplb_balance.webp" alt="balance"><br>均衡后，高负载的Expert1，3，5，6复制了两份，4个GPU负载都差不多了。</p><p>EPLB中还有两种均衡策略：</p><blockquote><p>Hierarchical Load Balancing<br>When the number of server nodes divides the number of expert groups, we use the hierarchical load balancing policy to harness the group-limited expert routing. We first pack the expert groups to nodes evenly, ensuring the loads of different nodes are balanced. Then, we replicate the experts within each node. Finally, we pack the replicated experts to individual GPUs to ensure different GPUs are load-balanced. The hierarchical load balancing policy can be used in prefilling stage with a smaller expert-parallel size.</p><p>Global Load Balancing<br>In other cases, we use the global load balancing policy that replicates the experts globally regardless of expert groups, and pack the replicated experts to individual GPUs. This policy can be adopted in decoding stage with a larger expert-parallel size.</p><p><a href="https://github.com/deepseek-ai/EPLB">EPLB Github</a></p></blockquote><p>Decode节点进行全局负载均衡，直接重排所有GPU所有权重。（EP size 大）<br>Prefill节点中权重按组负载均衡（EP size 小），先分高负载配低负载好组，然后把各个组放到各个结点。这里分组均衡和全局均衡的区别，说是同一个组放一个机器更好，可能是因为训练时带有分组相关loss？</p><p><img src="/img/eplb/eplb_trace.webp" alt="balanced trace"></p><p>均衡后再看trace，嗯舒服了。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;MOE 模型 用两个batch</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>MOE - Micro Batch Overlap with EP</title>
    <link href="https://www.jmyjmy.top/2025-05-19_MOE-Micro-Batch-Overlap/"/>
    <id>https://www.jmyjmy.top/2025-05-19_MOE-Micro-Batch-Overlap/</id>
    <published>2025-05-19T04:01:18.000Z</published>
    <updated>2025-05-19T04:01:18.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="moe-mixture-of-experts"><a class="header-anchor" href="#moe-mixture-of-experts">¶</a>MOE(Mixture-of-Experts)</h2><p>一句话：训练多个专家模型组合成一个更大的模型，在前向过程中动态选择TopK个专家。</p><p>这样做可以在训练时也避免各个领域知识互相打架导致模型难以收敛。</p><p>相比一个很大的模型什么都会什么都不太对，也就是学杂了，拆成小模型然后需要哪个用哪个来保证样样精通更容易提高模型的通用性和准确性。</p><h3 id="组成"><a class="header-anchor" href="#组成">¶</a>组成</h3><p>Gate 就是一个全连接打个分投个票，根据当前input得到他对于各个专家的相关性，然后选取topk个专家</p><p>所谓专家，也只是很简单的MLP升维再降维（当然可以换成任何网络结构）</p><p>还有共享专家，就是不走Gate打分，相当于普通的MLP。但是相比普通的MLP，拆成多个专家后计算量少很多。</p><p>专家们算完结果，最后拿到一起用Gate打的分做个加权。</p><p>得到输出，给到下一层的RN+MLA</p><p><img src="/img/MOE_EP/MOE_naive.webp" alt="MOE"></p><h2 id="ep-expert-parallelism"><a class="header-anchor" href="#ep-expert-parallelism">¶</a>EP(Expert Parallelism)</h2><p>DeepSeek V3 有256个专家+32个共享专家，MOE中Topk = 8。</p><p>在DeepSeek 的MOE 中，使用EP，把全部256个专家分散到所有卡上，每个卡各自仍保留完整的32个共享专家。</p><p>根据Gate的结果选取8个专家，然后All-to-All把hidden_state传到选中的专家（可能就在当前卡，可能在同一个机器，也可能在其他机器上）。算完后再All-to-All收集回原来的卡上。</p><p><img src="/img/MOE_EP/DP_EP_MOE.webp" alt="EP"></p><h3 id="通信开销"><a class="header-anchor" href="#通信开销">¶</a>通信开销</h3><p>每层都有2次 All-to-All 通信，使用DeepEP实现。其中把hidden state根据topk 发送出去叫dispatch，Dtype是FP8，MLP后收回来叫combine，Dtype是BF16</p><p>通信量计算</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">(</mo><mn>1</mn><mtext>Byte</mtext><mo>+</mo><mn>2</mn><mtext>Bytes</mtext><mo stretchy="false">)</mo><mo>×</mo><mn>32</mn><mo>×</mo><mn>9</mn><mo>×</mo><mn>7168</mn><mo>÷</mo><mn>50</mn><mtext>GB/s</mtext><mo>=</mo><mn>120.96</mn><mtext>us</mtext></mrow><annotation encoding="application/x-tex">(1\text{Byte} + 2\text{Bytes}) \times 32 \times 9 \times 7168 \div 50\text{GB/s} = 120.96\text{us}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">1</span><span class="mord text"><span class="mord">Byte</span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord text"><span class="mord">Bytes</span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">32</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">9</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">7168</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">50</span><span class="mord text"><span class="mord">GB/s</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">120.96</span><span class="mord text"><span class="mord">us</span></span></span></span></span></span></p><blockquote><p>Here, dispatch uses FP8 (1 byte), while combine uses BF16 (2 bytes), and the hidden size of each token is approximately 7K. The factor 9 indicates that each token is ransferred to 8 routed experts and 1 shared expert.</p></blockquote><p>profile发现通信开销是大头。</p><h2 id="micro-batch-overlap-tbo-two-batch-overlap"><a class="header-anchor" href="#micro-batch-overlap-tbo-two-batch-overlap">¶</a>Micro batch Overlap (TBO, two-batch-overlap)</h2><p>一层可以分为几个部分</p><ul><li>MLA</li><li>Gate + select</li><li>share expert</li><li>dispatch</li><li>MLP</li><li>combine</li></ul><p>其中通信有dispatch和combine，而且combine的耗时是dispatch的两倍，是前面小后面大。计算量都不大，MLA略多于MLP，是前面大后面小。</p><p><img src="/img/MOE_EP/EP-sync.webp" alt="EP"></p><p>考虑把大块通信和大块计算重叠，那么把输入平均切成两个小batch，错开顺序使得一个batch的combine和另一个batch的MLA重叠， 一个batch的dispatch和另一个batch的share expert重叠。</p><p><img src="/img/MOE_EP/TBO.webp" alt="TBO overlap"></p><p>MLA切成了两个部分，一部分是计算QK+RMS Norm，另一部分是Attention。细分计算步骤更灵活的重叠。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;moe-mixture-of-experts&quot;&gt;&lt;a class=&quot;header-anchor&quot;</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>记一次NVIDIA GPU ECC故障</title>
    <link href="https://www.jmyjmy.top/2025-05-15_nvidia-ECC-error/"/>
    <id>https://www.jmyjmy.top/2025-05-15_nvidia-ECC-error/</id>
    <published>2025-05-15T09:57:19.000Z</published>
    <updated>2025-05-15T09:57:19.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="现象"><a class="header-anchor" href="#现象">¶</a>现象</h2><p>跑程序意外退出，crash在cpp里面了，随机复现，无法定位</p><h2 id="排查"><a class="header-anchor" href="#排查">¶</a>排查</h2><p>查看dmesg发现DBE<br><img src="/img/nvidia_ecc/dbe.webp" alt="DBE"><br>赶紧查看一下ECC count</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nvidia-smi -q -d ECC</span><br></pre></td></tr></table></figure><p><img src="/img/nvidia_ecc/ecc.webp" alt="nvidia-smi -q -d ECC"></p><p><em><strong>好的直接换卡。</strong></em></p><h2 id="错误类型"><a class="header-anchor" href="#错误类型">¶</a>错误类型</h2><table><thead><tr><th style="text-align:right">错误类型</th><th style="text-align:left">可修复性</th><th style="text-align:left">严重性</th><th style="text-align:left">建议行动</th></tr></thead><tbody><tr><td style="text-align:right">SRAM Correctable (SBE)</td><td style="text-align:left">可自动修复</td><td style="text-align:left">低</td><td style="text-align:left">监控趋势</td></tr><tr><td style="text-align:right">DRAM Correctable (SBE)</td><td style="text-align:left">可自动修复</td><td style="text-align:left">低</td><td style="text-align:left">监控趋势</td></tr><tr><td style="text-align:right">SRAM Uncorrectable Parity</td><td style="text-align:left">不可修复</td><td style="text-align:left">高</td><td style="text-align:left">立即调查</td></tr><tr><td style="text-align:right">DRAM Uncorrectable (DBE)</td><td style="text-align:left">不可修复</td><td style="text-align:left">高</td><td style="text-align:left">立即调查</td></tr></tbody></table><h2 id="reference"><a class="header-anchor" href="#reference">¶</a>Reference</h2><p>nvidia-smi 文档：<a href="https://docs.nvidia.com/deploy/nvidia-smi/index.html">nvidia-smi - NVIDIA System Management Interface program</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;现象&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#现象&quot;&gt;¶&lt;/a&gt;现象&lt;/h2&gt;
&lt;p&gt;跑程序意外退出，crash在cpp里面了，随机复现，无法定位&lt;/p&gt;
&lt;h2 id=&quot;排查&quot;&gt;&lt;a class=&quot;header-anchor&quot;</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    
    <category term="CUDA" scheme="https://www.jmyjmy.top/tags/CUDA/"/>
    
  </entry>
  
  <entry>
    <title>nvidia 查看拓扑</title>
    <link href="https://www.jmyjmy.top/2025-04-29_nvidia-topo/"/>
    <id>https://www.jmyjmy.top/2025-04-29_nvidia-topo/</id>
    <published>2025-04-29T11:53:52.000Z</published>
    <updated>2025-04-29T11:53:52.000Z</updated>
    
    <content type="html"><![CDATA[<p>在国外的H100机器上查看GPU拓扑</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nvidia-smi topo -m</span><br></pre></td></tr></table></figure><p><img src="/img/nvidia-smi-topo.webp" alt="nvidia-smi topo -m"></p><p>SYS (System): 表示通过系统互连（如QPI/UPI总线）连接的设备。</p><ul><li>这是最慢的连接方式，通常需要完整的数据往返系统内存</li><li>两个设备之间的通信必须通过系统内存（主机内存）进行</li><li>数据传输需要经过 CPU 和系统总线</li><li>两个设备之间没有直接的点对点（P2P）连接</li></ul><p>NODE: 表示NUMA节点内的连接 NUMA Node Connection，即设备位于同一个NUMA节点内。<br>NUMA 是一种计算机内存设计，其中内存访问时间取决于内存相对于处理器的位置。在大型服务器系统中，可能有多个 NUMA 节点，每个节点包含自己的处理器、内存和 I/O 设备。</p><ul><li>两个设备位于同一个 NUMA（非统一内存访问）节点内</li><li>它们共享同一个内存控制器和本地内存</li><li>虽然仍然需要通过系统内存通信，但延迟通常比 SYS 连接低</li><li>在多处理器系统中特别相关</li></ul><p>NV# (如NV18): 表示通过NVIDIA NVLink连接的设备，数字表示NVLink的带宽或版本。</p><p>PIX (PCI Express Switch): 同一 PCIe 交换机下的 GPU，<strong>如ROCE，IB网络</strong>。</p><ul><li>数据路径：GPU → PCIe → GPU</li><li>完全支持P2P</li></ul><p>PXB (PCI Express Bridge): 不同 PCIe 交换机但同一 PCIe 段的 GPU</p><ul><li>数据路径：GPU → PCIe → PCIe桥 → PCIe → GPU</li><li>支持P2P</li></ul><p>PHB (PCI Host Bridge): 表示不同 PCIe 根复合体的 GPU ，通过PCI主机桥连接的设备。</p><ul><li>数据路径： GPU → PCIe → 主机桥 → PCIe → GPU</li><li>有限支持P2P</li></ul><p>NIC 是Network Interface Card ，上图每个GPU都有一个IB网卡</p><p>Reference: <a href="https://docs.nvidia.com/deploy/nvidia-smi/index.html">nvidia-smi - NVIDIA System Management Interface program</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;在国外的H100机器上查看GPU拓扑&lt;/p&gt;
&lt;figure class=&quot;highlight bash&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
    <category term="CUDA" scheme="https://www.jmyjmy.top/tags/CUDA/"/>
    
  </entry>
  
  <entry>
    <title>福建之行</title>
    <link href="https://www.jmyjmy.top/2025-04-26_fu-jian-travel/"/>
    <id>https://www.jmyjmy.top/2025-04-26_fu-jian-travel/</id>
    <published>2025-04-26T17:43:09.000Z</published>
    <updated>2025-04-26T17:43:09.000Z</updated>
    
    <content type="html"><![CDATA[<p>用一周时间去了一趟福建，参加了一个婚礼顺便把福建多个城市都打卡了一下</p><h2 id="行程"><a class="header-anchor" href="#行程">¶</a>行程</h2><div class="timeline undefined"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>4月13日·福州</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>8:13</p></div></div><div class='timeline-item-content'><p>高铁 上海虹桥-福州</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>12:30</p></div></div><div class='timeline-item-content'><p>到达福州酒店办理入住，简单休整</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>13:30</p></div></div><div class='timeline-item-content'><p>三坊七巷吃吃逛逛</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>17:00</p></div></div><div class='timeline-item-content'><p>去上下杭继续吃吃逛逛</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>18:00</p></div></div><div class='timeline-item-content'><p>在闽江边青年广场拍日落</p></div></div></div><div class="timeline undefined"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>4月14日·平潭</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>9:30</p></div></div><div class='timeline-item-content'><p>租车从福州出发前往平潭</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>11:30</p></div></div><div class='timeline-item-content'><p>到达平潭仙人井景区</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>15:00</p></div></div><div class='timeline-item-content'><p>一路向北沿海边逛逛拍拍</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>16:40</p></div></div><div class='timeline-item-content'><p>到达北部湾玻璃栈道</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>18:20</p></div></div><div class='timeline-item-content'><p>到达北部生态廊道F5观景台拍日落</p></div></div></div><div class="timeline undefined"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>4月15日·莆田</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>12:00</p></div></div><div class='timeline-item-content'><p>高铁到莆田</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>14:30</p></div></div><div class='timeline-item-content'><p>大巴-乘船至湄洲岛</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>15:00</p></div></div><div class='timeline-item-content'><p>到湄洲岛上民宿办入住</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>16:00</p></div></div><div class='timeline-item-content'><p>租电驴到湄洲岛最南端鹅尾海蚀公园</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>18:30</p></div></div><div class='timeline-item-content'><p>在山顶灯塔拍日落</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>18:30</p></div></div><div class='timeline-item-content'><p>在山顶灯塔拍日落</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>19:30</p></div></div><div class='timeline-item-content'><p>在农贸市场附近吃晚餐</p></div></div></div><div class="timeline undefined"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>4月16日·莆田&amp;泉州</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>5:30</p></div></div><div class='timeline-item-content'><p>在民宿露台看日出，然后回去继续睡觉</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>10:00</p></div></div><div class='timeline-item-content'><p>天妃故里，了解妈祖文化</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>12:00</p></div></div><div class='timeline-item-content'><p>妈祖祖庙</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>17:00</p></div></div><div class='timeline-item-content'><p>乘船-大巴-到达莆田火车站前往泉州</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>20:00</p></div></div><div class='timeline-item-content'><p>泉州古城，开元寺，西街，钟楼</p></div></div></div><div class="timeline undefined"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>4月17日·泉州&amp;永安</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>10:00</p></div></div><div class='timeline-item-content'><p>南少林寺</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>12:00</p></div></div><div class='timeline-item-content'><p>蟳埔民俗文化村</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>16:00</p></div></div><div class='timeline-item-content'><p>到达泉州站，坐城际动车去永安</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>18:30</p></div></div><div class='timeline-item-content'><p>到达永安，晚餐</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>20:00</p></div></div><div class='timeline-item-content'><p>婚礼前准备</p></div></div></div><div class="timeline undefined"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>4月18日·永安</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>5:00</p></div></div><div class='timeline-item-content'><p>接亲</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>12:00</p></div></div><div class='timeline-item-content'><p>婚礼</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>15:00</p></div></div><div class='timeline-item-content'><p>贡川古镇</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>17:00</p></div></div><div class='timeline-item-content'><p>九龙竹海</p></div></div></div><div class="timeline undefined"><div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'><p>4月19日·永安</p></div></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>7:30</p></div></div><div class='timeline-item-content'><p>早餐，特色小吃</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>9:00</p></div></div><div class='timeline-item-content'><p>天宝岩景区</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>12:30</p></div></div><div class='timeline-item-content'><p>午餐</p></div></div><div class='timeline-item'><div class='timeline-item-title'><div class='item-circle'><p>15:15</p></div></div><div class='timeline-item-content'><p>乘高铁返回上海</p></div></div></div><h2 id="福州"><a class="header-anchor" href="#福州">¶</a>福州</h2><p>由十条东西走向的小街巷构成 “棋盘状” 街区，南后街西边三条为 “三坊”，即衣锦坊、文儒坊、光禄坊，东边七条为 “七巷”，从北到南依次是杨桥巷、郎官巷、塔巷、黄巷、安民巷、宫巷、吉庇巷。坊巷内院落沿中轴线对称分布，宅院外有围墙，内部多进院落沿纵深轴线布置，为中轴线对称布局，白墙瓦屋，曲线山墙，具有典型的福州建筑风格，被称为 “明清建筑博物馆”。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/1.webp","alt":""},{"url":"/img/fujian/2.webp","alt":""},{"url":"/img/fujian/3.webp","alt":""},{"url":"/img/fujian/4.webp","alt":""},{"url":"/img/fujian/6.webp","alt":""},{"url":"/img/fujian/7.webp","alt":""},{"url":"/img/fujian/8.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>一片三坊七巷，半部中国近现代史。很多近代的名人都曾在此居住，如林觉民冰心故居，林则徐纪念馆。</p><p><img src="/img/fujian/IMG_20250413_135333.webp" alt="林觉民是林徽因的叔叔"></p><p>林觉民故居内有林觉民生平事迹的介绍，展示了他从出生于福州书香门第，到接受新式教育、东渡日本留学、加入中国同盟会，再到参加广州起义并英勇就义的全过程，让人们了解到他为民族独立和解放事业所做出的巨大贡献。厢房内有著名的《与妻书》手迹。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/IMG_20250413_135348.webp","alt":""},{"url":"/img/fujian/IMG_20250413_135455.webp","alt":""},{"url":"/img/fujian/5.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>林则徐纪念馆原为林则徐专祠，建于清光绪三十一年，占地面积约 3000 平方米，内有仪门厅、御碑亭、树德堂、南北花厅、曲尺楼、竹柏轩等主要建筑物，具有江南园林风格。</p><p>进入馆内迎面的有御碑亭，亭中的圣旨是清咸丰皇帝得知林则徐病逝后，慰问其家属的圣旨。圣旨刻在青石碑上，放置于御碑亭正中位置。御碑亭为正方形重檐歇山顶，内立三座御赐石碑，成品字形排列，隐喻林则徐一生品重柱石，刚正不阿。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/9.webp","alt":""},{"url":"/img/fujian/25.webp","alt":""},{"url":"/img/fujian/26.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>除了熟知的“虎门销烟”外，林则徐还兴修水利。鸦片战争爆发后他被贬新疆，在新疆对坎儿井进行了改良和推广。1845 年初，林则徐在赴南疆勘地途中第一次见到坎儿井，认为其 “其利甚薄，其法颇巧”，于是积极推广官府筹集银两开挖坎儿井，并倡导农民 “自行出夫挖井”。在林则徐的推动下，从 1845 年到 1877 年，吐鲁番、鄯善、托克逊新挖坎儿井 300 多条，使许多荒地变成了沃壤。为感谢林则徐的功绩，当地群众把坎儿井称之为 “林公井”<br><img src="/img/fujian/27.webp" alt="做官不易，做大官更不易"><br>“做官不易，做大官更不易。我是奉命唯谨，毕恭毕敬。夫人务嘱二儿须千万谨慎，切勿仰仗乃父的势力，和官府佞相往来，更不可干预地方事务。” 他通过家书告诫家人，做官要时刻保持谨慎，不能凭借权势为非作歹，这体现了林则徐自身廉洁奉公的高尚品格以及对家人严格要求的治家之道。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/28.webp","alt":""},{"url":"/img/fujian/29.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>同利肉燕和烧卖很好吃</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/10.webp","alt":""},{"url":"/img/fujian/11.webp","alt":""},{"url":"/img/fujian/30.webp","alt":""},{"url":"/img/fujian/31.webp","alt":""},{"url":"/img/fujian/32.webp","alt":""},{"url":"/img/fujian/33.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>福州上下杭有众多明清古建筑、会馆，如古田会馆等</p><p><img src="/img/fujian/34.webp" alt="青年广场"><br>青年广场在闽江边，适合拍夜景</p><h2 id="平潭"><a class="header-anchor" href="#平潭">¶</a>平潭</h2><p>这里的海是蓝色的！</p><p>岛上有很多风车。</p><p>平潭作为里台湾最近的岛，京台高速G3目前的终点，是被好好开发过的。岛上风景很好，开车走在沿海的公路上很舒服，但工作日依然会堵车。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/12.webp","alt":""},{"url":"/img/fujian/13.webp","alt":""},{"url":"/img/fujian/14.webp","alt":""},{"url":"/img/fujian/15.webp","alt":""},{"url":"/img/fujian/16.webp","alt":""},{"url":"/img/fujian/35.webp","alt":""},{"url":"/img/fujian/36.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><h2 id="湄洲岛"><a class="header-anchor" href="#湄洲岛">¶</a>湄洲岛</h2><p>湄洲岛需要从莆田火车站乘公交车到文甲码头，从码头乘船上岛，船票￥125包括景区门票。到岛上民宿的会派车接送到民宿，在租个电驴￥50一天。</p><p>岛上的民宿有一个联合管理的组织，会统一派车接送，统一安排租车服务。</p><p>我订的民宿叫 “默林”，妈祖叫 林默。这个民宿是妈祖传承人的房子。在海边景色很好。<br><img src="/img/fujian/17.webp" alt="民宿楼顶露台"></p><p>岛上风景很不错，骑个电驴去哪里都很方便。<br><img src="/img/fujian/23.webp" alt="日出"><br><img src="/img/fujian/42.webp" alt="妈祖祖庙山上栈道俯瞰“湄屿潮音”"></p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/18.webp","alt":""},{"url":"/img/fujian/24.webp","alt":""},{"url":"/img/fujian/43.webp","alt":""},{"url":"/img/fujian/44.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>鹅尾海蚀公园有沙滩，有山。可以沿着海边的步道爬山，上山先往“小象赶海”方向走，然后打卡“飞戟洞”，在金山寺后面上山顶到灯塔，再回到起点。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/19.webp","alt":""},{"url":"/img/fujian/20.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>天妃故里遗址公园从大牌坊上山，里面有很多展馆讲妈祖的历史文化，以及两岸交流。吃了红团很好吃。<br><img src="/img/fujian/37.webp" alt="红团"><br><img src="/img/fujian/38.webp" alt="天妃故里山顶上的“林默铜像”"></p><p>妈祖祖庙在岛的北部山顶上，可以俯瞰整个湄洲岛，有妈祖庇佑湄洲岛的意思。<br><img src="/img/fujian/39.webp" alt="300多千克，纯金妈祖像"></p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/21.webp","alt":""},{"url":"/img/fujian/22.webp","alt":""},{"url":"/img/fujian/IMG_20250416_122734.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>去的这周临近妈祖生日三月廿三，每天中午都有很长的队伍护送妈祖像游行。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/71.webp","alt":""},{"url":"/img/fujian/72.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><h2 id="泉州"><a class="header-anchor" href="#泉州">¶</a>泉州</h2><p>晚上到开元寺，沿着西街逛吃。商业很重，很多景点特色的卖茶叶卖酒卖金银卖小吃的店。这里有个奶茶店叫“壶见”类似茶颜悦色。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/41.webp","alt":""},{"url":"/img/fujian/40.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>钟楼围起来在搭T台。没有拍照。</p><p>第二天早上去了南少林寺和浔埔，在浔埔体验了簪花。簪花店里有一个老奶奶来簪花，也是体验到传统手艺了。可惜我头发太短只能戴个发箍。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/45.webp","alt":""},{"url":"/img/fujian/46.webp","alt":""},{"url":"/img/fujian/47.webp","alt":""},{"url":"/img/fujian/48.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p><img src="/img/fujian/49.webp" alt="牛肉羹"><br><img src="/img/fujian/50.webp" alt="海蛎煎"></p><h2 id="永安"><a class="header-anchor" href="#永安">¶</a>永安</h2><p>参加婚礼<br><img src="/img/fujian/52.webp" alt="早上接亲时在新娘家吃的甜汤"><br><img src="/img/fujian/51.webp" alt="终于让我放到炮了哈哈"><br>后面就是新娘的姨丈（姨父）带我们来参加婚礼的外地人去永安周边逛。</p><p>贡川古镇古名 “贡堡”，是福建唯一的城堡式古镇，也是福建省现存最完整的古镇之一。早在新石器时代就有人类活动，唐代开始开发，宋代达到辉煌，陈姓家族享有 “一门双理学，九子十登科” 的美誉，宋高宗还特赐 “大儒里” 牌坊。明清时期进士、举人、贡生众多，明末城堡内建有书院，藏书十万册。</p><p>省级文物保护单位有古城墙、会清桥、笋帮公栈；市级文物保护单位有正顺庙、陈氏大宗祠、古井、李宝峻故居等。</p><p>会清桥造型别致，建于明末清初，桥屋有 11 间，56 根木柱，南北两端设有门楼，中部是升起的桥亭，布局匀称。<br><img src="/img/fujian/56.webp" alt="这里河水泾渭分明汇在一起，故名“会清”"></p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/53.webp","alt":""},{"url":"/img/fujian/54.webp","alt":""},{"url":"/img/fujian/55.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>古桥，古城桥，古青石板路。都有几百甚至上千年历史，没想到在这没什么游客的小古镇里见着真的古迹了。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/57.webp","alt":""},{"url":"/img/fujian/58.webp","alt":""},{"url":"/img/fujian/59.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>九龙竹海，曲折的山路穿过竹海。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/60.webp","alt":""},{"url":"/img/fujian/61.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p><img src="/img/fujian/62.webp" alt="超嫩竹笋"></p><p>永安小吃也很多，比沙县好吃</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/63.webp","alt":"早上吃永安小吃"},{"url":"/img/fujian/64.webp","alt":"叉叉粿，用叉子叉着吃"},{"url":"/img/fujian/65.webp","alt":"叉叉粿，用叉子叉着吃"}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>天宝岩原始森林覆盖率达 96.7%，是闽江重要水源涵养林区和国内少有的物种基因库之一。里面一条清澈干净的小溪流过。有华东地区较为罕见的绝壁、深谷、飞瀑、激流、密林等景观资源组合。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="800" data-limit="20">    <span class="gallery-data">[{"url":"/img/fujian/66.webp","alt":""},{"url":"/img/fujian/67.webp","alt":""},{"url":"/img/fujian/68.webp","alt":""},{"url":"/img/fujian/69.webp","alt":""},{"url":"/img/fujian/70.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;用一周时间去了一趟福建，参加了一个婚礼顺便把福建多个城市都打卡了一下&lt;/p&gt;
&lt;h2 id=&quot;行程&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#行程&quot;&gt;¶&lt;/a&gt;行程&lt;/h2&gt;
&lt;div class=&quot;timeline undefined&quot;&gt;&lt;div</summary>
        
      
    
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/categories/Travel/"/>
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/tags/Travel/"/>
    
  </entry>
  
  <entry>
    <title>雷军在雷军班主题班会上，跟大家做了一些分享</title>
    <link href="https://www.jmyjmy.top/2025-03-27_leijun-speech/"/>
    <id>https://www.jmyjmy.top/2025-03-27_leijun-speech/</id>
    <published>2025-03-27T18:08:28.000Z</published>
    <updated>2025-03-27T18:08:28.000Z</updated>
    
    <content type="html"><![CDATA[<p>原视频<br><a href="https://www.bilibili.com/video/BV1HyZ3YREUg/?share_source=copy_web&amp;vd_source=5e4cc8f3eba46e607b6f1b1072e7aae5">【【雷军】在雷军班主题班会上，跟大家做了一些分享</a></p><p>雷军讲自己如何造车的，前面铺垫了很多带货的凸显造车的成功。那么为什么？</p><ul><li><em>小米的复盘文化，经常复盘，什么做的好，什么做的不好，假如重来要怎么做。</em></li></ul><blockquote><p>小米是造车产业的新人，第一天就说要做全球前五</p></blockquote><blockquote><p>小米的产品方法论：做第一，唯一，最好。小米汽车里列了100项第一，最后可能做成了只有三分之一，那也挺好</p></blockquote><ul><li><em>要有高目标牵引，求其上者，得其中。激发挑战精神，只要开始追赶我们就在赢的路上，我们要用无比乐观的精神看待工作生活遇到的各种困难</em></li><li><em>要分解目标，分解成多个“稍微努努力就能达成”的目标，不然直接被高目标劝退。</em></li><li><em><strong>热爱</strong>，造摄影手机，只有懂摄影、爱摄影的才能造好摄影手机，只有懂车、爱车的才能造好车。</em></li></ul>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;原视频&lt;br&gt;
&lt;a</summary>
        
      
    
    
    
    <category term="Think" scheme="https://www.jmyjmy.top/categories/Think/"/>
    
    
  </entry>
  
  <entry>
    <title>docker工具脚本合集</title>
    <link href="https://www.jmyjmy.top/2025-03-25_docker-scripts/"/>
    <id>https://www.jmyjmy.top/2025-03-25_docker-scripts/</id>
    <published>2025-03-25T07:35:26.000Z</published>
    <updated>2025-03-25T07:35:26.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="根据进程找容器"><a class="header-anchor" href="#根据进程找容器">¶</a>根据进程找容器</h2><p><code>find_docker.sh</code></p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line">docker ps -a --filter <span class="built_in">id</span>=$(<span class="built_in">cat</span> /proc/<span class="variable">$1</span>/cgroup | grep docker | awk -F <span class="string">&#x27;/&#x27;</span> <span class="string">&#x27;&#123;print $3&#125;&#x27;</span>  | <span class="built_in">uniq</span>)</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">docker ps -a --filter <span class="built_in">id</span>=$(<span class="built_in">cat</span> /proc/<span class="variable">$1</span>/cgroup | grep docker | awk -F <span class="string">&#x27;/&#x27;</span> <span class="string">&#x27;&#123;print $3&#125;&#x27;</span> | awk -F<span class="string">&#x27;-&#x27;</span> <span class="string">&#x27;&#123;print$2&#125;&#x27;</span> | awk -F<span class="string">&#x27;.&#x27;</span> <span class="string">&#x27;&#123;print $1&#125;&#x27;</span> | <span class="built_in">uniq</span>)</span><br></pre></td></tr></table></figure><p>Usage:</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./find_docker.sh  12345</span><br></pre></td></tr></table></figure><h2 id="根据overlayfs找容器或镜像layer"><a class="header-anchor" href="#根据overlayfs找容器或镜像layer">¶</a>根据overlayfs找容器或镜像layer</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/bash</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 获取输入参数，即文件系统层ID</span></span><br><span class="line">fslayer_id=<span class="variable">$1</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 遍历所有容器</span></span><br><span class="line"><span class="keyword">for</span> container_id <span class="keyword">in</span> $(docker ps -aq)</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">  <span class="comment"># 使用docker inspect命令获取容器信息，并查找文件系统层ID</span></span><br><span class="line">  <span class="keyword">if</span> docker inspect <span class="variable">$container_id</span> | grep -q <span class="string">&quot;<span class="variable">$fslayer_id</span>&quot;</span></span><br><span class="line">  <span class="keyword">then</span></span><br><span class="line">    <span class="comment"># 如果找到了，打印容器ID并退出脚本</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;File system layer <span class="variable">$fslayer_id</span> is in container: <span class="variable">$container_id</span>&quot;</span></span><br><span class="line">    <span class="built_in">exit</span> 0</span><br><span class="line">  <span class="keyword">fi</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment"># 逐个检查所有的镜像</span></span><br><span class="line"><span class="keyword">for</span> image_id <span class="keyword">in</span> $(docker images -q)</span><br><span class="line"><span class="keyword">do</span></span><br><span class="line">  <span class="comment"># 使用docker history命令检查镜像的每一层</span></span><br><span class="line">  <span class="keyword">if</span> docker <span class="built_in">history</span> <span class="variable">$image_id</span> | grep -q <span class="string">&quot;<span class="variable">$fslayer_id</span>&quot;</span></span><br><span class="line">  <span class="keyword">then</span></span><br><span class="line">    <span class="comment"># 如果找到了，打印镜像ID并退出脚本</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;OverlayFS layer <span class="variable">$fslayer_id</span> is in image: <span class="variable">$image_id</span>&quot;</span></span><br><span class="line">    <span class="built_in">exit</span> 0</span><br><span class="line">  <span class="keyword">fi</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># 如果遍历所有容器后还没有找到，打印错误信息</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;File system layer <span class="variable">$fslayer_id</span> was not found in any container or image&quot;</span></span><br><span class="line"><span class="built_in">exit</span> 1</span><br></pre></td></tr></table></figure><h2 id="squash镜像"><a class="header-anchor" href="#squash镜像">¶</a>squash镜像</h2><p><a href="https://www.jmyjmy.top/2024-08-04_docker-squash/">docker squash</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;根据进程找容器&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#根据进程找容器&quot;&gt;¶&lt;/a&gt;根据进程找容器&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;find_docker.sh&lt;/code&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="Dev Environment" scheme="https://www.jmyjmy.top/categories/Tech-blog/Dev-Environment/"/>
    
    
    <category term="Docker" scheme="https://www.jmyjmy.top/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>nvidia dyanamo get start</title>
    <link href="https://www.jmyjmy.top/2025-03-24_nvidia-dyanamo-get-start/"/>
    <id>https://www.jmyjmy.top/2025-03-24_nvidia-dyanamo-get-start/</id>
    <published>2025-03-24T00:03:29.000Z</published>
    <updated>2025-03-24T00:03:29.000Z</updated>
    
    <content type="html"><![CDATA[<p>NVIDIA 源码开源（没有二进制开源）的VLLM PD分离实现</p><h2 id="主要解决问题"><a class="header-anchor" href="#主要解决问题">¶</a>主要解决问题</h2><ul><li>KV cache offloading 显存不够,内存来凑(很早就有用内存/ssd来扩充kvcache的方法)</li><li>Accelerated data transfer 传输优化((NIXL)[<a href="https://github.com/ai-dynamo/nixl">https://github.com/ai-dynamo/nixl</a>])</li><li>PD分离</li><li>动态请求调度</li><li>动态GPU调度</li></ul><h2 id="运行架构"><a class="header-anchor" href="#运行架构">¶</a>运行架构</h2><p>首先需要etcd prometheus grafana 三件套，deploy目录下有个写好的compose</p><p>这三个启动好了以后可以跑server了</p><p>可以参考/example/llm</p><p>这个目录下还有几个目录</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">components</span><br><span class="line">configs</span><br><span class="line">graphs</span><br><span class="line">utils</span><br></pre></td></tr></table></figure><p>graphs里面是服务架构图，类似triton server里的，定义一个请求按什么步骤处理，比如<code>disagg_router.py</code> 分离架构部署+KV Routing</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> components.frontend <span class="keyword">import</span> Frontend</span><br><span class="line"><span class="keyword">from</span> components.kv_router <span class="keyword">import</span> Router</span><br><span class="line"><span class="keyword">from</span> components.prefill_worker <span class="keyword">import</span> PrefillWorker</span><br><span class="line"><span class="keyword">from</span> components.processor <span class="keyword">import</span> Processor</span><br><span class="line"><span class="keyword">from</span> components.worker <span class="keyword">import</span> VllmWorker</span><br><span class="line"></span><br><span class="line">Frontend.link(Processor).link(Router).link(VllmWorker).link(PrefillWorker)</span><br></pre></td></tr></table></figure><p><code>Processor</code>,<code>Router</code>,<code>VllmWorker</code>,<code>PrefillWorker</code>都在<code>components</code>里定义好初始化参数，实现<code>generate(Request)</code>接口</p><p>这几个类用<code>config</code>里面的yaml配置来初始化，用graph建图，一个server就ready了</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> /workspace/examples/llm</span><br><span class="line">dynamo serve graphs.disagg_router:Frontend -f ./configs/disagg_router.yaml</span><br></pre></td></tr></table></figure><p>各个组件功能：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">                                                 +----------------+</span><br><span class="line">                                          +------| prefill worker |-------+</span><br><span class="line">                                   notify |      |                |       |</span><br><span class="line">                                 finished |      +----------------+       | pull</span><br><span class="line">                                          v                               v</span><br><span class="line">+------+      +-----------+      +------------------+    push     +---------------+</span><br><span class="line">| HTTP |-----&gt;| processor |-----&gt;| decode/monolith  |------------&gt;| prefill queue |</span><br><span class="line">|      |&lt;-----|           |&lt;-----|      worker      |             |               |</span><br><span class="line">+------+      +-----------+      +------------------+             +---------------+</span><br><span class="line">                  |    ^                  |</span><br><span class="line">       query best |    | return           | publish kv events</span><br><span class="line">           worker |    | worker_id        v</span><br><span class="line">                  |    |         +------------------+</span><br><span class="line">                  |    +---------|     kv-router    |</span><br><span class="line">                  +-------------&gt;|                  |</span><br><span class="line">                                 +------------------+</span><br><span class="line"></span><br></pre></td></tr></table></figure>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;NVIDIA 源码开源（没有二进制开源）的VLLM PD分离实现&lt;/p&gt;
&lt;h2 id=&quot;主要解决问题&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#主要解决问题&quot;&gt;¶&lt;/a&gt;主要解决问题&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;KV cache</summary>
        
      
    
    
    
    
  </entry>
  
  <entry>
    <title>LLM 通信量 计算量 总结</title>
    <link href="https://www.jmyjmy.top/2025-03-09_LLM-comm-data-size/"/>
    <id>https://www.jmyjmy.top/2025-03-09_LLM-comm-data-size/</id>
    <published>2025-03-09T04:28:54.000Z</published>
    <updated>2025-03-09T04:28:54.000Z</updated>
    
    <content type="html"><![CDATA[<ul><li>Batch Size <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi></mrow><annotation encoding="application/x-tex">B</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span></span></span></span></li><li>Sequence length <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>S</mi></mrow><annotation encoding="application/x-tex">S</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span></span></li><li>Head num <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>H</mi></mrow><annotation encoding="application/x-tex">H</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span></span></span></span></li><li>Head dim <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi></mrow><annotation encoding="application/x-tex">d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span></li><li>Hidden size <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>h</mi><mo>=</mo><mi>H</mi><mo>×</mo><mi>d</mi></mrow><annotation encoding="application/x-tex">h = H\times d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span></li><li>Parallel Size <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi></mrow><annotation encoding="application/x-tex">p</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span></span></span></span></li></ul><h2 id="tensor-parallel-in-one-machine"><a class="header-anchor" href="#tensor-parallel-in-one-machine">¶</a>Tensor Parallel in one machine</h2><h3 id="attention"><a class="header-anchor" href="#attention">¶</a>Attention</h3><p>计算量</p><p><img src="/img/attention_tp/Attention.webp" alt="Attention"><br><em>Usually d = hidden_size</em><br>矩阵乘法每个元素为乘加计算，为2个操作<br><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><msub><mi>W</mi><mrow><mi>q</mi><mi>k</mi><mi>v</mi></mrow></msub></mrow><annotation encoding="application/x-tex">XW_{qkv}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mn>3</mn><mo>×</mo><mi>s</mi><mo>×</mo><mi>h</mi><mo>×</mo><mi>h</mi><mo>=</mo><mn>6</mn><mi>B</mi><mi>s</mi><msup><mi>h</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">2 \times B \times 3 \times s \times h \times h = 6Bsh^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord">6</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi><msup><mi>K</mi><mi>T</mi></msup></mrow><annotation encoding="application/x-tex">QK^T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0358em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span></span></span></span>:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mi>s</mi><mo>×</mo><mi>h</mi><mo>×</mo><mi>s</mi><mo>=</mo><mn>2</mn><mi>B</mi><msup><mi>s</mi><mn>2</mn></msup><mi>h</mi></mrow><annotation encoding="application/x-tex">2 \times B \times s \times h \times s = 2Bs^2h</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal">h</span></span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo>=</mo><mi>S</mi><mi>V</mi></mrow><annotation encoding="application/x-tex">P = SV</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span>:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mi>s</mi><mo>×</mo><mi>s</mi><mo>×</mo><mi>h</mi><mo>=</mo><mn>2</mn><mi>B</mi><msup><mi>s</mi><mn>2</mn></msup><mi>h</mi></mrow><annotation encoding="application/x-tex">2 \times B \times s \times s \times h = 2Bs^2h</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal">h</span></span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>o</mi><mi>u</mi><mi>t</mi><mi>p</mi><mi>u</mi><mi>t</mi><mo>=</mo><mi>P</mi><msub><mi>W</mi><mi>o</mi></msub></mrow><annotation encoding="application/x-tex">output = PW_o</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">o</span><span class="mord mathnormal">u</span><span class="mord mathnormal">tp</span><span class="mord mathnormal">u</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">o</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mi>s</mi><mo>×</mo><mi>h</mi><mo>×</mo><mi>h</mi><mo>=</mo><mn>2</mn><mi>B</mi><mi>s</mi><msup><mi>h</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">2 \times B \times s \times h \times h = 2Bsh^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span></p><p>total:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>8</mn><mi>B</mi><mi>s</mi><msup><mi>h</mi><mn>2</mn></msup><mo>+</mo><mn>4</mn><mi>B</mi><msup><mi>s</mi><mn>2</mn></msup><mi>h</mi></mrow><annotation encoding="application/x-tex">\text{FLOP} = 8Bsh^2 + 4Bs^2h</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord">8</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal">h</span></span></span></span></span></p><p>通信量：<br>All-Reduce after attention layer:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>×</mo><mfrac><mn>1</mn><mi>p</mi></mfrac><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi><mo>=</mo><mfrac><mrow><mn>2</mn><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi></mrow><mi>p</mi></mfrac></mrow><annotation encoding="application/x-tex">2 \times (p-1) \times \frac{1}{p} BSHd = \frac{2(p-1)BSHd}{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.2019em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord mathnormal" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3074em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mord mathnormal" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>Prefill阶段Sequence Parallel 是 Reduce-Scatter + All Gather， 通信量和All-Reduce一样</p><p><img src="/img/attention_tp/sequence_parallel.webp" alt="Sequence Parallel"></p><h3 id="mlp-block"><a class="header-anchor" href="#mlp-block">¶</a>MLP Block</h3><p>前后通信方式和Attention一样，故通信量也一样。</p><p><img src="/img/attention_tp/MLP.webp" alt="MLP Tensor Parallel"><br>计算量：<br>升维再降维的操作,设升维到<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi></mrow><annotation encoding="application/x-tex">d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mi>s</mi><mi>h</mi><mi>d</mi><mo>=</mo><mn>2</mn><mi>B</mi><mi>s</mi><mi>h</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">2 \times B \times shd = 2Bshd</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span><span class="mord mathnormal">d</span></span></span></span></span></p><p>升维再降维总量：</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>4</mn><mi>B</mi><mi>s</mi><mi>h</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\text{FLOP}=4Bshd</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span><span class="mord mathnormal">d</span></span></span></span></span></p><h3 id="ffn-in-moe"><a class="header-anchor" href="#ffn-in-moe">¶</a>FFN in MOE</h3><p>前后各一个All-To-All<br>收集Attention结果，得到完整的sequence作为FFN输入，FFN输出分到各rank继续其他层TP执行</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>×</mo><mfrac><mn>1</mn><mi>p</mi></mfrac><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi><mo>=</mo><mfrac><mrow><mn>2</mn><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi></mrow><mi>p</mi></mfrac></mrow><annotation encoding="application/x-tex">2 \times (p-1) \times \frac{1}{p} BSHd = \frac{2(p-1)BSHd}{p}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:2.2019em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3214em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mord mathnormal" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:2.3074em;vertical-align:-0.8804em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.427em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">p</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">2</span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mord mathnormal" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.8804em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p><img src="/img/attention_tp/MOE-Parallel.webp" alt="Sequence Parallel"></p><p>计算量：<br>MOE内部FFN为降维再升维，设降维到<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi></mrow><annotation encoding="application/x-tex">d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>4</mn><mi>B</mi><mi>s</mi><mi>h</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">\text{FLOP}=4Bshd</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span><span class="mord mathnormal">d</span></span></span></span></span></p><h2 id="pipeline-parallel"><a class="header-anchor" href="#pipeline-parallel">¶</a>Pipeline Parallel</h2><p>按层分到各个rank，每个rank负责一部分网络<br>单次rank间通信为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">BSHd</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span></span></span></span>，整体总通信</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">(</mo><mi>p</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>×</mo><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">(p-1) \times BSHd</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span></span></span></span></span></p><p>通信量减少，服务端利用率最大化。<br>每个Request一次在各rank上运行并把输出传到下个rank，相比Tensor Parallel latency增加。</p><p>TP + PP 如 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mi>P</mi><mi>s</mi><mi>i</mi><mi>z</mi><mi>e</mi><mo>=</mo><mn>4</mn></mrow><annotation encoding="application/x-tex">TP size = 4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">TP</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">ze</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">4</span></span></span></span>, <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mi>P</mi><mi>s</mi><mi>i</mi><mi>z</mi><mi>e</mi><mo>=</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">PP size =2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">PP</span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">ze</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span></span></span></span>, 在attention后的All-Reduce可以从 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>0</mn></msub></mrow><annotation encoding="application/x-tex">P_0</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>传到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>P</mi><mn>1</mn></msub></mrow><annotation encoding="application/x-tex">P_1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3011em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，一次的通信量是<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>p</mi><mo>×</mo><mfrac><mrow><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi></mrow><mi>p</mi></mfrac><mo>=</mo><mi>B</mi><mi>S</mi><mi>H</mi><mi>d</mi></mrow><annotation encoding="application/x-tex">p\times \frac{BSHd}{p} = BSHd</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">p</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.3612em;vertical-align:-0.4811em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal mtight" style="margin-right:0.08125em;">H</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.4811em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">BS</span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span></span></span></span></p><h2 id="kv-cache"><a class="header-anchor" href="#kv-cache">¶</a>KV Cache</h2><ul><li>Layer num <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>L</mi></mrow><annotation encoding="application/x-tex">L</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span></li></ul><p>decoder需要获取之前每个step token 的KV，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>s</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup><mo>=</mo><msub><mi>s</mi><mrow><mi>p</mi><mi>r</mi><mi>e</mi><mi>f</mi><mi>i</mi><mi>l</mi><mi>l</mi></mrow></msub><mo>+</mo><msub><mi>s</mi><mrow><mi>d</mi><mi>e</mi><mi>c</mi><mi>o</mi><mi>d</mi><mi>e</mi></mrow></msub></mrow><annotation encoding="application/x-tex">s\rq = s_{prefill}+s_{decode}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7519em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">p</span><span class="mord mathnormal mtight">re</span><span class="mord mathnormal mtight" style="margin-right:0.10764em;">f</span><span class="mord mathnormal mtight">i</span><span class="mord mathnormal mtight" style="margin-right:0.01968em;">ll</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">eco</span><span class="mord mathnormal mtight">d</span><span class="mord mathnormal mtight">e</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></p><p>KV cache size:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mn>2</mn><mo>×</mo><mi>L</mi><mo>×</mo><mi>H</mi><mi>d</mi><mo>×</mo><msup><mi>s</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msup></mrow><annotation encoding="application/x-tex">2 \times L \times Hd \times s\rq</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">L</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.08125em;">H</span><span class="mord mathnormal">d</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8019em;"></span><span class="mord"><span class="mord mathnormal">s</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span></span></span></span></span></p><p>再乘上sizeof(dtype)即可</p><h3 id="常见模型kv-cache-size"><a class="header-anchor" href="#常见模型kv-cache-size">¶</a>常见模型KV cache size</h3><p>Deepseek V3:<br>head size: Compresed 512, Rope k size 64<br>Layer: 61</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mo stretchy="false">(</mo><mn>512</mn><mo>+</mo><mn>64</mn><mo stretchy="false">)</mo><mo>∗</mo><mn>61</mn></mrow><annotation encoding="application/x-tex">(512 + 64) * 61</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">512</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">64</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">∗</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">61</span></span></span></span></span></p><h3 id="计算量："><a class="header-anchor" href="#计算量：">¶</a>计算量：</h3><p>每个step需要计算当前token 的QKV，即<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>s</mi><mo>=</mo><mn>1</mn></mrow><annotation encoding="application/x-tex">s = 1</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1</span></span></span></span><br><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><msub><mi>W</mi><mrow><mi>q</mi><mi>k</mi><mi>v</mi></mrow></msub></mrow><annotation encoding="application/x-tex">XW_{qkv}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3361em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03588em;">q</span><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span><span class="mord mathnormal mtight" style="margin-right:0.03588em;">v</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mn>3</mn><mo>×</mo><mn>1</mn><mo>×</mo><mi>h</mi><mo>×</mo><mi>h</mi><mo>=</mo><mn>6</mn><mi>B</mi><msup><mi>h</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">\text{FLOP} = 2 \times B \times 3 \times 1 \times h \times h = 6Bh^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord">6</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>Q</mi><mi>i</mi></msub><msup><mi>K</mi><mi>T</mi></msup></mrow><annotation encoding="application/x-tex">Q_iK^T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0358em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span></span></span></span>为当前token <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>Q</mi><mi>i</mi></msub></mrow><annotation encoding="application/x-tex">Q_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>和所有<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>K</mi></mrow><annotation encoding="application/x-tex">K</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mn>1</mn><mo>×</mo><mi>h</mi><mo>×</mo><mi>s</mi><mo>=</mo><mn>2</mn><mi>B</mi><mi>s</mi><mi>h</mi></mrow><annotation encoding="application/x-tex">\text{FLOP} = 2 \times B \times 1 \times h \times s = 2Bsh</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span></span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>P</mi><mo>=</mo><mi>S</mi><mi>V</mi></mrow><annotation encoding="application/x-tex">P = SV</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span>:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mn>1</mn><mo>×</mo><mi>s</mi><mo>×</mo><mi>h</mi><mo>=</mo><mn>2</mn><mi>B</mi><mi>s</mi><mi>h</mi></mrow><annotation encoding="application/x-tex">\text{FLOP} = 2 \times B \times 1 \times s \times h = 2Bsh</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">s</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span></span></span></span></span></p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>o</mi><mi>u</mi><mi>t</mi><mi>p</mi><mi>u</mi><mi>t</mi><mo>=</mo><mi>P</mi><msub><mi>W</mi><mi>o</mi></msub></mrow><annotation encoding="application/x-tex">output = PW_o</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8095em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">o</span><span class="mord mathnormal">u</span><span class="mord mathnormal">tp</span><span class="mord mathnormal">u</span><span class="mord mathnormal">t</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">o</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>:</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>2</mn><mo>×</mo><mi>B</mi><mo>×</mo><mn>1</mn><mo>×</mo><mi>h</mi><mo>×</mo><mi>h</mi><mo>=</mo><mn>2</mn><mi>B</mi><msup><mi>h</mi><mn>2</mn></msup></mrow><annotation encoding="application/x-tex">\text{FLOP} =2 \times B \times 1 \times h \times h = 2Bh^2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7778em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8641em;"></span><span class="mord">2</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span></span></span></span></span></p><p>总计算量：</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>FLOP</mtext><mo>=</mo><mn>8</mn><mi>B</mi><msup><mi>h</mi><mn>2</mn></msup><mo>+</mo><mn>4</mn><mi>B</mi><mi>s</mi><mi>h</mi></mrow><annotation encoding="application/x-tex">\text{FLOP} = 8Bh^2 + 4Bsh</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord text"><span class="mord">FLOP</span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9474em;vertical-align:-0.0833em;"></span><span class="mord">8</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal">h</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">4</span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord mathnormal">s</span><span class="mord mathnormal">h</span></span></span></span></span></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;ul&gt;
&lt;li&gt;Batch Size &lt;span class=&quot;katex&quot;&gt;&lt;span class=&quot;katex-mathml&quot;&gt;&lt;math</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>DeepGEMM</title>
    <link href="https://www.jmyjmy.top/2025-02-28_deepgemm/"/>
    <id>https://www.jmyjmy.top/2025-02-28_deepgemm/</id>
    <published>2025-02-28T07:37:21.000Z</published>
    <updated>2025-02-28T07:37:21.000Z</updated>
    
    <content type="html"><![CDATA[<p>Deepseek 一天一开源 根本学不过来。</p><p>fp8 gemm ，使用方法是用JIT，很方便</p><p><strong>exclusively supports NVIDIA Hopper tensor cores.</strong> 我的40系显卡跑不了了。</p><p>参考cutlass但是和cutlass繁重的utils剥离开。只有~300行代码</p><p>竟然还对比cutlass SASS发现黑科技。</p><blockquote><p>We observe a performance improvement in the CUTLASS FP8 kernel between NVCC 12.2 and 12.3. By comparing the compiled SASS, we discover that one bit in a series of FADD instructions is flipped in an interleaving pattern. After referencing some open-source CUDA assembler implementations, we identified that this bit controls yield, which may enhance warp-level parallelism (just a guess, yielding the current warp and let other warps work).</p></blockquote><p>数据使用TMA加速并且和计算overlap。</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// 准备好barrier， full表示有数据可以计算,empty表示算完没用了换下一个</span></span><br><span class="line">Barrier *full_barriers[kNumStages],*empty_barriers[kNumStages]; </span><br><span class="line"><span class="keyword">if</span> (threadIdx.x &gt;= kNumMathThreads) &#123;</span><br><span class="line">    <span class="comment">// 这些thread 负责 copy</span></span><br><span class="line">    empty_barriers[i]-&gt;<span class="built_in">wait</span>();</span><br><span class="line">    <span class="comment">// copy</span></span><br><span class="line">    full_barriers[i]-&gt;<span class="built_in">arrive</span>()</span><br><span class="line"></span><br><span class="line">&#125; <span class="keyword">else</span> &#123;</span><br><span class="line">    <span class="comment">// 这些thread 负责 calc</span></span><br><span class="line">    full_barriers[i]-&gt;<span class="built_in">wait</span>();</span><br><span class="line">    <span class="comment">// calc</span></span><br><span class="line">    empty_barriers[i]-&gt;<span class="built_in">arrive</span>()</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>矩阵计算用<code>WGMMA</code>,tensor core的FFMA指令（矩阵AB+C），这里tensor描述涉及<a href="https://github.com/NVIDIA/cutlass/blob/main/media/docs/cute/01_layout.md">cute layout</a>, 一种加速矩阵运算的<strong>Hierarchy Tensor Layout</strong>，关于layout：<a href="https://dl.acm.org/doi/pdf/10.1145/3582016.3582018">这个论文讲了layout历史</a><br>这种2D layout方便描述大矩阵中切tile。</p><p>一个循环体内最多算4个tile,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>A</mi><mi>i</mi></msub><msub><mi>B</mi><mi>j</mi></msub><mo separator="true">,</mo><msub><mi>A</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub><mo separator="true">,</mo><msub><mi>B</mi><mi>j</mi></msub><mo separator="true">,</mo><msub><mi>A</mi><mi>i</mi></msub><mi>B</mi><mrow><mi>j</mi><mo>+</mo><mn>1</mn></mrow><mo separator="true">,</mo><msub><mi>A</mi><mrow><mi>i</mi><mo>+</mo><mn>1</mn></mrow></msub><mi>B</mi><mrow><mi>j</mi><mo>+</mo><mn>1</mn></mrow></mrow><annotation encoding="application/x-tex">A_iB_j,A_{i+1},B_j,A_iB{j+1},A_{i+1}B{j+1}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0502em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">A</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2083em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span></span></span></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span> (<span class="type">int</span> k = <span class="number">0</span>; k &lt; BLOCK_K / WGMMA::K; ++ k) &#123;</span><br><span class="line">    <span class="keyword">auto</span> desc_a = <span class="built_in">make_smem_desc</span>(smem_a[s] + math_wg_idx * WGMMA::M * BLOCK_K + k * WGMMA::K, <span class="number">1</span>);</span><br><span class="line">    <span class="keyword">auto</span> desc_b = <span class="built_in">make_smem_desc</span>(smem_b[s] + k * WGMMA::K, <span class="number">1</span>);</span><br><span class="line">    WGMMA::<span class="built_in">wgmma</span>(desc_a, desc_b, accum, k);</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// do something</span></span><br><span class="line"><span class="meta">#<span class="keyword">pragma</span> unroll</span></span><br><span class="line"><span class="keyword">for</span> (<span class="type">int</span> i = <span class="number">0</span>; i &lt; WGMMA::kNumAccum / <span class="number">4</span>; ++ i) &#123;</span><br><span class="line">    <span class="type">bool</span> predicate = kMustUseUniformedScaleB <span class="keyword">or</span> i &lt; num_former_iters;</span><br><span class="line">    final_accum[i * <span class="number">4</span> + <span class="number">0</span>] += (predicate ? scale_0_0 : scale_0_1) * accum[i * <span class="number">4</span> + <span class="number">0</span>];</span><br><span class="line">    final_accum[i * <span class="number">4</span> + <span class="number">1</span>] += (predicate ? scale_0_0 : scale_0_1) * accum[i * <span class="number">4</span> + <span class="number">1</span>];</span><br><span class="line">    final_accum[i * <span class="number">4</span> + <span class="number">2</span>] += (predicate ? scale_1_0 : scale_1_1) * accum[i * <span class="number">4</span> + <span class="number">2</span>];</span><br><span class="line">    final_accum[i * <span class="number">4</span> + <span class="number">3</span>] += (predicate ? scale_1_0 : scale_1_1) * accum[i * <span class="number">4</span> + <span class="number">3</span>];</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>wgmma cutlass里的，不同规模都有。<a href="https://github.com/deepseek-ai/DeepGEMM/blob/6c5da03ba9a311b69aaeb3236ceb674e714950c1/deep_gemm/include/deep_gemm/mma_utils.cuh">mma_utils.cuh</a></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;Deepseek 一天一开源 根本学不过来。&lt;/p&gt;
&lt;p&gt;fp8 gemm ，使用方法是用JIT，很方便&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;exclusively supports NVIDIA Hopper tensor cores.&lt;/strong&gt;</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>Multi-head Latent Attention</title>
    <link href="https://www.jmyjmy.top/2025-02-26_multi-latent-attn/"/>
    <id>https://www.jmyjmy.top/2025-02-26_multi-latent-attn/</id>
    <published>2025-02-26T10:03:30.000Z</published>
    <updated>2025-02-26T10:03:30.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="普通multi-head-attention"><a class="header-anchor" href="#普通multi-head-attention">¶</a>普通Multi-head attention</h2><p><img src="/img/mla/attn.webp" alt="attention"></p><h2 id="mla-multi-head-latent-attention-省略掉scale-mask等。"><a class="header-anchor" href="#mla-multi-head-latent-attention-省略掉scale-mask等。">¶</a>MLA(Multi-head Latent Attention) 省略掉scale mask等。</h2><p>可以看到QKV前都做了一次降维<br><img src="/img/mla/MLA.webp" alt="MLA"></p><h2 id="具体训练网络："><a class="header-anchor" href="#具体训练网络：">¶</a>具体训练网络：</h2><p>因为K不能直接加ROPE，所以这里额外加一部分不压缩的，可以加ROPE的维度，拼成一个完整的QK。Q只是降维再升维，马甲脱了再穿还是它。<br>为什么不能加ROPE看下面推理过程。（训练网络拆解示意图，非最终代码实现）<br><img src="/img/mla/mla-train.webp" alt="mla training "></p><h2 id="推理过程优化："><a class="header-anchor" href="#推理过程优化：">¶</a>推理过程优化：</h2><p><img src="/img/mla/mla-infer.webp" alt="mla inference"><br>在代码中<code>compressed_kv</code>和未加rope的k <code>k_pe</code> 在一个<code>Linear</code>合并计算然后split。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">compressed_kv = self.kv_a_proj_with_mqa(hidden_states)</span><br><span class="line">compressed_kv, k_pe = torch.split(</span><br><span class="line">    compressed_kv, [self.kv_lora_rank, self.qk_rope_head_dim], dim=-<span class="number">1</span></span><br><span class="line">)</span><br><span class="line">compressed_kv = self.kv_a_layernorm(compressed_kv)</span><br><span class="line">k_pe = k_pe.view(bsz, q_len, <span class="number">1</span>, self.qk_rope_head_dim).transpose(<span class="number">1</span>, <span class="number">2</span>)</span><br></pre></td></tr></table></figure><p>K和V的权重位置跑掉了，原本的<code>K V cache</code> 变成<code>compressed latent vector</code>。Q也变了，降维的Q后面乘了Q的权重和K的权重。QK的K变成了<code>compressed latent vector</code>,SV的V也是<code>compressed latent vector</code>，而且最后output还乘了个V的权重</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>Q</mi><mo>=</mo><mi>X</mi><msub><mi>W</mi><mi>Q</mi></msub><mspace linebreak="newline"></mspace><mi>K</mi><mo>=</mo><msub><mi>C</mi><mi>T</mi></msub><msub><mi>W</mi><mi>K</mi></msub><mspace linebreak="newline"></mspace><mi>V</mi><mo>=</mo><msub><mi>C</mi><mi>T</mi></msub><msub><mi>W</mi><mi>V</mi></msub><mspace linebreak="newline"></mspace><mi>Q</mi><msup><mi>K</mi><mi>T</mi></msup><mo>=</mo><mo stretchy="false">(</mo><mi>X</mi><msub><mi>W</mi><mi>Q</mi></msub><mo stretchy="false">)</mo><mo stretchy="false">(</mo><msub><mi>C</mi><mi>T</mi></msub><msub><mi>W</mi><mi>K</mi></msub><msup><mo stretchy="false">)</mo><mi>T</mi></msup><mo>=</mo><mo stretchy="false">(</mo><mi>X</mi><msub><mi>W</mi><mi>Q</mi></msub><msubsup><mi>W</mi><mi>K</mi><mi>T</mi></msubsup><mo stretchy="false">)</mo><msub><mi>C</mi><mi>T</mi></msub><mspace linebreak="newline"></mspace></mrow><annotation encoding="application/x-tex">Q = XW_Q \\K = C_TW_K \\V = C_TW_V \\QK^T = (XW_Q)(C_TW_K)^T = (XW_QW_K^T)C_T \\</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">Q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">V</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:1.0858em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1774em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">Q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.1774em;vertical-align:-0.2861em;"></span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">Q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.453em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="mspace newline"></span></span></span></span></p><p><img src="/img/mla/why_no_rope.webp" alt="正常加ROPE"></p><p>这里<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span> 表示降维后的KV，论文中的<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>C</mi><mi>t</mi></msub></mrow><annotation encoding="application/x-tex">C_t</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.2806em;"><span style="top:-2.55em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">t</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>W</mi><mi>K</mi></msub></mrow><annotation encoding="application/x-tex">W_K</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span>是把降维的K升维的权重。推理过程中把 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>C</mi></mrow><annotation encoding="application/x-tex">C</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span></span></span></span> 存入cache， 合并计算 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo stretchy="false">(</mo><msub><mi>W</mi><mi>Q</mi></msub><msubsup><mi>W</mi><mi>K</mi><mi>T</mi></msubsup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">X(W_QW_K^T)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1274em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">Q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-2.4247em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span> 。这样和QK是等效的，同理，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo>=</mo><mi>S</mi><mi>V</mi></mrow><annotation encoding="application/x-tex">O=SV</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span> 也变成了 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo>=</mo><mi>S</mi><mo stretchy="false">(</mo><mi>C</mi><msub><mi>W</mi><mi>V</mi></msub><mo stretchy="false">)</mo><mo>=</mo><mi>S</mi><mi>C</mi><msub><mi>W</mi><mi>V</mi></msub></mrow><annotation encoding="application/x-tex">O = S(CW_V) = SCW_V</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07153em;">C</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">V</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">SC</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">V</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span> ，然而直接把C当成K计算，<strong>移走了<code>W_k</code>，矩阵乘法不满足交换律</strong>，C上没法加ROPE了，要加就得乘回<code>W_k</code>，所以训练就单独加一点普通的QK用来加ROPE。<br>这样推理时Cache的东西就只有<code>compressed latent vector</code>和rope(K)，相比KV cache很少，但是计算的就多了。decode阶段是访存瓶颈，所以依然有很大收益</p><p><img src="/img/mla/why_no_rope_mla.webp" alt="MLA中的ROPE"></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">kv_b_proj = self.kv_b_proj.weight.view(self.num_heads, -<span class="number">1</span>, self.kv_lora_rank)</span><br><span class="line">q_absorb = kv_b_proj[:, :self.qk_nope_head_dim, :] <span class="comment"># Linear K</span></span><br><span class="line">out_absorb = kv_b_proj[:, self.qk_nope_head_dim:, :] <span class="comment"># Linear V</span></span><br><span class="line"></span><br><span class="line">q_nope = torch.matmul(q_nope, q_absorb) <span class="comment"># 吸收 Linear K</span></span><br><span class="line">attn_weights = (torch.matmul(q_pe, k_pe.mT) +</span><br><span class="line">                torch.matmul(q_nope, compressed_kv.unsqueeze(-<span class="number">3</span>).mT)) * self.softmax_scale</span><br><span class="line"><span class="comment"># 没有concat，直接相加，数学等价，减少显存</span></span><br></pre></td></tr></table></figure><p>计算QK时(代码里是<code>attn_weights</code>)，先计算<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><msub><mi>W</mi><mi>Q</mi></msub></mrow><annotation encoding="application/x-tex">XW_Q</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">Q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span> <code>q_nope</code> 后乘 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>W</mi><mi>K</mi><mi>T</mi></msubsup></mrow><annotation encoding="application/x-tex">W_K^T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1167em;vertical-align:-0.2753em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-2.4247em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span></span></span></span> <code>torch.matmul(q_nope, q_absorb)</code>， 而不是离线算好 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>W</mi><mi>Q</mi></msub><msubsup><mi>W</mi><mi>K</mi><mi>T</mi></msubsup></mrow><annotation encoding="application/x-tex">W_QW_K^T</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.1274em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">Q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-2.4247em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2753em;"><span></span></span></span></span></span></span></span></span></span>，因为分开计算量更小</p><h2 id="reference"><a class="header-anchor" href="#reference">¶</a>Reference</h2><ul><li><a href="https://github.com/deepseek-ai/DeepSeek-VL2/blob/main/deepseek_vl2/models/modeling_deepseek.py">modeling_deepseek.py</a></li><li><a href="https://github.com/deepseek-ai/DeepSeek-V3/blob/main/DeepSeek_V3.pdf">Deepseek V3</a></li><li><a href="https://kexue.fm/archives/10091">缓存与效果的极限拉扯：从MHA、MQA、GQA到MLA</a></li><li><a href="https://zhuanlan.zhihu.com/p/16730036197">deepseek技术解读</a></li></ul>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;普通multi-head-attention&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#普通multi-head-attention&quot;&gt;¶&lt;/a&gt;普通Multi-head attention&lt;/h2&gt;
&lt;p&gt;&lt;img</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>AI应该是啥样的</title>
    <link href="https://www.jmyjmy.top/2025-02-13_AGI_hows_it_like/"/>
    <id>https://www.jmyjmy.top/2025-02-13_AGI_hows_it_like/</id>
    <published>2025-02-13T15:51:55.000Z</published>
    <updated>2025-02-13T15:51:55.000Z</updated>
    
    <content type="html"><![CDATA[<p>曾经以为AI是永远能做对的选择，每当我们有疑问，它便能给出精准答案；每当我们有任务，它便能圆满完成。然而仔细想想，我意识到这不过是理想化的愿景，无法训练出一个永远做正确选择的东西。很多时候并不存在绝对的正确答案。人们想追求的高级的人工智能实际上是希望它足够拟人，然而，即便是人类，也难免犯错。<br>人是如何学习的？实际上是靠大脑的记忆能力。那些聪明的学生，每次都能考高分，实际上他们的记性也是非常好的。人工智能的训练也是一样，通过不断的灌数据去拟合，从而达到记忆的效果，然后程序再通过这些记忆来得出一个答案。相较于人类，人工智能在记忆容量和运算速度上拥有显著优势。它能够整合互联网上浩如烟海的知识，形成远超任何个体的知识库。<br>然而，人类的学习过程并非仅仅依赖于结构化的知识积累。我们从出生到成长，经历了无数次的尝试、思考和感悟。这些非结构化的数据，如情感、经历、直觉等，构成了我们独特的个体特征。那么，如何让人工智能学习这些非结构化的数据呢？<br>我想一个可能的途径是将所有数据转化为图像形式进行输入。因为人类无论是写字、阅读、画画还是演奏，都是通过视觉来感知和理解的。这些信息在大脑中实际上是以图像的形式存储的。因此，将所有数据转化为像素输入给人工智能程序，或许能够使其更好地理解和学习。所以，到底还是人类的算力不支持这么玩吧。<br>另外，人类大脑实际上是一边输出的同时也在输入，即“在线更新”。Deepseek使用think的方式可以当成有一个草稿纸，就像人说话的时候也会参考已经说了的话来组织后面的语言。AI的下一个突破可以是“在线更新”，一边forward 一边 backward，这个回答我不满意那么模型立即更新权重来降低这个答案的分数。这又有点像推荐系统了，果然还得是搜广推啊。Test-Time-Train (TTT)架构是做这个的但是没有广泛用起来。倒是彭博新发的<a href="https://github.com/BlinkDL/RWKV-LM/tree/main/RWKV-v7">RWKV7</a>改进了这个TTT架构。</p><table><thead><tr><th style="text-align:center">当前AI的模式</th><th style="text-align:center">可能的技术突破方向</th></tr></thead><tbody><tr><td style="text-align:center">输入文字，图像，音频</td><td style="text-align:center">结合具身机器人增加更多模态输入</td></tr><tr><td style="text-align:center">输入结构化数据</td><td style="text-align:center">多模态任意形式数据输入</td></tr><tr><td style="text-align:center">离线训练</td><td style="text-align:center">在线持续训练</td></tr></tbody></table>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;曾经以为AI是永远能做对的选择，每当我们有疑问，它便能给出精准答案；每当我们有任务，它便能圆满完成。然而仔细想想，我意识到这不过是理想化的愿景，无法训练出一个永远做正确选择的东西。很多时候并不存在绝对的正确答案。人们想追求的高级的人工智能实际上是希望它足够拟人，然而，即便是</summary>
        
      
    
    
    
    <category term="Think" scheme="https://www.jmyjmy.top/categories/Think/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>Chrome开启HDR时屏幕截图时亮度过高</title>
    <link href="https://www.jmyjmy.top/2024-12-09_chrome-screen-capture-is-overly-bright/"/>
    <id>https://www.jmyjmy.top/2024-12-09_chrome-screen-capture-is-overly-bright/</id>
    <published>2024-12-09T01:21:34.000Z</published>
    <updated>2024-12-09T01:21:34.000Z</updated>
    
    <content type="html"><![CDATA[<p>系统开启HDR的时候Chrome的颜色也是HDR10的，但是截图的时候就会变成很亮的，解决方法就是进<a href="chrome://flags/#force-color-profile">设置 chrome://flags/#force-color-profile</a>里面颜色改成sRGB。但是改了sRGB以后就看不了HDR视频了。</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;系统开启HDR的时候Chrome的颜色也是HDR10的，但是截图的时候就会变成很亮的，解决方法就是进&lt;a href=&quot;chrome://flags/#force-color-profile&quot;&gt;设置</summary>
        
      
    
    
    
    
  </entry>
  
  <entry>
    <title>Attention Tensor Parallel</title>
    <link href="https://www.jmyjmy.top/2024-10-30_attention-tensor-parallel/"/>
    <id>https://www.jmyjmy.top/2024-10-30_attention-tensor-parallel/</id>
    <published>2024-10-30T00:05:55.000Z</published>
    <updated>2024-10-30T00:05:55.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="普通的attention"><a class="header-anchor" href="#普通的attention">¶</a>普通的Attention</h2><p><img src="/img/attention_tp/Attention.webp" alt=""></p><h2 id="tensor-parallel-attention"><a class="header-anchor" href="#tensor-parallel-attention">¶</a>Tensor Parallel Attention</h2><p>TP size = 4</p><p><img src="/img/attention_tp/Attention_TP.webp" alt="Tensor Parallel, TP size = 4"></p><p><code>Linear_QKV</code>的<code>out_channel</code>变成<code>dim / tp_size</code>, <code>Linear_out</code> 的 <code>in_channel</code>变成<code>dim / tp_size</code>，<code>out_channel</code>还是<code>hidden_size</code>，最后输出的shape是<code>[seq_len, hidden_size]</code>， 因为<code>Linear_out</code> 切的是“累加维度”，所以需要All-Reduce加起来是完整的output</p><h2 id="sequence-parallel"><a class="header-anchor" href="#sequence-parallel">¶</a>Sequence Parallel</h2><p><img src="/img/attention_tp/sequence_parallel.webp" alt="Sequence Parallel"></p><p>All-Reduce = Reduce-Scatter + All-Gather 。 通信量一样</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mfrac><mrow><mi>s</mi><mi>e</mi><mi>q</mi><mtext> </mtext><mi>l</mi><mi>e</mi><mi>n</mi><mi>g</mi><mi>t</mi><mi>h</mi><mo>×</mo><mi>h</mi><mi>i</mi><mi>d</mi><mi>d</mi><mi>e</mi><mi>n</mi><mtext> </mtext><mi>s</mi><mi>i</mi><mi>z</mi><mi>e</mi></mrow><mn>4</mn></mfrac><mo>×</mo><mn>3</mn><mo>×</mo><mn>2</mn></mrow><annotation encoding="application/x-tex">\frac{seq\ length \times hidden\ size}{4} \times 3 \times 2 </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.0574em;vertical-align:-0.686em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3714em;"><span style="top:-2.314em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord">4</span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">se</span><span class="mord mathnormal" style="margin-right:0.03588em;">q</span><span class="mspace"> </span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mord mathnormal">t</span><span class="mord mathnormal">h</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal">hi</span><span class="mord mathnormal">dd</span><span class="mord mathnormal">e</span><span class="mord mathnormal">n</span><span class="mspace"> </span><span class="mord mathnormal">s</span><span class="mord mathnormal">i</span><span class="mord mathnormal">ze</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.686em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">2</span></span></span></span></span></p><p>Reduce-Scatter 后，每个卡都有部分sequce，但是已经累加好了，此时可以进行sequence并行计算add, layernorm等。算好后再All-Gather，使每个卡都持有完整的结果，进入下一layer的attention或者MLP</p><p>MLP的Tensor parallel 的输入输出和Attention一样，都是完整的输入，输出需要累加</p><p><img src="/img/attention_tp/MLP.webp" alt="MLP Tensor Parallel"></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;普通的attention&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#普通的attention&quot;&gt;¶&lt;/a&gt;普通的Attention&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/img/attention_tp/Attention.webp&quot;</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>成都</title>
    <link href="https://www.jmyjmy.top/2024-09-20_cheng-du/"/>
    <id>https://www.jmyjmy.top/2024-09-20_cheng-du/</id>
    <published>2024-09-20T07:02:39.000Z</published>
    <updated>2024-09-20T07:02:39.000Z</updated>
    
    <content type="html"><![CDATA[<p>到成都肯定得去杜甫草堂。<br>杜甫草堂里面很大，南面是个公园，北面是省博物馆。里面有一些活动和情景表演，去的时候是中秋节，有表演投壶的，说书的。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chengdu/0.webp","alt":""},{"url":"/img/chengdu/1.webp","alt":"说书"},{"url":"/img/chengdu/2.webp","alt":"投壶"},{"url":"/img/chengdu/3.webp","alt":"投壶"},{"url":"/img/chengdu/4.webp","alt":""},{"url":"/img/chengdu/5.webp","alt":""},{"url":"/img/chengdu/6.webp","alt":""},{"url":"/img/chengdu/7.webp","alt":""},{"url":"/img/chengdu/8.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>又去了宽窄巷子，密密麻麻的小商铺大致分三类：喝茶看变脸，大熊猫周边，奶茶咖啡店书店<br><img src="/img/chengdu/13.webp" alt="宽巷子窄巷子"><br><img src="/img/chengdu/14.webp" alt="五粮液冰淇淋"><br><img src="/img/chengdu/12.webp" alt="做了个扇子，我觉得很好看"></p><p>晚上去东郊记忆逛了逛，这里是个废弃的工厂重新开发成文创园区，类似上海的老厂坊<br><img src="/img/chengdu/26.webp" alt="老火车头"></p><p>太古里也都是熊猫</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chengdu/9.webp","alt":""},{"url":"/img/chengdu/10.webp","alt":""},{"url":"/img/chengdu/11.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>起个大早去大熊猫基地看熊猫</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chengdu/17.webp","alt":""},{"url":"/img/chengdu/16.webp","alt":""},{"url":"/img/chengdu/15.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>在川剧院看的“芙蓉国粹”这个不错，比较全的展示了变脸，杂技，云锦等国粹</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chengdu/18.webp","alt":""},{"url":"/img/chengdu/19.webp","alt":""},{"url":"/img/chengdu/20.webp","alt":""},{"url":"/img/chengdu/21.webp","alt":""},{"url":"/img/chengdu/22.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>中秋节了，太古里上的圆月<br><img src="/img/chengdu/23.webp" alt=""></p><p>起飞<br><img src="/img/chengdu/24.webp" alt="成都上空"></p><p><img src="/img/chengdu/25.webp" alt="飞机餐"></p><p><video src='/img/chengdu/video_20240916_092000.mp4' type='video/mp4' controls='controls'  width='100%' height='100%' muted preload='none' poster=''></video><br><video src='/img/chengdu/video_20240916_165542.mp4' type='video/mp4' controls='controls'  width='100%' height='100%' muted preload='none' poster=''></video><br><video src='/img/chengdu/video_20240916_165629.mp4' type='video/mp4' controls='controls'  width='100%' height='100%' muted preload='none' poster=''></video></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;到成都肯定得去杜甫草堂。&lt;br&gt;
杜甫草堂里面很大，南面是个公园，北面是省博物馆。里面有一些活动和情景表演，去的时候是中秋节，有表演投壶的，说书的。&lt;/p&gt;
&lt;div class=&quot;gallery&quot;&gt;
    &lt;div class=&quot;fj-gallery  data&quot;</summary>
        
      
    
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/categories/Travel/"/>
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/tags/Travel/"/>
    
  </entry>
  
  <entry>
    <title>宁波 象山</title>
    <link href="https://www.jmyjmy.top/2024-08-22_xiang-shan/"/>
    <id>https://www.jmyjmy.top/2024-08-22_xiang-shan/</id>
    <published>2024-08-22T06:01:13.000Z</published>
    <updated>2024-08-22T06:01:13.000Z</updated>
    
    <content type="html"><![CDATA[<p>去了象山南部的一个小岛，<strong>东门岛</strong>，去了岛上的妈祖像、海神庙，沿着海边栈道走了一圈后上山，刚好在山顶看日落。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/xiangshan/0.webp","alt":""},{"url":"/img/xiangshan/1.webp","alt":""},{"url":"/img/xiangshan/2.webp","alt":""},{"url":"/img/xiangshan/3.webp","alt":""},{"url":"/img/xiangshan/4.webp","alt":""},{"url":"/img/xiangshan/5.webp","alt":""},{"url":"/img/xiangshan/6.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>晚上在<strong>中国渔村</strong>的海边吃个海鲜大排档，大虾真的很大。<br><img src="/img/xiangshan/12.webp" alt="海肠，蛏子,蚝"><br>这里早上看日出和晚上6点以后不要门票。<br>第二天早上看了日出，趁着门卫没上班去<strong>松兰山</strong>转了一圈（9点保安上班再进就要收费了），但是实在太热了，海边沙滩根本无法生存，尽管白沙滩真的沙子又细又白。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/xiangshan/7.webp","alt":""},{"url":"/img/xiangshan/11.webp","alt":""},{"url":"/img/xiangshan/8.webp","alt":""},{"url":"/img/xiangshan/9.webp","alt":""},{"url":"/img/xiangshan/10.webp","alt":""},{"url":"/img/xiangshan/13.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;去了象山南部的一个小岛，&lt;strong&gt;东门岛&lt;/strong&gt;，去了岛上的妈祖像、海神庙，沿着海边栈道走了一圈后上山，刚好在山顶看日落。&lt;/p&gt;
&lt;div class=&quot;gallery&quot;&gt;
    &lt;div class=&quot;fj-gallery  data&quot;</summary>
        
      
    
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/categories/Travel/"/>
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/tags/Travel/"/>
    
  </entry>
  
  <entry>
    <title>南浔古镇</title>
    <link href="https://www.jmyjmy.top/2024-08-12_nan-xun-gu-zhen/"/>
    <id>https://www.jmyjmy.top/2024-08-12_nan-xun-gu-zhen/</id>
    <published>2024-08-12T08:49:22.000Z</published>
    <updated>2024-08-12T08:49:22.000Z</updated>
    
    <content type="html"><![CDATA[<p>南浔在湖州市南浔区，地处江浙两省交界处，旁边挨着苏州（没想到苏州这么大）</p><p>南浔古镇也很大，走得很累。从南门进去一直走到里面跟着小河拐个弯。</p><p>这里是京杭运河的一段，所以古时候这里是靠盐商发展起来的，里面很多宅子，桥，设施都和盐商有关。</p><p>这一天又走了2.1w步…</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/nan-xun/0.webp","alt":""},{"url":"/img/nan-xun/1.webp","alt":""},{"url":"/img/nan-xun/2.webp","alt":""},{"url":"/img/nan-xun/3.webp","alt":""},{"url":"/img/nan-xun/4.webp","alt":""},{"url":"/img/nan-xun/5.webp","alt":""},{"url":"/img/nan-xun/6.webp","alt":""},{"url":"/img/nan-xun/7.webp","alt":""},{"url":"/img/nan-xun/8.webp","alt":""},{"url":"/img/nan-xun/9.webp","alt":""},{"url":"/img/nan-xun/10.webp","alt":""},{"url":"/img/nan-xun/11.webp","alt":""},{"url":"/img/nan-xun/12.webp","alt":""},{"url":"/img/nan-xun/13.webp","alt":""},{"url":"/img/nan-xun/14.webp","alt":""},{"url":"/img/nan-xun/15.webp","alt":""},{"url":"/img/nan-xun/17.webp","alt":""},{"url":"/img/nan-xun/18.webp","alt":""},{"url":"/img/nan-xun/19.webp","alt":""},{"url":"/img/nan-xun/20.webp","alt":""},{"url":"/img/nan-xun/21.webp","alt":""},{"url":"/img/nan-xun/22.webp","alt":""},{"url":"/img/nan-xun/23.webp","alt":""},{"url":"/img/nan-xun/24.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;南浔在湖州市南浔区，地处江浙两省交界处，旁边挨着苏州（没想到苏州这么大）&lt;/p&gt;
&lt;p&gt;南浔古镇也很大，走得很累。从南门进去一直走到里面跟着小河拐个弯。&lt;/p&gt;
&lt;p&gt;这里是京杭运河的一段，所以古时候这里是靠盐商发展起来的，里面很多宅子，桥，设施都和盐商有关。&lt;/p&gt;
&lt;p</summary>
        
      
    
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/categories/Travel/"/>
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/tags/Travel/"/>
    
  </entry>
  
  <entry>
    <title>Docker squash</title>
    <link href="https://www.jmyjmy.top/2024-08-04_docker-squash/"/>
    <id>https://www.jmyjmy.top/2024-08-04_docker-squash/</id>
    <published>2024-08-04T04:38:09.000Z</published>
    <updated>2024-08-04T04:38:09.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="background"><a class="header-anchor" href="#background">¶</a>Background</h2><p>docker squash 通过merge所有layer从而减小docker image的体积，得到一个“所见即所得”的镜像。<br>缺点是这样就用不了layer cache了，并且会产生一个很大的最终layer。</p><p>曾经docker build有一个<code>--squash</code>选项，是experimental的。最近用的时候发现没了。于是查了一下怎么个事。</p><p><a href="https://github.com/docker/buildx/issues/1287">Issue - Better documentation for “squash”</a><br><a href="https://docs.docker.com/reference/cli/docker/build-legacy/#squash">docker build (legacy builder)</a></p><p>这个实验性的功能最终是被删除了。因为docker fs的兼容问题，这个功能无法在各种fs上普及。</p><blockquote><p>No plans atm. Squash was never taken out of experimental and is only supported in moby outside the builder component. You should squash layers with a multi-stage dockerfile(if you are sure you know what you are doing and need to squash at all).</p></blockquote><h2 id="multistage-dockerfile实现squash"><a class="header-anchor" href="#multistage-dockerfile实现squash">¶</a>Multistage dockerfile实现squash</h2><p>正确姿势应该是使用multi-stage dockerfile</p><p>先贴代码：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#!/bin/sh</span></span><br><span class="line"><span class="comment">################################################################################</span></span><br><span class="line"><span class="comment"># The setups in this file belong to https://code.shin.company/docker-squash</span></span><br><span class="line"><span class="comment"># I appreciate you respecting my intellectual efforts in creating them.</span></span><br><span class="line"><span class="comment"># If you intend to copy or use ideas from this project, please credit properly.</span></span><br><span class="line"><span class="comment"># Author:  SHIN Company &lt;shin@shin.company&gt;</span></span><br><span class="line"><span class="comment"># License: https://code.shin.company/docker-squash/blob/main/LICENSE</span></span><br><span class="line"><span class="comment">################################################################################</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Check if Docker is installed, if not exit</span></span><br><span class="line"><span class="keyword">if</span> [ ! -x <span class="string">&quot;<span class="subst">$(command -v docker)</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;Docker is not installed. Please install Docker and try again.&quot;</span> &gt;&amp;2</span><br><span class="line">    <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># HELPER FUNCTIONS</span></span><br><span class="line"><span class="comment">################################################################################</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">usage</span></span>() &#123;</span><br><span class="line">    <span class="built_in">cat</span> &lt;&lt;<span class="string">EOF</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">Combines Docker image layers into a single layer, reducing storage space</span></span><br><span class="line"><span class="string">and improving runtime performance by decreasing mount points.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">Usage: $&#123;0##*/&#125; &lt;source_image&gt; [build_options]</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">  Arguments:</span></span><br><span class="line"><span class="string">    source_image   The original image ID or name:tag to be squashed.</span></span><br><span class="line"><span class="string">                   An absolute path to your Dockerfile can also be used.</span></span><br><span class="line"><span class="string">    build_options  Optional Docker build options like --build-arg, --label, etc.</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">Author:  SHIN Company &lt;shin@shin.company&gt;</span></span><br><span class="line"><span class="string">License: https://code.shin.company/docker-squash/blob/main/LICENSE</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">EOF</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">upgrade</span></span>() &#123;</span><br><span class="line">    <span class="built_in">local</span> install=/usr/local/bin/docker-squash.sh</span><br><span class="line">    sudo curl -L https://github.com/shinsenter/docker-squash/raw/main/docker-squash.sh \</span><br><span class="line">        -o <span class="variable">$install</span> &amp;&amp; <span class="built_in">chmod</span> +x <span class="variable">$install</span> &amp;&amp; <span class="variable">$install</span> -h</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">docker_tag_id</span></span>() &#123;</span><br><span class="line">    docker images --format <span class="string">&#x27;&#123;&#123;.Repository&#125;&#125;:&#123;&#123;.Tag&#125;&#125;\t&#123;&#123;.ID&#125;&#125;&#x27;</span> 2&gt;/dev/null | grep -wi <span class="string">&quot;<span class="variable">$@</span>&quot;</span> | <span class="built_in">sort</span> | <span class="built_in">head</span> -n1</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">docker_config</span></span>() &#123;</span><br><span class="line">    docker image inspect --format=<span class="string">&#x27;&#123;&#123;json .Config&#125;&#125;&#x27;</span> <span class="string">&quot;<span class="variable">$1</span>&quot;</span> | <span class="built_in">tr</span> -d <span class="string">&#x27;[:cntrl:]&#x27;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">parse_config</span></span>() &#123;</span><br><span class="line">    <span class="built_in">local</span> <span class="built_in">id</span>=<span class="string">&quot;<span class="variable">$1</span>&quot;</span>; <span class="built_in">shift</span>; docker_config <span class="string">&quot;<span class="variable">$id</span>&quot;</span> | jq -r <span class="string">&quot;<span class="variable">$@</span>&quot;</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">get_name</span></span>()        &#123; docker_tag_id <span class="string">&quot;<span class="variable">$1</span>&quot;</span> | awk <span class="string">&#x27;&#123;printf $1&#125;&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_id</span></span>()          &#123; docker_tag_id <span class="string">&quot;<span class="variable">$1</span>&quot;</span> | awk <span class="string">&#x27;&#123;printf $2&#125;&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_labels</span></span>()      &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.Labels // empty|to_entries|map(&quot;LABEL \(.key)=\&quot;\(.value)\&quot;&quot;)|.[]&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_shell</span></span>()       &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.Shell // empty|@json&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_envs</span></span>()        &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.Env // empty|map(gsub(&quot;\\\\&quot;; &quot;\\\\\\\\&quot;))|sort|.[]|capture(&quot;(?&lt;key&gt;[^=]+)=(?&lt;value&gt;.*)&quot;)|&quot;ENV \(.key)=\&quot;\(.value)\&quot;&quot;&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_onbuilds</span></span>()    &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.OnBuild // empty|map(&quot;ONBUILD \(.)&quot;)|.[]&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_exposes</span></span>()     &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.ExposedPorts // empty|keys|map(&quot;EXPOSE \(.)&quot;)|.[]&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_workdir</span></span>()     &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.WorkingDir // empty&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_user</span></span>()        &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.User // empty&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_volumes</span></span>()     &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.Volumes // empty|keys|map(&quot;VOLUME \&quot;\(.)\&quot;&quot;)|sort|.[]&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_entrypoint</span></span>()  &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.Entrypoint // empty|@json&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_cmd</span></span>()         &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.Cmd // empty|@json&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_stopsignal</span></span>()  &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.StopSignal // empty&#x27;</span>; &#125;</span><br><span class="line"><span class="function"><span class="title">get_healthcheck</span></span>() &#123; parse_config <span class="string">&quot;<span class="variable">$1</span>&quot;</span> <span class="string">&#x27;.Healthcheck // empty|(</span></span><br><span class="line"><span class="string">    (if .Interval    then &quot;--interval=&quot;+(.Interval|tonumber/1000000000|tostring)+&quot;s &quot; else &quot;&quot; end) +</span></span><br><span class="line"><span class="string">    (if .Timeout     then &quot;--timeout=&quot;+(.Timeout|tonumber/1000000000|tostring)+&quot;s &quot; else &quot;&quot; end) +</span></span><br><span class="line"><span class="string">    (if .StartPeriod then &quot;--start-period=&quot;+(.StartPeriod|tonumber/1000000000|tostring)+&quot;s &quot; else &quot;&quot; end) +</span></span><br><span class="line"><span class="string">    (if .StartInterval then &quot;--start-interval=&quot;+(.StartInterval|tonumber/1000000000|tostring)+&quot;s &quot; else &quot;&quot; end) +</span></span><br><span class="line"><span class="string">    (if .Retries    then &quot;--retries=&quot;+(.Retries|tostring)+&quot; &quot; else &quot;&quot; end) +</span></span><br><span class="line"><span class="string">    (.Test[0]|sub(&quot;-SHELL&quot;;&quot;&quot;)) + &quot; &quot; + .Test[1]</span></span><br><span class="line"><span class="string">)&#x27;</span>; &#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">generate</span></span>() &#123;</span><br><span class="line">    <span class="built_in">local</span> <span class="built_in">id</span>=<span class="string">&quot;<span class="subst">$(get_id <span class="string">&quot;<span class="variable">$1</span>&quot;</span>)</span>&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$id</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;Invalid docker image: <span class="variable">$1</span>. Please build or pull the image first.&quot;</span> &gt;&amp;2</span><br><span class="line">        <span class="built_in">exit</span> 1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">local</span> base=<span class="string">&quot;scratch&quot;</span></span><br><span class="line">    <span class="built_in">local</span> <span class="built_in">alias</span>=<span class="string">&quot;temp-<span class="variable">$id</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> tag=<span class="string">&quot;<span class="subst">$(get_name <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> labels=<span class="string">&quot;<span class="subst">$(get_labels <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> shell=<span class="string">&quot;<span class="subst">$(get_shell <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> envs=<span class="string">&quot;<span class="subst">$(get_envs <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> onbuilds=<span class="string">&quot;<span class="subst">$(get_onbuilds <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> exposes=<span class="string">&quot;<span class="subst">$(get_exposes <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> workdir=<span class="string">&quot;<span class="subst">$(get_workdir <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> user=<span class="string">&quot;<span class="subst">$(get_user <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> volumes=<span class="string">&quot;<span class="subst">$(get_volumes <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> entrypoint=<span class="string">&quot;<span class="subst">$(get_entrypoint <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> cmd=<span class="string">&quot;<span class="subst">$(get_cmd <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> stopsignal=<span class="string">&quot;<span class="subst">$(get_stopsignal <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line">    <span class="built_in">local</span> healthcheck=<span class="string">&quot;<span class="subst">$(get_healthcheck <span class="string">&quot;<span class="variable">$id</span>&quot;</span>)</span>&quot;</span></span><br><span class="line"></span><br><span class="line">    awk NF &lt;&lt;<span class="string">Dockerfile</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">################################################################################</span></span><br><span class="line"><span class="string"># Base image: $tag (Image ID: $id)</span></span><br><span class="line"><span class="string"># Created at: $(date -u +&quot;%Y-%m-%dT%H:%M:%SZ&quot;)</span></span><br><span class="line"><span class="string"># Created by: https://code.shin.company/docker-squash</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">################################################################################</span></span><br><span class="line"><span class="string"># CLEANING UP THE SOURCE IMAGE. ################################################</span></span><br><span class="line"><span class="string"># Enable SBOM attestations</span></span><br><span class="line"><span class="string"># See: https://docs.docker.com/build/attestations/sbom/</span></span><br><span class="line"><span class="string">ARG BUILDKIT_SBOM_SCAN_CONTEXT=true</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">FROM $tag AS $alias</span></span><br><span class="line"><span class="string">ARG  BUILDKIT_SBOM_SCAN_STAGE=true</span></span><br><span class="line"><span class="string"># Pre-squash scripts may be useful to clean the source image before squashing.</span></span><br><span class="line"><span class="string"># Use build argument to add your pre-squash scripts, and run them in this stage.</span></span><br><span class="line"><span class="string"># Example:</span></span><br><span class="line"><span class="string">#   $&#123;0##*/&#125; $tag --build-arg PRESQUASH_SCRIPTS=&quot;rm -rf /tmp/*&quot;</span></span><br><span class="line"><span class="string">#   $&#123;0##*/&#125; $tag --build-arg PRESQUASH_SCRIPTS=&quot;/path/to/script.sh&quot;</span></span><br><span class="line"><span class="string">ARG PRESQUASH_SCRIPTS=&quot;\$&#123;PRESQUASH_SCRIPTS:-rm -rf /tmp/* /usr/share/doc/* /var/cache/* /var/lib/apt/lists/* /var/log/*&#125;&quot;</span></span><br><span class="line"><span class="string">RUN [ ! -z &quot;\$PRESQUASH_SCRIPTS&quot; ] &amp;&amp; sh -c &quot;\$PRESQUASH_SCRIPTS&quot; || true</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">################################################################################</span></span><br><span class="line"><span class="string"># BUILDING SQUASHED IMAGE FROM SCRATCH. ########################################</span></span><br><span class="line"><span class="string">FROM $base AS squashed-$id</span></span><br><span class="line"><span class="string">ARG  BUILDKIT_SBOM_SCAN_STAGE=true</span></span><br><span class="line"><span class="string">COPY --link --from=$alias / /</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$labels&quot; ];      then echo &quot;$labels&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$shell&quot; ];       then echo &quot;SHELL $shell&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$envs&quot; ];        then echo &quot;$envs&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$onbuilds&quot; ];    then echo &quot;$onbuilds&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$exposes&quot; ];     then echo &quot;$exposes&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$workdir&quot; ];     then echo &quot;WORKDIR $workdir&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$user&quot; ];        then echo &quot;USER $user&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$volumes&quot; ];     then echo &quot;$volumes&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$entrypoint&quot; ];  then echo &quot;ENTRYPOINT $entrypoint&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$cmd&quot; ];         then echo &quot;CMD $cmd&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$stopsignal&quot; ];  then echo &quot;STOPSIGNAL $stopsignal&quot;; fi)</span></span><br><span class="line"><span class="string">$(if [ -n &quot;$healthcheck&quot; ]; then echo &quot;HEALTHCHECK $healthcheck&quot;; fi)</span></span><br><span class="line"><span class="string"># FINISH. ######################################################################</span></span><br><span class="line"><span class="string">################################################################################</span></span><br><span class="line"><span class="string">Dockerfile</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment"># Parse arguments</span></span><br><span class="line"><span class="comment">################################################################################</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Show usage if no arguments are passed</span></span><br><span class="line"><span class="keyword">if</span> [ <span class="variable">$#</span> -eq 0 ]; <span class="keyword">then</span></span><br><span class="line">    usage &gt;&amp;2</span><br><span class="line">    <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> a; <span class="keyword">do</span></span><br><span class="line">    <span class="built_in">shift</span></span><br><span class="line">    <span class="keyword">case</span> <span class="string">&quot;<span class="variable">$a</span>&quot;</span> <span class="keyword">in</span></span><br><span class="line">    --<span class="built_in">help</span> | -h) usage &gt;&amp;2; <span class="built_in">exit</span> 0; ;;</span><br><span class="line">    --upgrade | upgrade | -u) upgrade; <span class="built_in">exit</span> 0; ;;</span><br><span class="line">    --<span class="built_in">print</span>* | -p*) <span class="built_in">print</span>=1 ;;</span><br><span class="line">    *) <span class="built_in">set</span> -- <span class="string">&quot;<span class="variable">$@</span>&quot;</span> <span class="string">&quot;<span class="variable">$a</span>&quot;</span> ;;</span><br><span class="line">    <span class="keyword">esac</span></span><br><span class="line"><span class="keyword">done</span></span><br><span class="line"></span><br><span class="line">dockerfile=<span class="string">&quot;<span class="variable">$1</span>&quot;</span></span><br><span class="line">cleanup=0</span><br><span class="line"><span class="built_in">shift</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Check Source Image / Build From Dockerfile</span></span><br><span class="line"><span class="comment">################################################################################</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Enable debug mode</span></span><br><span class="line"><span class="keyword">if</span> [ ! -z <span class="string">&quot;<span class="variable">$DEBUG</span>&quot;</span> ]; <span class="keyword">then</span> <span class="built_in">set</span> -ex; <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Build tempoprary image from Dockerfile</span></span><br><span class="line"><span class="keyword">if</span> [ -f <span class="string">&quot;<span class="variable">$dockerfile</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">hash</span>=<span class="string">&quot;<span class="subst">$(sha256sum <span class="string">&quot;<span class="variable">$dockerfile</span>&quot;</span>)</span>/<span class="subst">$(echo $@ | sha256sum)</span>&quot;</span></span><br><span class="line">    temptag=<span class="string">&quot;docker-squash-build-<span class="subst">$(echo $hash | sha256sum | head -c 8)</span>&quot;</span></span><br><span class="line">    context=<span class="string">&quot;<span class="subst">$(dirname <span class="string">&quot;<span class="variable">$dockerfile</span>&quot;</span>)</span>&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> ! docker build -f <span class="string">&quot;<span class="variable">$dockerfile</span>&quot;</span> <span class="string">&quot;<span class="variable">$context</span>&quot;</span> <span class="string">&quot;<span class="variable">$@</span>&quot;</span> -t <span class="string">&quot;<span class="variable">$temptag</span>&quot;</span>; <span class="keyword">then</span></span><br><span class="line">        <span class="built_in">echo</span> <span class="string">&quot;Failed to build image from <span class="variable">$dockerfile</span>.&quot;</span> &gt;&amp;2</span><br><span class="line">        <span class="built_in">exit</span> 1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">source</span>=<span class="string">&quot;<span class="variable">$temptag</span>&quot;</span></span><br><span class="line">    cleanup=<span class="string">&quot;<span class="variable">$&#123;CLEAR_TEMP_BUILD:-1&#125;</span>&quot;</span></span><br><span class="line"><span class="keyword">else</span></span><br><span class="line">    <span class="comment"># try pulling the docker image from Docker Hub</span></span><br><span class="line">    <span class="keyword">if</span> [ -z <span class="string">&quot;<span class="subst">$(get_name <span class="string">&quot;<span class="variable">$dockerfile</span>&quot;</span>)</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">        docker pull <span class="string">&quot;<span class="variable">$dockerfile</span>&quot;</span> 2&gt;&amp;1</span><br><span class="line">    <span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line">    <span class="built_in">source</span>=<span class="string">&quot;<span class="subst">$(get_name <span class="string">&quot;<span class="variable">$dockerfile</span>&quot;</span>)</span>&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Check if source exists</span></span><br><span class="line"><span class="keyword">if</span> [ -z <span class="string">&quot;<span class="variable">$source</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    <span class="built_in">echo</span> <span class="string">&quot;Invalid image data from &#x27;<span class="variable">$dockerfile</span>&#x27;. Please build or pull the image first.&quot;</span> &gt;&amp;2</span><br><span class="line">    <span class="built_in">exit</span> 1</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Squash / Output to New Dockerfile</span></span><br><span class="line"><span class="comment">################################################################################</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Print Dockerfile to stdout</span></span><br><span class="line"><span class="keyword">if</span> [ ! -z <span class="string">&quot;<span class="variable">$print</span>&quot;</span> ]; <span class="keyword">then</span></span><br><span class="line">    generate <span class="string">&quot;<span class="variable">$source</span>&quot;</span></span><br><span class="line">    <span class="built_in">exit</span> 0</span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Use Docker buildx if available</span></span><br><span class="line">BUILD_CMD=<span class="string">&quot;docker build&quot;</span></span><br><span class="line"><span class="keyword">if</span> docker buildx version &amp;&gt;/dev/null; <span class="keyword">then</span></span><br><span class="line">    BUILD_CMD=<span class="string">&quot;docker buildx build&quot;</span></span><br><span class="line"><span class="keyword">fi</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># Squash image to single layer</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Start squashing the image <span class="variable">$source</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;  Build options: <span class="variable">$@</span>&quot;</span></span><br><span class="line">generate <span class="string">&quot;<span class="variable">$source</span>&quot;</span> | <span class="variable">$BUILD_CMD</span> <span class="string">&quot;<span class="variable">$@</span>&quot;</span> -</span><br><span class="line">[ <span class="string">&quot;<span class="variable">$cleanup</span>&quot;</span> -eq 1 ] &amp;&amp; docker image <span class="built_in">rm</span> -f <span class="string">&quot;<span class="variable">$source</span>&quot;</span></span><br><span class="line"><span class="built_in">echo</span> <span class="string">&quot;Done.&quot;</span></span><br><span class="line"></span><br></pre></td></tr></table></figure><p>这个脚本使用方法：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">bash -ex docker-squash.sh \</span><br><span class="line">    <span class="variable">$&#123;原镜像tag&#125;</span> \</span><br><span class="line">    --tag <span class="variable">$&#123;压缩后tag&#125;</span></span><br></pre></td></tr></table></figure><h2 id="how-does-it-work"><a class="header-anchor" href="#how-does-it-work">¶</a>How does it work</h2><p>这个代码构造了一个dockerfile</p><figure class="highlight dockerfile"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">ARG</span> BUILDKIT_SBOM_SCAN_CONTEXT=true</span><br><span class="line"></span><br><span class="line"><span class="keyword">FROM</span> $tag AS $alias</span><br><span class="line"><span class="keyword">ARG</span>  BUILDKIT_SBOM_SCAN_STAGE=true</span><br><span class="line"><span class="comment"># Pre-squash scripts may be useful to clean the source image before squashing.</span></span><br><span class="line"><span class="comment"># Use build argument to add your pre-squash scripts, and run them in this stage.</span></span><br><span class="line"><span class="comment"># Example:</span></span><br><span class="line"><span class="comment">#   $&#123;0##*/&#125; $tag --build-arg PRESQUASH_SCRIPTS=&quot;rm -rf /tmp/*&quot;</span></span><br><span class="line"><span class="comment">#   $&#123;0##*/&#125; $tag --build-arg PRESQUASH_SCRIPTS=&quot;/path/to/script.sh&quot;</span></span><br><span class="line"><span class="keyword">ARG</span> PRESQUASH_SCRIPTS=<span class="string">&quot;\$&#123;PRESQUASH_SCRIPTS:-rm -rf /tmp/* /usr/share/doc/* /var/cache/* /var/lib/apt/lists/* /var/log/*&#125;&quot;</span></span><br><span class="line"><span class="keyword">RUN</span><span class="language-bash"> [ ! -z <span class="string">&quot;\$PRESQUASH_SCRIPTS&quot;</span> ] &amp;&amp; sh -c <span class="string">&quot;\$PRESQUASH_SCRIPTS&quot;</span> || <span class="literal">true</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">################################################################################</span></span><br><span class="line"><span class="comment"># BUILDING SQUASHED IMAGE FROM SCRATCH. ########################################</span></span><br><span class="line"><span class="keyword">FROM</span> $base AS squashed-$id</span><br><span class="line"><span class="keyword">ARG</span>  BUILDKIT_SBOM_SCAN_STAGE=true</span><br><span class="line"><span class="keyword">COPY</span><span class="language-bash"> --<span class="built_in">link</span> --from=<span class="variable">$alias</span> / /</span></span><br><span class="line">$(if [ -n <span class="string">&quot;$labels&quot;</span> ];      then echo <span class="string">&quot;$labels&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$shell&quot;</span> ];       then echo <span class="string">&quot;SHELL $shell&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$envs&quot;</span> ];        then echo <span class="string">&quot;$envs&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$onbuilds&quot;</span> ];    then echo <span class="string">&quot;$onbuilds&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$exposes&quot;</span> ];     then echo <span class="string">&quot;$exposes&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$workdir&quot;</span> ];     then echo <span class="string">&quot;WORKDIR $workdir&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$user&quot;</span> ];        then echo <span class="string">&quot;USER $user&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$volumes&quot;</span> ];     then echo <span class="string">&quot;$volumes&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$entrypoint&quot;</span> ];  then echo <span class="string">&quot;ENTRYPOINT $entrypoint&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$cmd&quot;</span> ];         then echo <span class="string">&quot;CMD $cmd&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$stopsignal&quot;</span> ];  then echo <span class="string">&quot;STOPSIGNAL $stopsignal&quot;</span>; fi)</span><br><span class="line">$(if [ -n <span class="string">&quot;$healthcheck&quot;</span> ]; then echo <span class="string">&quot;HEALTHCHECK $healthcheck&quot;</span>; fi)</span><br></pre></td></tr></table></figure><p>把原镜像里面的ENV，LABEL，Volume啥的都拿出来，然后在dockerfile里面以<code>base=&quot;scratch&quot;</code>为基镜像，把这些变量，都加进去，然后在把原镜像直接把根目录都copy过去<code>COPY --link --from=$alias / /</code>。</p><p>scratch是docker提供的，“空的”base image</p><blockquote><p><a href="https://arc.net/l/quote/zsplqkkn">Create a minimal base image using scratch</a><br>The reserved, minimal scratch image serves as a starting point for building containers. Using the scratch image signals to the build process that you want the next command in the Dockerfile to be the first filesystem layer in your image.</p></blockquote>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;background&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#background&quot;&gt;¶&lt;/a&gt;Background&lt;/h2&gt;
&lt;p&gt;docker squash 通过merge所有layer从而减小docker</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="Dev Environment" scheme="https://www.jmyjmy.top/categories/Tech-blog/Dev-Environment/"/>
    
    
    <category term="Docker" scheme="https://www.jmyjmy.top/tags/Docker/"/>
    
  </entry>
  
  <entry>
    <title>重庆游记</title>
    <link href="https://www.jmyjmy.top/2024-07-29_chong-qing/"/>
    <id>https://www.jmyjmy.top/2024-07-29_chong-qing/</id>
    <published>2024-07-29T11:32:10.000Z</published>
    <updated>2024-07-29T11:32:10.000Z</updated>
    
    <content type="html"><![CDATA[<p><img src="/img/chongqing/16.webp" alt=""></p><p>重庆真的是个很立体的城市，经常走着走着一个特别特别高的楼就立在面前，或者一个很深的悬崖加一堆台阶下山<br><img src="/img/chongqing/24.webp" alt="一边是1楼，另一边是30楼"><br><img src="/img/chongqing/22.webp" alt="白象居王俊凯他家"></p><p>这里还是很多电影名场面<br><img src="/img/chongqing/25.webp" alt="燕子你走了我怎么活啊"></p><p>晚上去洪崖洞逛了逛，很多人，都在拍网红视频“11点洪崖洞熄灯”。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chongqing/0.webp","alt":"洪崖洞"},{"url":"/img/chongqing/1.webp","alt":"戴家巷崖壁步道"},{"url":"/img/chongqing/2.webp","alt":"解放碑"},{"url":"/img/chongqing/3.webp","alt":"冰汤圆是冰"}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>沿着山上的步道一直走，从七星岗地铁站开始走到山城步道，然后一直走到了十八梯。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chongqing/18.webp","alt":""},{"url":"/img/chongqing/19.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>重庆博物馆也是三峡博物馆，外面修成了一个水坝的形状<br><img src="/img/chongqing/4.webp" alt=""></p><p>观音桥一群人拍个屏幕</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chongqing/10.webp","alt":""},{"url":"/img/chongqing/34.webp","alt":""},{"url":"/img/chongqing/11.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>地铁也是特色，尤其是李子坝的“地铁穿楼”<br>坐地铁简直就是过山车</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chongqing/5.webp","alt":""},{"url":"/img/chongqing/6.webp","alt":""},{"url":"/img/chongqing/12.webp","alt":""},{"url":"/img/chongqing/26.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>朝天门</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chongqing/8.webp","alt":""},{"url":"/img/chongqing/17.webp","alt":""},{"url":"/img/chongqing/20.webp","alt":"在白象居，拍到了白象，缆车，朝天门"},{"url":"/img/chongqing/13.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chongqing/9.webp","alt":""},{"url":"/img/chongqing/14.webp","alt":""},{"url":"/img/chongqing/15.webp","alt":""},{"url":"/img/chongqing/21.webp","alt":"串串火锅"},{"url":"/img/chongqing/23.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>在磁器口有个剧场，看了一个演出《重庆1949》，非常震撼，讲的是1949年解放前夕渣滓洞的故事。</p><div class="gallery">    <div class="fj-gallery  data" data-rowHeight="480" data-limit="10">    <span class="gallery-data">[{"url":"/img/chongqing/27.webp","alt":""},{"url":"/img/chongqing/28.webp","alt":""},{"url":"/img/chongqing/29.webp","alt":""},{"url":"/img/chongqing/30.webp","alt":""},{"url":"/img/chongqing/31.webp","alt":""},{"url":"/img/chongqing/32.webp","alt":""}]</span>    </div>    <button class="gallery-load-more"><span>加载更多</span><i class="fa-solid fa-arrow-down"></i></button>    </div><p>刚刚发过洪水，磁器口的江边还封着，水还很大<br><img src="/img/chongqing/33.webp" alt=""></p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;p&gt;&lt;img src=&quot;/img/chongqing/16.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;重庆真的是个很立体的城市，经常走着走着一个特别特别高的楼就立在面前，或者一个很深的悬崖加一堆台阶下山&lt;br&gt;
&lt;img</summary>
        
      
    
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/categories/Travel/"/>
    
    
    <category term="Travel" scheme="https://www.jmyjmy.top/tags/Travel/"/>
    
  </entry>
  
  <entry>
    <title>Flash Attention</title>
    <link href="https://www.jmyjmy.top/2024-07-20_flash-attention/"/>
    <id>https://www.jmyjmy.top/2024-07-20_flash-attention/</id>
    <published>2024-07-20T00:05:55.000Z</published>
    <updated>2024-07-20T00:05:55.000Z</updated>
    
    <content type="html"><![CDATA[<h2 id="online-softmax"><a class="header-anchor" href="#online-softmax">¶</a>Online Softmax</h2><p>Softmax公式</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mi>S</mi><mi>o</mi><mi>f</mi><mi>t</mi><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>X</mi><mo stretchy="false">)</mo><mo>=</mo><mfrac><msup><mi>e</mi><mrow><msub><mi>X</mi><mi>i</mi></msub><mo>−</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>X</mi><mo stretchy="false">)</mo></mrow></msup><mstyle scriptlevel="0" displaystyle="true"><munderover><mo>∑</mo><mrow><mi>j</mi><mo>=</mo><mn>0</mn></mrow><mi>n</mi></munderover><msup><mi>e</mi><mrow><msub><mi>X</mi><mi>j</mi></msub><mo>−</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>X</mi><mo stretchy="false">)</mo></mrow></msup></mstyle></mfrac></mrow><annotation encoding="application/x-tex">Softmax(X) = \frac{e^{X_i - max(X)}}{\displaystyle\sum_{j=0}^{n} e^{X_j-max(X)}}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:4.5202em;vertical-align:-2.9552em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.565em;"><span style="top:-2.11em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.4138em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.938em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2819em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.8814em;"><span class="pstrut" style="height:3.6514em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-4.3284em;"><span class="pstrut" style="height:3.6514em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.9552em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span></span></span></p><p>指数上都减掉<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>X</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">max(X)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span>防止溢出</p><p>简单的代码就是</p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">vector&lt;<span class="type">float</span>&gt; arr;</span><br><span class="line"><span class="type">float</span> sum = <span class="number">0</span>;</span><br><span class="line"><span class="type">float</span> max_v = arr[<span class="number">0</span>];</span><br><span class="line"><span class="keyword">for</span>(<span class="type">size_t</span> i = <span class="number">0</span> ;i &lt; arr.<span class="built_in">size</span>(); i++)&#123;</span><br><span class="line">    max_v = <span class="built_in">max</span>(max_v, arr[i]);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">size_t</span> i = <span class="number">0</span> ;i &lt; arr.<span class="built_in">size</span>(); i++)&#123;</span><br><span class="line">    sum += <span class="built_in">exp</span>(arr[i] - max_v);</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">for</span>(<span class="type">size_t</span> i = <span class="number">0</span> ;i &lt; arr.<span class="built_in">size</span>(); i++)&#123;</span><br><span class="line">    arr[i] = <span class="built_in">exp</span>(arr[i] - max_v) / sum ;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里求max 和求sum的时候需要两次reduce，这是不可接受的。</p><p>如何压榨这个代码？</p><p>sum 是必须的， max 也是必须的，但是这两个for做的事情可以同时做到，但是当前的<code>max_v</code>不一定就是全局的最大值，需要不断的更新更大的<code>max_v</code>，同时要把前面少减的补回来。</p><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>X</mi><mi>i</mi></msub><mo>−</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>X</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">X_i - max(X)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0785em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mclose">)</span></span></span></span> 这个操作是在指数上的，也就是说这里是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msup><mi>e</mi><msub><mi>X</mi><mi>i</mi></msub></msup><mo>÷</mo><msup><mi>e</mi><mrow><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>X</mi><mo stretchy="false">)</mo></mrow></msup></mrow><annotation encoding="application/x-tex">e^{X_i} \div e^{max(X)}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9247em;vertical-align:-0.0833em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.888em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.888em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span><span class="mopen mtight">(</span><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left right left" columnspacing="0em 1em 0em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mi>g</mi><mo>−</mo><mi>f</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mi>e</mi></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mi>g</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mi>e</mi><mo>+</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mi>f</mi></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mi>a</mi><mo>÷</mo><mi>g</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>a</mi><mo>÷</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mi>e</mi><mo>÷</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mi>f</mi></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align}g-f &amp;= &amp;e  \nonumber \\g &amp;= &amp;e + &amp;f \nonumber \\a \div g &amp;= a \div &amp;e \div &amp;f \nonumber\end{align}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.5em;vertical-align:-2em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span><span style="top:-3.16em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03588em;">g</span></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">a</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord mathnormal" style="margin-right:0.03588em;">g</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span></span></span><span style="top:-3.16em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal">a</span><span class="mord">÷</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5em;"><span style="top:-4.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span></span></span><span style="top:-3.16em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="mord">+</span></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="mord">÷</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1em;"><span style="top:-3.16em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span><span style="top:-1.66em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>所以在for循环<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mi>N</mi></msup><mo separator="true">,</mo><mi>i</mi><mo>=</mo><mi>n</mi></mrow><annotation encoding="application/x-tex">X \in \R^N, i=n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7224em;vertical-align:-0.0391em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0358em;vertical-align:-0.1944em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span></span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span>时，当新值需要更新<code>max_v</code>值时，直接<strong>按新的max算</strong>，并把前面已经加好的值<strong>除去新老max的差值</strong>。</p><p>if <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi><mo>+</mo><mn>1</mn><mo mathvariant="normal">≠</mo><mi>m</mi><mi>a</mi><msub><mi>x</mi><mi>n</mi></msub></mrow><annotation encoding="application/x-tex">n+1 \neq max_n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6667em;vertical-align:-0.0833em;"></span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel"><span class="mrel"><span class="mord vbox"><span class="thinbox"><span class="rlap"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="inner"><span class="mord"><span class="mrel"></span></span></span><span class="fix"></span></span></span></span></span><span class="mrel">=</span></span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.5806em;vertical-align:-0.15em;"></span><span class="mord mathnormal">ma</span><span class="mord"><span class="mord mathnormal">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1514em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left" columnspacing="0em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>0</mn></mrow><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></munderover><msup><mi>e</mi><msub><mi>X</mi><mi>i</mi></msub></msup></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>0</mn></mrow><mi>n</mi></munderover><msup><mi>e</mi><msub><mi>X</mi><mi>i</mi></msub></msup><mo>÷</mo><msup><mi>e</mi><mrow><mo stretchy="false">(</mo><msub><mi>X</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub><mo>−</mo><mi>m</mi><mi>a</mi><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow></msup><mo>+</mo><msup><mi>e</mi><mrow><msub><mi>X</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub><mo>−</mo><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><msub><mi>X</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub><mo separator="true">,</mo><mi>m</mi><mi>a</mi><msub><mi>x</mi><mi>n</mi></msub><mo stretchy="false">)</mo></mrow></msup></mrow></mstyle></mtd></mtr><mtr><mtd class ="mtr-glue"></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><munderover><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>0</mn></mrow><mi>n</mi></munderover><msup><mi>e</mi><msub><mi>X</mi><mi>i</mi></msub></msup><mo>×</mo><msup><mi>e</mi><mrow><mo stretchy="false">(</mo><mi>m</mi><mi>a</mi><msub><mi>x</mi><mi>n</mi></msub><mo>−</mo><msub><mi>X</mi><mrow><mi>n</mi><mo>+</mo><mn>1</mn></mrow></msub><mo stretchy="false">)</mo></mrow></msup><mo>+</mo><mn>1</mn></mrow></mstyle></mtd><mtd class ="mtr-glue"></mtd><mtd class ="mml-eqn-num"></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align}\sum_{i=0}^{n+1} e^{X_i} &amp;= \sum_{i=0}^n e^{X_i}\div e^{(X_{n+1} - max_n)}  + e^{X_{n+1} - max(X_{n+1},max_n)} \nonumber \\&amp;= \sum_{i=0}^n e^{X_i} \times e^{(max_n - X_{n+1})}  + 1\end{align}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:6.6078em;vertical-align:-3.0539em;"></span><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.5539em;"><span style="top:-5.5539em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8011em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span style="top:-2.3249em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.0539em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.5539em;"><span style="top:-5.5539em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">÷</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.938em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2025em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">ma</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.938em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2025em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mathnormal mtight">ma</span><span class="mord mathnormal mtight">x</span><span class="mopen mtight">(</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2025em;"><span></span></span></span></span></span></span><span class="mpunct mtight">,</span><span class="mord mathnormal mtight">ma</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span></span></span><span style="top:-2.3249em;"><span class="pstrut" style="height:3.8011em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.6514em;"><span style="top:-1.8723em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">0</span></span></span></span><span style="top:-3.05em;"><span class="pstrut" style="height:3.05em;"></span><span><span class="mop op-symbol large-op">∑</span></span></span><span style="top:-4.3em;margin-left:0em;"><span class="pstrut" style="height:3.05em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.2777em;"><span></span></span></span></span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.938em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mopen mtight">(</span><span class="mord mathnormal mtight">ma</span><span class="mord mtight"><span class="mord mathnormal mtight">x</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.1645em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">n</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.07847em;">X</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3173em;"><span style="top:-2.357em;margin-left:-0.0785em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span><span class="mbin mtight">+</span><span class="mord mtight">1</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2025em;"><span></span></span></span></span></span></span><span class="mclose mtight">)</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord">1</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.0539em;"><span></span></span></span></span></span></span></span><span class="tag"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:3.5539em;"><span style="top:-5.5539em;"><span class="pstrut" style="height:3.8011em;"></span><span></span></span><span style="top:-2.3249em;"><span class="pstrut" style="height:3.8011em;"></span><span class="eqn-num"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:3.0539em;"><span></span></span></span></span></span></span></span></span></p><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">vector&lt;<span class="type">float</span>&gt; arr;</span><br><span class="line"><span class="type">float</span> sum = <span class="number">0</span>;</span><br><span class="line"><span class="type">float</span> max_v = arr[<span class="number">0</span>];</span><br><span class="line"><span class="keyword">for</span>(<span class="type">size_t</span> i = <span class="number">0</span> ;i &lt; arr.<span class="built_in">size</span>(); i++)&#123;</span><br><span class="line">    <span class="keyword">if</span>(arr[i] &gt; max_v)&#123;</span><br><span class="line">        sum *= <span class="built_in">exp</span>(max_v - arr[i]);</span><br><span class="line">        sum += <span class="number">1</span>;</span><br><span class="line">        max_v = arr[i];</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">else</span>&#123;</span><br><span class="line">        sum += <span class="built_in">exp</span>(arr[i] - max_v);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span>(<span class="type">size_t</span> i = <span class="number">0</span> ;i &lt; arr.<span class="built_in">size</span>(); i++)&#123;</span><br><span class="line">    arr[i] = <span class="built_in">exp</span>(arr[i] - max_v) / sum ;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>这样，可以一边求max一边算sum，而且元素直接互不干扰，只要把少的<code>max_v</code>补上就行了，在GPU上分块求和也不影响，block内算自己的，最后block间把差的<code>max_v</code>补齐就是了。</p><h2 id="flash-attention"><a class="header-anchor" href="#flash-attention">¶</a>Flash Attention</h2><p>切开算，基于上文online softmax 的方法尽可能的分块算，然后在最后对齐结果。</p><h3 id="attention-计算公式："><a class="header-anchor" href="#attention-计算公式：">¶</a>Attention 计算公式：</h3><p><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>X</mi></mrow><annotation encoding="application/x-tex">X</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span></span></span></span>是输入，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span></span></span></span>是sequence length，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>d</mi></mrow><annotation encoding="application/x-tex">d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal">d</span></span></span></span>是hidden size</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left" columnspacing="0em"><mtr><mtd class ="mtr-glue"></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mi>Q</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>X</mi><msub><mi>W</mi><mi>Q</mi></msub><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>N</mi><mo>×</mo><mi>d</mi></mrow></msup></mrow></mstyle></mtd><mtd class ="mtr-glue"></mtd><mtd class ="mml-eqn-num"></mtd></mtr><mtr><mtd class ="mtr-glue"></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mi>K</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>X</mi><msub><mi>W</mi><mi>K</mi></msub><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>N</mi><mo>×</mo><mi>d</mi></mrow></msup></mrow></mstyle></mtd><mtd class ="mtr-glue"></mtd><mtd class ="mml-eqn-num"></mtd></mtr><mtr><mtd class ="mtr-glue"></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mi>V</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>X</mi><msub><mi>W</mi><mi>V</mi></msub><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>N</mi><mo>×</mo><mi>d</mi></mrow></msup></mrow></mstyle></mtd><mtd class ="mtr-glue"></mtd><mtd class ="mml-eqn-num"></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align}Q &amp;= XW_Q \in \R^{N \times d} \\K &amp;= XW_K \in \R^{N \times d} \\V &amp;= XW_V \in \R^{N \times d} \\\end{align}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.6773em;vertical-align:-2.0887em;"></span><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5887em;"><span style="top:-4.6896em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal">Q</span></span></span><span style="top:-3.1304em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span></span></span><span style="top:-1.5713em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.0887em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5887em;"><span style="top:-4.6896em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">Q</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.1304em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.07153em;">K</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span></span></span></span><span style="top:-1.5713em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.07847em;">X</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">W</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3283em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.22222em;">V</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.0887em;"><span></span></span></span></span></span></span></span><span class="tag"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.5887em;"><span style="top:-4.5887em;"><span class="pstrut" style="height:2.8991em;"></span><span class="eqn-num"></span></span><span style="top:-3.0296em;"><span class="pstrut" style="height:2.8991em;"></span><span class="eqn-num"></span></span><span style="top:-1.4704em;"><span class="pstrut" style="height:2.8991em;"></span><span class="eqn-num"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.0887em;"><span></span></span></span></span></span></span></span></span></p><p><strong>从这开始</strong>：Attention输入为<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi><mo separator="true">,</mo><mi>K</mi><mo separator="true">,</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">Q,K,V</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span>三矩阵，输出<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi></mrow><annotation encoding="application/x-tex">O</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span></span></span></span>矩阵</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left right" columnspacing="0em 1em"><mtr><mtd class ="mtr-glue"></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mi>S</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mfrac><mrow><mi>S</mi><mi>o</mi><mi>f</mi><mi>t</mi><mi>m</mi><mi>a</mi><mi>x</mi><mo stretchy="false">(</mo><mi>Q</mi><msup><mi>K</mi><mi>T</mi></msup><mo stretchy="false">)</mo></mrow><msqrt><mi>d</mi></msqrt></mfrac></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>N</mi><mo>×</mo><mi>N</mi></mrow></msup></mrow></mstyle></mtd><mtd class ="mtr-glue"></mtd><mtd class ="mml-eqn-num"></mtd></mtr><mtr><mtd class ="mtr-glue"></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mi>O</mi></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mi>S</mi><mi>V</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>N</mi><mo>×</mo><mi>d</mi></mrow></msup></mrow></mstyle></mtd><mtd class ="mtr-glue"></mtd><mtd class ="mml-eqn-num"></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align}S &amp;= \frac{Softmax(QK^T)}{\sqrt{d}} &amp; \in \R^{N\times N}  \\O &amp;= SV &amp; \in \R^{N \times d}\end{align}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.3074em;vertical-align:-1.9037em;"></span><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.4037em;"><span style="top:-4.4037em;"><span class="pstrut" style="height:3.5183em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span></span></span><span style="top:-2.2746em;"><span class="pstrut" style="height:3.5183em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">O</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.9037em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.4037em;"><span style="top:-4.4037em;"><span class="pstrut" style="height:3.5183em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.5183em;"><span style="top:-2.1778em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord sqrt"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.9322em;"><span class="svg-align" style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span class="mord" style="padding-left:0.833em;"><span class="mord mathnormal">d</span></span></span><span style="top:-2.8922em;"><span class="pstrut" style="height:3em;"></span><span class="hide-tail" style="min-width:0.853em;height:1.08em;"><svg xmlns="http://www.w3.org/2000/svg" width="400em" height="1.08em" viewBox="0 0 400000 1080" preserveAspectRatio="xMinYMin slice"><path d="M95,702c-2.7,0,-7.17,-2.7,-13.5,-8c-5.8,-5.3,-9.5,-10,-9.5,-14c0,-2,0.3,-3.3,1,-4c1.3,-2.7,23.83,-20.7,67.5,-54c44.2,-33.3,65.8,-50.3,66.5,-51c1.3,-1.3,3,-2,5,-2c4.7,0,8.7,3.3,12,10s173,378,173,378c0.7,0,35.3,-71,104,-213c68.7,-142,137.5,-285,206.5,-429c69,-144,104.5,-217.7,106.5,-221l0 -0c5.3,-9.3,12,-14,20,-14H400000v40H845.2724s-225.272,467,-225.272,467s-235,486,-235,486c-2.7,4.7,-9,7,-19,7c-6,0,-10,-1,-12,-3s-194,-422,-194,-422s-65,47,-65,47zM834 80h400000v40h-400000z"/></svg></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.1078em;"><span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.677em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal">o</span><span class="mord mathnormal" style="margin-right:0.10764em;">f</span><span class="mord mathnormal">t</span><span class="mord mathnormal">ma</span><span class="mord mathnormal">x</span><span class="mopen">(</span><span class="mord mathnormal">Q</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8413em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.93em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span></span></span><span style="top:-2.2746em;"><span class="pstrut" style="height:3.5183em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.9037em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.4037em;"><span style="top:-4.4037em;"><span class="pstrut" style="height:3.5183em;"></span><span class="mord"><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span></span></span></span></span></span></span></span></span></span></span><span style="top:-2.2746em;"><span class="pstrut" style="height:3.5183em;"></span><span class="mord"><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8991em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight">d</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.9037em;"><span></span></span></span></span></span></span></span><span class="tag"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.4037em;"><span style="top:-4.4037em;"><span class="pstrut" style="height:3.5183em;"></span><span class="eqn-num"></span></span><span style="top:-2.2746em;"><span class="pstrut" style="height:3.5183em;"></span><span class="eqn-num"></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.9037em;"><span></span></span></span></span></span></span></span></span></p><h3 id="算法过程"><a class="header-anchor" href="#算法过程">¶</a>算法过程</h3><p><img src="/img/flashattn1.webp" alt=""></p><p>将<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>Q</mi><mo separator="true">,</mo><mi>K</mi><mo separator="true">,</mo><mi>V</mi></mrow><annotation encoding="application/x-tex">Q,K,V</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8778em;vertical-align:-0.1944em;"></span><span class="mord mathnormal">Q</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span>都切成<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>B</mi><mo>=</mo><mo stretchy="false">⌈</mo><mfrac><mi>M</mi><mrow><mn>4</mn><mi>d</mi></mrow></mfrac><mo stretchy="false">⌉</mo></mrow><annotation encoding="application/x-tex">B = \lceil \frac{M}{4d} \rceil</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05017em;">B</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2173em;vertical-align:-0.345em;"></span><span class="mopen">⌈</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8723em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span><span class="mord mathnormal mtight">d</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">M</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">⌉</span></span></span></span> 大小，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>M</mi></mrow><annotation encoding="application/x-tex">M</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">M</span></span></span></span>是SRAM的size，比如8K。<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>4</mn><mi>d</mi></mrow><annotation encoding="application/x-tex">4d</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">4</span><span class="mord mathnormal">d</span></span></span></span>是qkvo的空间，这样切目的是把sram用满。<br>好了，QKVO都切成了<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>T</mi><mo>=</mo><mo stretchy="false">⌈</mo><mfrac><mrow><mn>4</mn><mi>N</mi><mi>d</mi></mrow><mi>M</mi></mfrac><mo stretchy="false">⌉</mo></mrow><annotation encoding="application/x-tex">T=\lceil \frac{4Nd}{M} \rceil</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2251em;vertical-align:-0.345em;"></span><span class="mopen">⌈</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.10903em;">M</span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">4</span><span class="mord mathnormal mtight" style="margin-right:0.10903em;">N</span><span class="mord mathnormal mtight">d</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mclose">⌉</span></span></span></span> 个块。（假设都刚刚好整除）<br>B是块大小，T是块个数</p><p>两层循环：外层for K,V，用<code>j</code>，从global 加载当前KV，内层for Q用<code>i</code>，从global 加载Q 和 O</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mrow><mtext>for </mtext><mi>j</mi><mtext> in </mtext><mi>T</mi><mspace linebreak="newline"></mspace><mtext>for </mtext><mi>i</mi><mtext> in </mtext><mi>T</mi><mspace linebreak="newline"></mspace><msub><mi>S</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>=</mo><msub><mi>Q</mi><mi>i</mi></msub><msubsup><mi>K</mi><mi>j</mi><mi>T</mi></msubsup><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>B</mi><mo>×</mo><mi>B</mi></mrow></msup><mspace linebreak="newline"></mspace></mrow><annotation encoding="application/x-tex">\text{for } j \text{ in } T \\\text{for } i \text{ in } T \\S_{ij} = Q_iK_j^T \in \R^{B\times B} \\</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8889em;vertical-align:-0.1944em;"></span><span class="mord text"><span class="mord">for </span></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mord text"><span class="mord"> in </span></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord text"><span class="mord">for </span></span><span class="mord mathnormal">i</span><span class="mord text"><span class="mord"> in </span></span><span class="mord mathnormal" style="margin-right:0.13889em;">T</span></span><span class="mspace newline"></span><span class="base"><span class="strut" style="height:0.9694em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.2744em;vertical-align:-0.3831em;"></span><span class="mord"><span class="mord mathnormal">Q</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.07153em;">K</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-2.453em;margin-left:-0.0715em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.3831em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8913em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span></span></span></span></span></span></span><span class="mspace newline"></span></span></span></span></p><p>用前面<em>softmax</em>中求分母的方法得到sum<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>l</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">l_{ij}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9805em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>和最大值<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>m</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">m_{ij}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7167em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span></p><p><strong>ij是新的</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left right" columnspacing="0em 1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><msub><mi>P</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><msup><mi>e</mi><mrow><msub><mi>S</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>−</mo><msub><mi>m</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow></msup></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>B</mi><mo>×</mo><mi>B</mi></mrow></msup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><msub><mi>m</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mtext>rowmax</mtext><mo stretchy="false">(</mo><msub><mi>S</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mi>B</mi></msup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><msub><mi>l</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mtext>sum</mtext><mo stretchy="false">(</mo><msub><mi>P</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mi>B</mi></msup></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align}P_{ij} &amp;= e^{S_{ij} - m_{ij}} &amp; \in \R^{B\times B } \nonumber \\m_{ij} &amp;= \text{rowmax}(S_{ij}) &amp; \in \R^B \nonumber \\l_{ij} &amp;= \text{sum}(P_{ij}) &amp; \in \R^B \nonumber \\\end{align}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:4.654em;vertical-align:-2.077em;"></span><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.577em;"><span style="top:-4.6857em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-3.1343em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span><span style="top:-1.583em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.077em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.577em;"><span style="top:-4.6857em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:-0.0576em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2819em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2819em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.1343em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord">rowmax</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0576em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span><span style="top:-1.583em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord">sum</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.077em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.577em;"><span style="top:-4.6857em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.1343em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span></span></span></span></span></span></span><span style="top:-1.583em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.077em;"><span></span></span></span></span></span></span></span><span class="tag"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:2.577em;"><span style="top:-4.577em;"><span class="pstrut" style="height:2.8913em;"></span><span></span></span><span style="top:-3.0257em;"><span class="pstrut" style="height:2.8913em;"></span><span></span></span><span style="top:-1.4743em;"><span class="pstrut" style="height:2.8913em;"></span><span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:2.077em;"><span></span></span></span></span></span></span></span></span></p><p>把<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>m</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mtext> </mtext><mo separator="true">,</mo><msub><mi>l</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub></mrow><annotation encoding="application/x-tex">m_{ij}\ ,l_{ij}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9805em;vertical-align:-0.2861em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mspace"> </span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span></span></span></span>更新到当前的<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msubsup><mi>m</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup><mtext> </mtext><mo separator="true">,</mo><msubsup><mi>l</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mrow><annotation encoding="application/x-tex">m\rq_i \ ,l\rq_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0106em;vertical-align:-0.2587em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4413em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2587em;"><span></span></span></span></span></span></span><span class="mspace"> </span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4413em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2587em;"><span></span></span></span></span></span></span></span></span></span></p><p><strong>i保留着历史值，每次outerloop j把所有i过一遍留着下一轮用</strong></p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right left right" columnspacing="0em 1em"><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><msubsup><mi>m</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><mtext>max</mtext><mo stretchy="false">(</mo><msub><mi>m</mi><mi>i</mi></msub><mo separator="true">,</mo><msub><mi>m</mi><mi>i</mi></msub><mi>j</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mi>B</mi></msup></mrow></mstyle></mtd></mtr><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><msubsup><mi>l</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mrow></mrow><mo>=</mo><msup><mi>e</mi><mrow><msub><mi>m</mi><mi>i</mi></msub><mo>−</mo><msubsup><mi>m</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mrow></msup><msub><mi>l</mi><mi>i</mi></msub><mo>+</mo><msup><mi>e</mi><mrow><msub><mi>m</mi><mi>i</mi></msub><mi>j</mi><mo>−</mo><msubsup><mi>m</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mrow></msup><msub><mi>l</mi><mi>i</mi></msub><mi>j</mi></mrow></mstyle></mtd><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><mo>∈</mo><msup><mi mathvariant="double-struck">R</mi><mrow><mi>B</mi><mo>×</mo><mi>B</mi></mrow></msup></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align}m\rq_{i} &amp;= \text{max}(m_i,m_ij) &amp; \in \R^B \nonumber \\l\rq_i &amp;= e^{m_i-m\rq_i}l_i + e^{m_ij-m\rq_i}l_ij &amp; \in \R^{B\times B} \nonumber \\\end{align}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:3.2038em;vertical-align:-1.3519em;"></span><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8519em;"><span style="top:-3.9606em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-2.453em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span><span style="top:-2.3081em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-2.453em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.3519em;"><span></span></span></span></span></span><span class="col-align-l"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8519em;"><span style="top:-3.9606em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord">max</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span><span class="mclose">)</span></span></span><span style="top:-2.3081em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mord mathnormal mtight" style="margin-right:0.05724em;">j</span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.05724em;">j</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.3519em;"><span></span></span></span></span></span><span class="arraycolsep" style="width:1em;"></span><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8519em;"><span style="top:-3.9606em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span></span></span></span></span></span></span><span style="top:-2.3081em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord"><span class="mord mathbb">R</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8913em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span><span class="mbin mtight">×</span><span class="mord mathnormal mtight" style="margin-right:0.05017em;">B</span></span></span></span></span></span></span></span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.3519em;"><span></span></span></span></span></span></span></span><span class="tag"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.8519em;"><span style="top:-3.9531em;"><span class="pstrut" style="height:2.9925em;"></span><span></span></span><span style="top:-2.3006em;"><span class="pstrut" style="height:2.9925em;"></span><span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:1.3519em;"><span></span></span></span></span></span></span></span></span></p><p>计算最后的<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo>=</mo><mi>S</mi><mi>V</mi></mrow><annotation encoding="application/x-tex">O = SV</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.05764em;">S</span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span></span></span></span>，<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi></mrow><annotation encoding="application/x-tex">O</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span></span></span></span>在z维度累加，因为sum和max在变，所以这里也要在线更新历史结果，补齐max导致的差异</p><p><span class="katex-display"><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML" display="block"><semantics><mtable rowspacing="0.25em" columnalign="right" columnspacing=""><mtr><mtd><mstyle scriptlevel="0" displaystyle="true"><mrow><msub><mi>O</mi><mi>i</mi></msub><mo>=</mo><mtext>diag</mtext><mo stretchy="false">(</mo><msubsup><mi>l</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup><msup><mo stretchy="false">)</mo><mrow><mo>−</mo><mn>1</mn></mrow></msup><mo stretchy="false">(</mo><mtext>diag</mtext><mo stretchy="false">(</mo><msub><mi>l</mi><mi>i</mi></msub><mo stretchy="false">)</mo><msup><mi>e</mi><mrow><msub><mi>m</mi><mi>i</mi></msub><mo>−</mo><msubsup><mi>m</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mrow></msup><msub><mi>O</mi><mi>i</mi></msub><mo>+</mo><msup><mi>e</mi><mrow><msub><mi>m</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mo>−</mo><msubsup><mi>m</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mrow></msup><msub><mi>P</mi><mrow><mi>i</mi><mi>j</mi></mrow></msub><mi>V</mi><mi>j</mi><mo stretchy="false">)</mo></mrow></mstyle></mtd></mtr></mtable><annotation encoding="application/x-tex">\begin{align}O_i = \text{diag}(l\rq_i)^{-1}(\text{diag}(l_i)e^{m_i-m\rq_i}O_i + e^{m_{ij} - m\rq_i} P_{ij}V{j} ) \nonumber\end{align}</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.6525em;vertical-align:-0.5762em;"></span><span class="mord"><span class="mtable"><span class="col-align-r"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.0762em;"><span style="top:-3.0838em;"><span class="pstrut" style="height:3em;"></span><span class="mord"><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mord text"><span class="mord">diag</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8019em;"><span style="top:-2.453em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.247em;"><span></span></span></span></span></span></span><span class="mclose"><span class="mclose">)</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8641em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">−</span><span class="mord mtight">1</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord text"><span class="mord">diag</span></span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose">)</span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.143em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mord"><span class="mord mathnormal">e</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.9925em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3281em;"><span style="top:-2.357em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2819em;"><span></span></span></span></span></span></span><span class="mbin mtight">−</span><span class="mord mtight"><span class="mord mathnormal mtight">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8278em;"><span style="top:-2.214em;margin-left:0em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-2.931em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.286em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.1389em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.05724em;">ij</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2861em;"><span></span></span></span></span></span></span><span class="mord mathnormal" style="margin-right:0.22222em;">V</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.05724em;">j</span></span><span class="mclose">)</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.5762em;"><span></span></span></span></span></span></span></span></span></span></span></span></p><p>最后把<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><msub><mi>O</mi><mi>i</mi></msub><mtext> </mtext><msubsup><mi>l</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup><mtext> </mtext><msubsup><mi>m</mi><mi>i</mi><mo mathvariant="normal" lspace="0em" rspace="0em">′</mo></msubsup></mrow><annotation encoding="application/x-tex">O_i \ l\rq_i \ m\rq_i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0106em;vertical-align:-0.2587em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3117em;"><span style="top:-2.55em;margin-left:-0.0278em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace"> </span><span class="mord"><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4413em;margin-left:-0.0197em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2587em;"><span></span></span></span></span></span></span><span class="mspace"> </span><span class="mord"><span class="mord mathnormal">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.7519em;"><span style="top:-2.4413em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span><span class="vlist-s">​</span></span><span class="vlist-r"><span class="vlist" style="height:0.2587em;"><span></span></span></span></span></span></span></span></span></span>写回global mem，继续下一个loop i</p><h3 id="改进"><a class="header-anchor" href="#改进">¶</a>改进</h3><p>这两层for 循环，里面这层是Q 和O， 每次inner loop都要从global 读 Q 和O 然后再写回 O，太频繁了。</p><p>把这两层调换一下，inner loop 读KV，内循环一样是从global读取两个，但是不需要频繁把O写回global， O在每次外层循环结束才写回global，这就相比之前少了很多次写回global的数据量。这就又水了一个<a href="https://arxiv.org/abs/2307.08691">FlashAttention V2</a></p><p>我都有H100 了，矩阵计算用tensor core算很合理吧，TMA跑起来得做一些计算访存并行吧。这就又水了一个<a href="https://arxiv.org/abs/2407.08608">FlashAttention V3</a></p><p>顺手的优化就又多发了两个paper</p>]]></content>
    
    
      
      
        
        
    <summary type="html">&lt;h2 id=&quot;online-softmax&quot;&gt;&lt;a class=&quot;header-anchor&quot; href=&quot;#online-softmax&quot;&gt;¶&lt;/a&gt;Online Softmax&lt;/h2&gt;
&lt;p&gt;Softmax公式&lt;/p&gt;
&lt;p&gt;&lt;span</summary>
        
      
    
    
    
    <category term="Tech blog" scheme="https://www.jmyjmy.top/categories/Tech-blog/"/>
    
    <category term="High Performance Computing" scheme="https://www.jmyjmy.top/categories/Tech-blog/High-Performance-Computing/"/>
    
    
    <category term="AI" scheme="https://www.jmyjmy.top/tags/AI/"/>
    
  </entry>
  
</feed>
