<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Jingze&apos;s Blog</title><description>GPU Architecture &amp; More</description><link>https://infra.simphoni.uk/</link><language>zh_CN</language><item><title>DeepSeek MegaMoE：MoE 推理的单 Kernel 融合与通信计算重叠</title><link>https://infra.simphoni.uk/posts/mega-moe/</link><guid isPermaLink="true">https://infra.simphoni.uk/posts/mega-moe/</guid><pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;2026 年 4 月，DeepSeek 在 &lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM&quot;&gt;DeepGEMM&lt;/a&gt; 仓库的 &lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/pull/304&quot;&gt;PR #304&lt;/a&gt; 中引入了一个新的 MoE 推理实现。其核心设计是将 dispatch、两层 GEMM、SwiGLU 激活、combine 全部合并到一个 CUDA kernel 中，利用 Warp Specialization 使 NVLink 通信与 Tensor Core 计算在同一 SM 上并发执行。&lt;/p&gt;
&lt;p&gt;本文直接从源码出发，逐层拆解实现。&lt;/p&gt;
&lt;p&gt;本文引用的所有代码基于 DeepGEMM 仓库 commit &lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/tree/714dd1a4a980f7937a74343d19a8eba4fe321480&quot;&gt;&lt;code&gt;714dd1a&lt;/code&gt;&lt;/a&gt;。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;1. 问题&lt;/h2&gt;
&lt;p&gt;标准 MoE 推理包含五个阶段：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;EP-Dispatch → Linear1 (Gate+Up) → SwiGLU → Linear2 (Down) → EP-Combine
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;传统实现中，每个阶段是独立的 kernel launch。每个 kernel 将中间结果写入 HBM，下一个 kernel 再从 HBM 读出。其中 dispatch 和 combine 阶段还涉及跨 GPU 的 NVLink 通信。&lt;/p&gt;
&lt;p&gt;这种分离式设计的问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;五次 kernel launch 意味着五次 global memory 往返&lt;/li&gt;
&lt;li&gt;通信和计算是串行的——dispatch 通信完成后才能启动 Linear1，Linear2 完成后才能启动 combine 通信&lt;/li&gt;
&lt;li&gt;SM 在通信阶段处于闲置状态（通信由专门的 copy engine 或通信 kernel 处理）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MegaMoE 将这些阶段全部合并到一个 kernel 中，中间数据通过 SMEM 和 TMEM 传递，同时使通信与计算 overlap。&lt;/p&gt;
&lt;p&gt;性能方面，官方给出的数据是分离方案相比推理提速 1.50∼1.73 倍，延迟敏感场景最高 1.96 倍。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;2. 硬件前提：Blackwell SM100&lt;/h2&gt;
&lt;p&gt;MegaMoE 目前仅支持 &lt;code&gt;sm_100f&lt;/code&gt;（Blackwell）目标架构。以下硬件特性是 MegaMoE 得以实现的前提。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;在 MegaMoE 中的用途&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;TMEM (Tensor Memory)&lt;/td&gt;
&lt;td&gt;256KB/SM，与通用寄存器独立的张量专用内存&lt;/td&gt;
&lt;td&gt;L1/L2 GEMM 之间的中间结果存储，避免占用 GPR 或回写 HBM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UMMA (Unbound MMA)&lt;/td&gt;
&lt;td&gt;替代 SM90 WGMMA 的张量核心指令集，原生支持 FP4&lt;/td&gt;
&lt;td&gt;执行 FP8×FP4 混合精度 MMA，双 SM 协同（2-CTA cluster）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TMA (Tensor Memory Accelerator)&lt;/td&gt;
&lt;td&gt;硬件异步数据搬运引擎，支持跨 GPU RDMA&lt;/td&gt;
&lt;td&gt;从远端 GPU 直接 load token 数据到本地 SMEM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FP4 原生支持&lt;/td&gt;
&lt;td&gt;E2M1 格式&lt;/td&gt;
&lt;td&gt;权重存储带宽需求为 FP8 的一半&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UE8M0 缩放格式&lt;/td&gt;
&lt;td&gt;8-bit 无符号指数，0-bit 尾数&lt;/td&gt;
&lt;td&gt;Block scaling 的紧凑 scale factor 表示&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NVLink 6.0&lt;/td&gt;
&lt;td&gt;3.6 TB/s 双向&lt;/td&gt;
&lt;td&gt;提供足够通信带宽使 overlap 有意义&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ClusterTransactionBarrier&lt;/td&gt;
&lt;td&gt;集群级硬件同步原语&lt;/td&gt;
&lt;td&gt;2-CTA 之间同步&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;TMEM 是 SM100 相对于 SM90 最关键的变化。SM90 的 WGMMA 要求累加器 D 矩阵全部驻留在通用寄存器中，这成为限制 occupancy 的瓶颈——寄存器容量决定了每个 SM 能同时执行的 tile 数量。TMEM 将累加器移出 GPR 文件，256KB/SM 的容量允许容纳更多 inflight tile，直接提高了 occupancy。&lt;/p&gt;
&lt;p&gt;UMMA 在 SM100 上提供的 &lt;code&gt;SM100_MMA_MXF8F6F4_2x1SM_SS&lt;/code&gt; 指令是 MegaMoE MMA 发射的核心。其中 &lt;code&gt;MXF8F6F4&lt;/code&gt; 表示 A=FP8 (E4M3)、B=FP4 (E2M1)、D=F32 的混合精度；&lt;code&gt;2x1SM&lt;/code&gt; 表示两个 SM 通过 2-CTA cluster 协同计算；&lt;code&gt;SS&lt;/code&gt; 表示 block scaled。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;3. Symmetric Memory&lt;/h2&gt;
&lt;p&gt;Symmetric Memory 是 MegaMoE 实现通信计算重叠的基础。在讨论 warp 分工之前，需要先理解这一机制。&lt;/p&gt;
&lt;h3&gt;3.1 原理&lt;/h3&gt;
&lt;p&gt;Symmetric Memory 是 PyTorch 2.x 通过 &lt;code&gt;torch.distributed._symmetric_memory&lt;/code&gt; 导出的特性，底层基于 CUDA P2P memory access over NVLink。多个 GPU 将各自的物理 HBM 映射到相同的虚拟地址范围。每个 GPU 可以通过普通的 load/store 指令直接读写其他 GPU 的物理 HBM——无需经过 &lt;code&gt;cudaMemcpy&lt;/code&gt;、NCCL 集合通信或 kernel launch。&lt;/p&gt;
&lt;p&gt;从 MegaMoE 的 SymBuffer 实现（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/layout/sym_buffer.cuh&quot;&gt;&lt;code&gt;sym_buffer.cuh&lt;/code&gt;&lt;/a&gt;）可以看到完整的地址映射逻辑：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;template &amp;lt;uint32_t kNumRanks&amp;gt;
struct SymBuffer {
    int64_t base;                    // 本 GPU 在本地虚拟地址空间的基地址
    int64_t offsets[kNumMaxRanks];   // offsets[i] = GPU_i.BASE - base
    uint32_t rank_idx;
};

template &amp;lt;typename ptr_t&amp;gt;
CUTLASS_DEVICE ptr_t map(const ptr_t&amp;amp; ptr, const uint32_t&amp;amp; dst_rank_idx) const {
    int64_t mapped_ptr = offsets[dst_rank_idx] + reinterpret_cast&amp;lt;int64_t&amp;gt;(ptr);
    return *reinterpret_cast&amp;lt;ptr_t*&amp;gt;(&amp;amp;mapped_ptr);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;offsets[i]&lt;/code&gt; 存储的是 &lt;code&gt;(GPU_i 本地物理 HBM 的虚拟地址) - (本 GPU 本地物理 HBM 的虚拟地址)&lt;/code&gt;。因此 &lt;code&gt;map(local_ptr, dst_rank)&lt;/code&gt; 的返回值就是一个直接指向远端 GPU HBM 的有效指针，可以直接 dereference。&lt;/p&gt;
&lt;p&gt;在 Python 侧，SymBuffer 的创建通过 &lt;code&gt;symm_mem.empty()&lt;/code&gt; 和 &lt;code&gt;symm_mem.rendezvous()&lt;/code&gt; 完成（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/mega/__init__.py&quot;&gt;&lt;code&gt;mega/__init__.py&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;self.buffer = symm_mem.empty(num_bytes, dtype=torch.int8, device=&apos;cuda&apos;)
self.handle = symm_mem.rendezvous(self.buffer, group=group)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;empty()&lt;/code&gt; 在所有 GPU 上分配大小相同的 buffer，&lt;code&gt;rendezvous()&lt;/code&gt; 交换各 GPU 的地址信息并填充到 &lt;code&gt;SymBuffer&lt;/code&gt; 的 &lt;code&gt;offsets&lt;/code&gt; 数组中。&lt;/p&gt;
&lt;h3&gt;3.2 远端访问延迟&lt;/h3&gt;
&lt;p&gt;通过 NVLink 进行 P2P load 的单次延迟约 1∼3 μs，远高于本地 HBM 的数百 ns。如果每个 token 的每个元素都通过细粒度 load 从远端获取，延迟将无法接受。&lt;/p&gt;
&lt;p&gt;MegaMoE 通过 &lt;strong&gt;TMA 批量传输&lt;/strong&gt;处理这个问题。在 dispatch 阶段拉取 token 数据时，每次 TMA load 传输的是整个 hidden 维度的连续数据（默认 7168 bytes）（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L548&quot;&gt;&lt;code&gt;sm100_fp8_fp4_mega_moe.cuh#L548&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ptx::tma_load_1d(
    pull_buffer.get_base_ptr(),
    sym_buffer.map(input_token_buffer.get_data_buffer(src_token_idx).get_base_ptr(),
                   current_rank_in_expert_idx),
    pull_mbarrier, kHidden);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TMA 是 GPU 的硬件 DMA 引擎，异步执行数据搬运。SM 发射 TMA 指令后可以立即切换到其他 warp 继续计算，不需要自旋等待搬运完成。单次 TMA load 的 payload 达到 KB 级别，摊薄了 NVLink 的固定访问延迟。&lt;/p&gt;
&lt;h3&gt;3.3 Dispatch Pull vs Combine Push&lt;/h3&gt;
&lt;p&gt;MegaMoE 在 dispatch 阶段使用 NVLink read（pull），在 combine 阶段使用 NVLink write（push）。&lt;/p&gt;
&lt;p&gt;代码注释指出 pull 的优势：read 可以避免 write 的 flag 额外延迟。Pull 模式下，发起方完全控制读取时机——只需要知晓远端 buffer 已写入完成（通过 NVLink barrier 保证），不需要远端显式设置 per-transaction flag。Push 模式下，发送方写入后远端必须通过某种同步机制确认 buffer 可用，增加了一轮协调。&lt;/p&gt;
&lt;h3&gt;3.4 适用边界&lt;/h3&gt;
&lt;p&gt;Symmetric Memory 的底层 NVLink P2P 仅在同一 NVSwitch 域内有效。这意味着 MegaMoE 的通信计算融合限于单机/超节点内部。跨节点的 expert dispatch 需要其他机制（如 RDMA 转发），不在 MegaMoE 的设计范围内。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;4. Warp Specialization&lt;/h2&gt;
&lt;p&gt;MegaMoE kernel 占用所有 SM，每个 SM 内部的 warp 被划分为三种功能角色，各自执行不同的代码路径。这是实现通信与计算重叠的核心机制。&lt;/p&gt;
&lt;h3&gt;4.1 线程布局&lt;/h3&gt;
&lt;p&gt;Kernel 模板参数定义了三种角色的线程数量（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L21&quot;&gt;&lt;code&gt;sm100_fp8_fp4_mega_moe.cuh#L21&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;template &amp;lt;
    uint32_t kNumDispatchThreads,        // Dispatch: 可配置
    uint32_t kNumNonEpilogueThreads,     // MMA: 固定 128 (= 4 warps)
    uint32_t kNumEpilogueThreads,        // Epilogue: 可配置
    ...
&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;派生常量：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kNumDispatchWarps = kNumDispatchThreads / 32;
kNumMMANonEpilogueWarps = 128 / 32;  // = 4
kNumEpilogueWarps = kNumEpilogueThreads / 32;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;三种 warp 的寄存器分配（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L346&quot;&gt;&lt;code&gt;sm100_fp8_fp4_mega_moe.cuh#L346&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;constexpr uint32_t kNumDispatchRegisters = 48;
constexpr uint32_t kNumNonEpilogueRegisters = 40;
constexpr uint32_t kNumEpilogueRegisters = 208;
// 约束：总和 ≤ 64512（Blackwell 单 SM 寄存器文件大小）
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Dispatch warp 需要的寄存器最少（48），因为它的主要操作是索引计算和 TMA 发射。MMA warp 只需要 40 个寄存器——矩阵乘法的主要工作状态在 TMEM 中，GPR 仅存储指令描述符和少量控制变量。Epilogue warp 需要 208 个寄存器，因为 SwiGLU 计算、amax reduction、FP8 cast、NVLink 写回等多步操作需要在寄存器中维护大量中间状态。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;每个 SM 内部的 warp 角色分配：

┌──────────────────────┬──────────────────┬──────────────────────┐
│  Dispatch Warps      │  MMA Warps (N)    │  Epilogue Warps      │
│  48 regs/warp        │  40 regs/warp     │  208 regs/warp       │
├──────────────────────┼──────────────────┼──────────────────────┤
│ Expert token 计数     │ TMA Load Token    │ L1: SwiGLU + FP8     │
│ 跨 GPU 写源 token 索引│ TMA Load Weight   │     重量化 + TMA store│
│ NVLink Pull Token    │ UMMA Issue        │ L2: BF16 cast +      │
│ 信号 l1_arrival       │ 信号 tmem_full     │     NVLink write     │
│ Workspace 清理        │                   │ Combine reduce       │
└──────────────────────┴──────────────────┴──────────────────────┘
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4.2 Dispatch Warps&lt;/h3&gt;
&lt;p&gt;Dispatch warp 的入口在 &lt;code&gt;warp_idx &amp;lt; kNumDispatchWarps&lt;/code&gt; 分支（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L359&quot;&gt;&lt;code&gt;sm100_fp8_fp4_mega_moe.cuh#L359&lt;/code&gt;&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 1 — 本地计数&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Dispatch warp 遍历本 GPU 上的所有 token，对每个 token 的 top-k expert 进行 &lt;code&gt;atomicAdd_block&lt;/code&gt; 累加，得到每个 expert 的本地 token 数（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L386&quot;&gt;L386&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 2 — 跨 GPU 通告 token 数&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;每个 expert 的 token 数通过 64-bit &lt;code&gt;atomic_add&lt;/code&gt; 写入 Symmetric Memory workspace 的 &lt;code&gt;expert_send_count&lt;/code&gt;（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L393&quot;&gt;L393&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (uint32_t i = thread_idx; i &amp;lt; kNumExperts; i += kNumDispatchThreads) {
    const uint64_t send_value = (1ull &amp;lt;&amp;lt; 32) | static_cast&amp;lt;uint64_t&amp;gt;(smem_expert_count[i]);
    smem_expert_count[i] = static_cast&amp;lt;uint32_t&amp;gt;(
        ptx::atomic_add(workspace.get_expert_send_count_ptr(i), send_value));
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;64-bit atomic 的高 32 位是「SM 完成计数器」，所有 SM 都写入后其值等于 &lt;code&gt;kNumSMs * kNumRanks&lt;/code&gt;，表示所有 GPU 的所有 SM 都已完成该 expert 的 token 数统计。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 3 — 写源 token 索引到远端&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;dispatch warp 再次遍历 token，这次将 &lt;code&gt;(token_idx, topk_idx)&lt;/code&gt; 组合写入对应 expert 所在 GPU 的 workspace 区域（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L401&quot;&gt;L401&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;*sym_buffer.map(dst_ptr, dst_rank_idx) = token_topk_idx;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;dst_ptr&lt;/code&gt; 指向 expert 所在 GPU 的 &lt;code&gt;src_token_topk_idx&lt;/code&gt; 数组中的位置，&lt;code&gt;sym_buffer.map()&lt;/code&gt; 将其转换为远端可写的指针。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 4 — Grid Sync + NVLink Barrier&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;所有 dispatch warp 完成写入后，执行 grid sync（SM 级同步），然后由 SM 0 的 dispatch warp 通过 &lt;code&gt;red_add_rel_sys&lt;/code&gt; 将 per-rank recv count 搬运到 expert 所在 GPU。最后是 NVLink barrier，确保所有 rank 之间的计数信息完全同步。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Step 5 — Pull Token 数据&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这是 dispatch 与计算重叠的关键阶段。dispatch warp 遍历本 GPU 上的所有 local expert，对每个 expert 通过 Round-Robin Min-Peeling 算法在所有 src rank 之间均衡选取 token。每选取一个 token，发射一次 TMA load 从远端 pull 该 token 的 hidden 向量到本地 SMEM（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L548&quot;&gt;L548&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (cute::elect_one_sync()) {
    ptx::tma_load_1d(
        pull_buffer.get_base_ptr(),
        sym_buffer.map(input_token_buffer.get_data_buffer(src_token_idx).get_base_ptr(),
                       current_rank_in_expert_idx),
        pull_mbarrier, kHidden);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;TMA load 完成后，dispatch warp 将 token 数据从 pull buffer（SMEM）搬到 L1 token buffer（也位于 Symmetric Memory workspace），写入 token 权重和源元数据，然后通过 &lt;code&gt;red_add_rel&lt;/code&gt; 递增 &lt;code&gt;l1_arrival_count&lt;/code&gt;，通知 MMA warp 该 token block 已就绪（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L599&quot;&gt;L599&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ptx::red_add_rel(
    workspace.get_l1_arrival_count_ptr(
        expert_pool_block_offset + token_idx_in_expert / BLOCK_M), 1);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;4.3 MMA Warps — TMA Load 数据 (&lt;code&gt;warp_idx == kNumDispatchWarps&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;该 warp 负责通过 TMA 将 token 激活量（activations）和 scale factor A 从 global memory 搬运到 SMEM，是 MMA 流水线的生产者。通过 &lt;code&gt;scheduler.for_each_block()&lt;/code&gt; 遍历所有待计算的 block（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L666&quot;&gt;L666&lt;/a&gt;）。&lt;/p&gt;
&lt;p&gt;关键同步逻辑在 block 循环开始处（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L682&quot;&gt;L682&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (block_phase == BlockPhase::Linear1) {
    const auto ptr = workspace.get_l1_arrival_count_ptr(pool_block_idx);
    const auto expected = scheduler.get_valid_m&amp;lt;false&amp;gt;();
    while (ptx::ld_acq(ptr) != expected);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里 &lt;code&gt;ld_acq&lt;/code&gt; 是 acquire 语义的 load，等待 dispatch warp 的 &lt;code&gt;red_add_rel&lt;/code&gt;（release 语义）。&lt;code&gt;expected&lt;/code&gt; 是当前 block 中有效 token 的数量（&lt;code&gt;BLOCK_M&lt;/code&gt; 或最后一个 block 的余数）。当所有 token 数据到达后，MMA warp 启动 TMA load 将 token 数据搬入 SMEM。&lt;/p&gt;
&lt;p&gt;对于 L2 phase，同步逻辑不同——它等待的是 L1 epilogue 的结果（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L694&quot;&gt;L694&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;const uint64_t expected = ((1ull &amp;lt;&amp;lt; num_k_blocks) &amp;lt;&amp;lt; num_k_blocks) - 1;
while (ptx::ld_acq_gpu(ptr) != expected);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;因为 &lt;code&gt;BLOCK_K == BLOCK_N&lt;/code&gt;，L1 输出的每个 block 被切分成两半（gate 和 up 分别对应 SwiGLU 的两个输入），所以 L2 需要等待 &lt;code&gt;2 * num_k_blocks&lt;/code&gt; 个 bit 的 mask 全为 1。&lt;code&gt;((1ull &amp;lt;&amp;lt; n) &amp;lt;&amp;lt; n) - 1&lt;/code&gt; 等价于 &lt;code&gt;(1ull &amp;lt;&amp;lt; 2n) - 1&lt;/code&gt;，但避免了 n==32 时的未定义行为。&lt;/p&gt;
&lt;p&gt;TMA load 完成后，warp 通过 &lt;code&gt;full_barrier.arrive()&lt;/code&gt; 通知 MMA issue warp 数据已就绪。&lt;/p&gt;
&lt;h3&gt;4.4 MMA Warps — TMA Load 权重 (&lt;code&gt;warp_idx == kNumDispatchWarps + 1&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;与上一 warp 对称，负责通过 TMA 将权重（weights）和 scale factor B 从 global memory 搬运到 SMEM（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L735&quot;&gt;L735&lt;/a&gt;）。权重数据不需要等待 dispatch 完成，只需要等待流水线中的 consumer release（&lt;code&gt;empty_barriers[stage_idx]-&amp;gt;wait(phase ^ 1)&lt;/code&gt;）。&lt;/p&gt;
&lt;h3&gt;4.5 MMA Warps — Issue (&lt;code&gt;warp_idx == kNumDispatchWarps + 2&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;这是唯一发射 UMMA 指令的 warp，且只有 leader CTA 执行（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L778&quot;&gt;L778&lt;/a&gt;）。2-CTA cluster 中 leader CTA 负责计算，follower CTA 仅提供 TMA load 带宽。&lt;/p&gt;
&lt;p&gt;在每个 K-block 迭代中，warp 先等待 TMA load 完成（&lt;code&gt;full_barriers[stage_idx]-&amp;gt;wait(phase)&lt;/code&gt;），然后通过 UTCCP 将 scale factor 从 SMEM copy 到 TMEM，最后发射 UMMA 指令（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L854&quot;&gt;L854&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for (uint32_t k = 0; k &amp;lt; BLOCK_K / UMMA_K; ++ k) {
    const auto runtime_instr_desc =
        mma::sm100::make_runtime_instr_desc_with_sf_id(instr_desc, k, k);
    ptx::SM100_MMA_MXF8F6F4_2x1SM_SS::fma(
        b_desc, a_desc, accum_stage_idx * UMMA_N,
        k_block_idx &amp;gt; 0 or k &amp;gt; 0,  // clear: 第一个 K-block 需要清零累加器
        runtime_instr_desc,
        kTmemStartColOfSFB, kTmemStartColOfSFA);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;BLOCK_K&lt;/code&gt; 固定为 128，&lt;code&gt;UMMA_K&lt;/code&gt; 为 32，所以每个 block 发射 4 次 UMMA 指令。第一条指令的 clear 标志为 1（累加器初始化为 0），后续指令的 clear 标志为 0（累加到已有结果上）。&lt;/p&gt;
&lt;p&gt;MMA 发射完成后通过 &lt;code&gt;empty_barrier_arrive()&lt;/code&gt; 释放流水线阶段，允许 TMA load warp 继续加载下一批数据。同时，如果当前 block 的所有 K 都已完成，则通过 &lt;code&gt;tmem_full_barriers[accum_stage_idx]-&amp;gt;arrive()&lt;/code&gt; 和 &lt;code&gt;umma_arrive_multicast_2x1SM&lt;/code&gt; 通知 epilogue warp。&lt;/p&gt;
&lt;h3&gt;4.6 Epilogue Warps&lt;/h3&gt;
&lt;p&gt;Epilogue warp 的入口在 &lt;code&gt;warp_idx &amp;gt;= kNumDispatchWarps + kNumMMANonEpilogueWarps&lt;/code&gt;（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L887&quot;&gt;L887&lt;/a&gt;）。这是寄存器需求最高的角色（208 regs/warp）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;L1 Epilogue&lt;/strong&gt;（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L941&quot;&gt;L941&lt;/a&gt;）：&lt;/p&gt;
&lt;p&gt;从 TMEM 加载 GEMM 累加结果，通过 &lt;code&gt;SM100_TMEM_LOAD_16dp256b1x&lt;/code&gt; 以 16 个 float 为粒度读出，然后执行 SwiGLU（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L997&quot;&gt;L997&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// silu(x) = x * sigmoid(x), 其中 sigmoid(x) = 1 / (1 + e^(-x))
auto gate = __bfloat1622float2(bf16_gate);
auto neg_gate_exp = make_float2(
    kFastMath ? __expf(-gate.x) : expf(-gate.x),
    kFastMath ? __expf(-gate.y) : expf(-gate.y));
const auto denom = __fadd2_rn({1.0f, 1.0f}, neg_gate_exp);
gate = {gate.x / denom.x, gate.y / denom.y};
swiglu_values[i * 2 + k] = __fmul2_rn(__fmul2_rn(gate, up), weights);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;kFastMath&lt;/code&gt; 路径使用 &lt;code&gt;__expf()&lt;/code&gt;（内联 PTX 的 &lt;code&gt;ex2.approx&lt;/code&gt; 指令，吞吐远高于 &lt;code&gt;expf()&lt;/code&gt;）和 &lt;code&gt;fast_rcp()&lt;/code&gt;（用牛顿迭代逼近倒数），牺牲末位精度换取吞吐。&lt;/p&gt;
&lt;p&gt;SwiGLU 之后，epilogue warp 执行：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;amax reduction&lt;/strong&gt;：跨 warp 求 max-abs，用于计算 FP8 的 scale factor（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L1024&quot;&gt;L1024&lt;/a&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;FP8 cast&lt;/strong&gt;：将 BF16 结果量化为 FP8 E4M3，写入 SMEM 的 CD buffer（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L1055&quot;&gt;L1055&lt;/a&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TMA store&lt;/strong&gt;：将 FP8 结果通过 TMA 写回 Symmetric Memory workspace 中的 L2 输入区域（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L1099&quot;&gt;L1099&lt;/a&gt;）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;通知 L2&lt;/strong&gt;：通过 &lt;code&gt;red_or_rel_gpu&lt;/code&gt; 设置 &lt;code&gt;l2_arrival_mask&lt;/code&gt; 的对应 bit（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L1118&quot;&gt;L1118&lt;/a&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;L2 Epilogue&lt;/strong&gt;（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L1124&quot;&gt;L1124&lt;/a&gt;）：&lt;/p&gt;
&lt;p&gt;与 L1 epilogue 类似，从 TMEM 读出 GEMM 累加结果，转换为 BF16 后写入 SMEM。然后通过 NVLink write 直接将结果写回远端 GPU 的 combine buffer（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L1212&quot;&gt;L1212&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// 读取 dispatch 阶段存储的源元数据
const auto src_metadata = *workspace.get_token_src_metadata_ptr(m_idx + m_idx_in_block);
const uint32_t dst_rank_idx = src_metadata.rank_idx;
const uint32_t dst_token_idx = src_metadata.token_idx;

// 直接通过 Symmetric Memory 写入远端 GPU
*sym_buffer.map(dst_ptr, dst_rank_idx) = packed;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Combine reduction&lt;/strong&gt;（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L1242&quot;&gt;L1242&lt;/a&gt;）：&lt;/p&gt;
&lt;p&gt;所有 L2 epilogue 完成后，epilogue warp 执行最终的 combine——将同一 token 在不同 expert 上的 top-k 结果按路由权重归约。这通过 TMA load 从 combine buffer 将 chunk 数据搬入 SMEM 逐元素累加，再 TMA store 写回最终的 output tensor。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;5. 通信计算重叠的同步机制&lt;/h2&gt;
&lt;p&gt;MegaMoE 的流水线重叠依赖两个核心同步变量，均存储在 Symmetric Memory workspace 中：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;变量&lt;/th&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;生产者&lt;/th&gt;
&lt;th&gt;消费者&lt;/th&gt;
&lt;th&gt;语义&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l1_arrival_count[pool_block_idx]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uint32_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Dispatch warp (&lt;code&gt;red_add_rel&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;MMA TMA warp (&lt;code&gt;ld_acq&lt;/code&gt; spin)&lt;/td&gt;
&lt;td&gt;一个 token block 的所有 token 已 pull 到本地 L1 buffer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l2_arrival_mask[pool_block_idx]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;uint64_t&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;L1 Epilogue warp (&lt;code&gt;red_or_rel_gpu&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;MMA TMA warp (&lt;code&gt;ld_acq_gpu&lt;/code&gt; spin)&lt;/td&gt;
&lt;td&gt;L1 输出中某个 K 方向的结果已写入，以 bitmask 表示&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;这两个变量实现了三级重叠：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dispatch ↔ L1 GEMM&lt;/strong&gt;：dispatch warp 在 pull token 的同时，MMA warp 在等待 &lt;code&gt;l1_arrival_count&lt;/code&gt;。一旦某个 block 就绪，MMA 立即启动。后续 block 的 NVLink pull 与当前 block 的 GEMM 并发。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;L1 Epilogue ↔ L2 GEMM&lt;/strong&gt;：L1 epilogue 完成后通过 &lt;code&gt;red_or_rel_gpu&lt;/code&gt; 设置 &lt;code&gt;l2_arrival_mask&lt;/code&gt;。L2 MMA warp 等待 mask 全 1 后启动。L1 后处理与 L2 GEMM 的 K-block 迭代卷积。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;L2 Epilogue ↔ Workspace Clean&lt;/strong&gt;：L2 epilogue 的 combine 写回与 dispatch warp 的 workspace 清理通过 &lt;code&gt;sync_unaligned(dispatch + epilogue, barrier)&lt;/code&gt; 交错执行。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;注意：调度器（见第 6 节）保证了每个 wave 内所有 expert 的 L1 全部完成后才启动 L2。这简化了 L2 的同步——开始时大部分 L1 block 的 mask 已经就绪，减少了 L2 MMA warp 的自旋等待时间。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;6. AB Swap&lt;/h2&gt;
&lt;p&gt;在 UMMA 配置中，一个非直观的设计选择是&lt;strong&gt;交换了 A(activation)和 B(weight)两个操作数&lt;/strong&gt;。通常 GEMM 中激活作为 A、权重作为 B，但 MegaMoE 相反（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L162&quot;&gt;&lt;code&gt;sm100_fp8_fp4_mega_moe.cuh#L162&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// NOTES: always swap A/B
constexpr uint32_t UMMA_M = LAYOUT_AD_M * 2;   // = 256 (2-CTA)
constexpr uint32_t UMMA_N = BLOCK_M;            // Swap AB
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这一选择的动机来自 SM100 的 UMMA 指令约束。SM100 UMMA 的 M 维度固定为 128（一 CTA）或 256（2-CTA），而 N 维度可以灵活取值。在 MoE 推理中，尤其是 decode 阶段的小 batch 场景，每个 expert 的 token 数很少，&lt;code&gt;BLOCK_M&lt;/code&gt; 可能取 16、32 等小值。如果将高维的 intermediate_hidden（通常 2048~7168）放在 M 方向，指令的 M=256 约束无法满足。&lt;/p&gt;
&lt;p&gt;通过 AB Swap，权重维度（hidden × intermediate_hidden）对齐到 UMMA 的 M 方向，激活的 token 维度对齐到灵活的 N 方向。这意味着 &lt;code&gt;BLOCK_M&lt;/code&gt; 可以按 token 数自由选择小值（如 16），而不受 UMMA 指令的 256 限制。&lt;/p&gt;
&lt;p&gt;Swap 之后，MMA 中的 A 矩阵是权重（FP4），B 矩阵是激活（FP8）。由于 2-CTA 的 TMA multicast，两个 CTA 各自只需要加载一半的 A tile（&lt;code&gt;LOAD_BLOCK_M = BLOCK_M / 2&lt;/code&gt;）。B tile 由两个 CTA 各自完整加载 &lt;code&gt;BLOCK_N = 128&lt;/code&gt; 宽度。TMA Producer B（权重加载 warp）利用 TMA multicast，一次 load 的权重数据被两个 CTA 共享。&lt;/p&gt;
&lt;p&gt;这一优化在 decode（小 BLOCK_M）和 prefill（大 BLOCK_M）场景下均有效：BLOCK_M 大小由 heuristics 根据 token-per-expert 动态选择，不受指令硬件约束。&lt;/p&gt;
&lt;h2&gt;7. MegaMoEScheduler 与启发式配置&lt;/h2&gt;
&lt;p&gt;MegaMoEScheduler（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/scheduler/mega_moe.cuh&quot;&gt;&lt;code&gt;scheduler/mega_moe.cuh&lt;/code&gt;&lt;/a&gt;）是一个 per-SM 状态机，决定每个 SM 在每一轮分配到哪个 expert 的哪个 block。与调度器紧密配合的是启发式配置模块（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/csrc/jit_kernels/heuristics/mega_moe.hpp&quot;&gt;&lt;code&gt;csrc/jit_kernels/heuristics/mega_moe.hpp&lt;/code&gt;&lt;/a&gt;），它在 JIT 编译期根据运行时参数推导出正确的 kernel 配置。&lt;/p&gt;
&lt;h3&gt;7.1 启发式配置&lt;/h3&gt;
&lt;p&gt;启发式配置需要满足三个约束：正确性、共享内存上限、SM 利用率。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;BLOCK_M 选择&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;get_block_config_for_mega_moe&lt;/code&gt; 根据每 expert 期望 token 数选择 &lt;code&gt;BLOCK_M&lt;/code&gt;，候选值为 &lt;code&gt;{16, 32, 64, 96, 128, 192}&lt;/code&gt;。预期 token 数的计算公式：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;expected_tokens_per_expert = num_tokens × num_ranks × num_topk / num_experts
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;分子是全局所有 token 乘以 topk 的总路由次数，分母是 expert 总数。实际路由不均匀，因此所有估算中引入了 &lt;code&gt;kImbalanceFactor = 2&lt;/code&gt;，把目标工作量放大两倍以吸收热专家的尾延迟。&lt;/p&gt;
&lt;p&gt;BLOCK_M 的选择阶梯为：token 很少时用小 BLOCK_M（16 或 32），避免 M 维度大量 padding 浪费计算；token 多时用大 BLOCK_M（128 或 192），提高单 tile 的算术密度。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Pool 容量&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;pool 容量必须覆盖所有 rank 的所有 token 全部路由到本 rank 的最坏情况（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/layout/mega_moe.cuh#L17&quot;&gt;&lt;code&gt;mega_moe.cuh#L17&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;num_max_recv_tokens = num_ranks × num_max_tokens_per_rank
num_max_experts_per_token = min(num_topk, num_experts_per_rank)
pool_size = align(
    num_max_recv_tokens × num_max_experts_per_token
    + num_experts_per_rank × (kMaxCandidateBlockM - 1),
    kLCMCandidateBlockM)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;其中 &lt;code&gt;num_max_experts_per_token&lt;/code&gt; 是因为一个 token 的 top-k 选择不可能重复落在同一个 expert 上，所以本 rank 最多收到该 token 的 &lt;code&gt;min(num_topk, num_experts_per_rank)&lt;/code&gt; 份副本。额外的 &lt;code&gt;num_experts_per_rank × (kMaxCandidateBlockM - 1)&lt;/code&gt; 是各 expert 之间 BLOCK_M 对齐填充的上界。最终对齐到 &lt;code&gt;kLCMCandidateBlockM = 384&lt;/code&gt;（所有候选 BLOCK_M 的最小公倍数）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Expert Wave 粒度&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;get_num_experts_per_wave_for_mega_moe&lt;/code&gt; 的核心逻辑是：在保证所有 SM 都有 block 可算的前提下，wave 内 expert 越少越好。原因是 expert 少 → L1 整体完成得快 → L2 启动得早 → pipeline 深度浅。&lt;/p&gt;
&lt;p&gt;具体计算：先估计一个 expert 的 L1 block 数（&lt;code&gt;num_m_blocks × num_n_blocks&lt;/code&gt;），然后除以 SM 数得到需要的 expert 数下界。用 &lt;code&gt;kImbalanceFactor = 2&lt;/code&gt; 放大以吸收路由不均。最后向上取整到 &lt;code&gt;num_experts_per_rank&lt;/code&gt; 的因子（scheduler 要求所有 wave 处理相同数量的 expert）。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;SMEM 分配与流水线深度&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;get_pipeline_config_for_mega_moe&lt;/code&gt; 估算共享内存的固定开销和单级流水线开销，然后计算 &lt;code&gt;num_stages = (total_smem - fixed) / per_stage&lt;/code&gt;。固定开销包括 dispatch 区的 expert 计数器和 send buffer、CD 输出区（L1/L2 epilogue 共享 SMEM 的 CD buffer，取两者 max）、amax reduction 区和所有 mbarrier 对象。单级流水线开销包括 A tile + B tile + SFA + SFB + full_barrier + empty_barrier。&lt;/p&gt;
&lt;h3&gt;7.2 Wave 划分&lt;/h3&gt;
&lt;p&gt;MoE 计算被划分为多个 wave，每个 wave 处理 &lt;code&gt;kNumExpertsPerWave&lt;/code&gt; 个 expert，包含两个 phase：L1、L2。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;get_num_experts_per_wave_for_mega_moe&lt;/code&gt; 的选取原则：在保证所有 SM 都有活可干的前提下，expert 越少越好。原因是：expert 少 → L1 完成得快 → L2 启动得早 → pipeline 深度浅、延迟低。但 expert 太少会导致部分 SM 闲置。因此最优取值是刚好能打满所有 SM 的最小 expert 数。&lt;/p&gt;
&lt;h3&gt;6.2 块分配&lt;/h3&gt;
&lt;p&gt;同一个 expert 内部按先 N 方向（output channel）、后 M 方向（token）遍历所有 block。分配策略是 round-robin：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;// fetch_next_l1_block 中
n_block_idx = block_idx - m_block_idx * kNumL1BlockNs;
block_idx += kNumSMs;  // 跳转到下一轮属于本 SM 的 block
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;所有 SM 从自己的 &lt;code&gt;sm_id&lt;/code&gt; 开始，每轮前进 &lt;code&gt;kNumSMs&lt;/code&gt; 步。这保证了每个 SM 的工作量均衡。&lt;/p&gt;
&lt;h3&gt;6.3 状态机&lt;/h3&gt;
&lt;p&gt;核心状态机位于 &lt;code&gt;for_each_block&lt;/code&gt; 调用的 &lt;code&gt;get_next_block()&lt;/code&gt;（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/scheduler/mega_moe.cuh#L148&quot;&gt;L148&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;L1 phase: 遍历当前 wave 所有 expert 的 L1 block
  → L1 完成 → 切换到 L2 phase
L2 phase: 遍历当前 wave 所有 expert 的 L2 block
  → L2 完成 → 切换到下一个 wave 的 L1 phase
所有 wave 完成 → BlockPhase::None → kernel 结束
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;状态机确保了一个关键性质：同一 wave 内，所有 SM 先共同完成所有 expert 的 L1，再切换到 L2。这意味着 L2 开始时大部分 L1 结果已就绪，L2 MMA warp 的自旋等待时间被最小化。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;8. FP8×FP4 混合精度管线&lt;/h2&gt;
&lt;h3&gt;7.1 精度配置&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;分量&lt;/th&gt;
&lt;th&gt;格式&lt;/th&gt;
&lt;th&gt;量化方式&lt;/th&gt;
&lt;th&gt;Block Size&lt;/th&gt;
&lt;th&gt;Scale 格式&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;输入激活&lt;/td&gt;
&lt;td&gt;FP8 E4M3&lt;/td&gt;
&lt;td&gt;per-token&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;UE8M0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L1 权重&lt;/td&gt;
&lt;td&gt;FP4 E2M1&lt;/td&gt;
&lt;td&gt;per-group&lt;/td&gt;
&lt;td&gt;32×32&lt;/td&gt;
&lt;td&gt;UE8M0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L1 输出（L2 输入）&lt;/td&gt;
&lt;td&gt;FP8 E4M3&lt;/td&gt;
&lt;td&gt;per-32&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;UE8M0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L2 权重&lt;/td&gt;
&lt;td&gt;FP4 E2M1&lt;/td&gt;
&lt;td&gt;per-group&lt;/td&gt;
&lt;td&gt;32×32&lt;/td&gt;
&lt;td&gt;UE8M0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;最终输出&lt;/td&gt;
&lt;td&gt;BF16&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;FP4 E2M1 格式：1-bit 符号、2-bit 指数、1-bit 尾数，共 16 个可能值（包含 ±0、±NaN 等特殊值）。有效范围约为 [0.5, 7.5]（不含非正规数）。&lt;/p&gt;
&lt;p&gt;UE8M0 格式：8-bit 无符号整数指数，0-bit 尾数，值为 &lt;code&gt;2^e&lt;/code&gt;。4 个 UE8M0 打包为一个 &lt;code&gt;uint32_t&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;7.2 Block Scaling&lt;/h3&gt;
&lt;p&gt;MegaMoE 的 scaling 是 block-wise 而非 per-tensor 的。对于权重，每个 32×32 的 block 有自己的 scale factor。对于激活，每 32 个元素（在 K 维度上）有一个 scale factor。&lt;/p&gt;
&lt;p&gt;这种粒度避免了 per-tensor scaling 的精度问题：不同 expert 的权重分布可能差异很大，per-tensor scaling 会导致某些 expert 的权重在量化后丧失精度。Block-wise scaling 以存储少量额外 scale 为代价，保证了各 expert 的精度。&lt;/p&gt;
&lt;p&gt;Block scaling 的 UMMA 指令语义为 &lt;code&gt;D = (A * scale_A) * (B * scale_B) + D&lt;/code&gt;。硬件在 MMA 过程中自动应用 scale factor，不增加额外的指令开销。&lt;/p&gt;
&lt;p&gt;SF 存储在 TMEM 中，与累加器共享同一块 TMEM 区域（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/impls/sm100_fp8_fp4_mega_moe.cuh#L217&quot;&gt;L217&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;constexpr uint32_t kNumAccumTmemCols = UMMA_N * kNumEpilogueStages;
constexpr uint32_t kNumSFATmemCols = SF_BLOCK_M / 32;
constexpr uint32_t kNumSFBTmemCols = SF_BLOCK_N / 32;
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;7.3 L1 权重 Interleave&lt;/h3&gt;
&lt;p&gt;L1 权重（gate + up projection）使用 interleave 布局，而非简单的 &lt;code&gt;[gate | up]&lt;/code&gt; 拼接（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/mega/__init__.py#L75&quot;&gt;&lt;code&gt;mega/__init__.py#L75&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# [gate: 0..7, up: 0..7, gate: 8..15, up: 8..15, ...]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这是为了配合 SwiGLU epilogue 的 gate/up pair 消费模式。TMEM load 指令 &lt;code&gt;SM100_TMEM_LOAD_16dp256b1x&lt;/code&gt; 一次读出 8 个值，排列为 &lt;code&gt;(0,2) (1,3) (4,6) (5,7)&lt;/code&gt; 的 gate/up pair。Interleave 布局保证了 gate 和对应位置的 up 在 TMEM 中相邻，简化了 SwiGLU 的索引计算。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;9. NVLink Barrier&lt;/h2&gt;
&lt;p&gt;MegaMoE 定义了三层同步原语（&lt;a href=&quot;https://github.com/deepseek-ai/DeepGEMM/blob/714dd1a4a980f7937a74343d19a8eba4fe321480/deep_gemm/include/deep_gemm/comm/barrier.cuh&quot;&gt;&lt;code&gt;comm/barrier.cuh&lt;/code&gt;&lt;/a&gt;）：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Grid Sync&lt;/strong&gt;：SM 级全局同步。基于 &lt;code&gt;cooperative_groups::this_grid().sync()&lt;/code&gt; 的思想，但使用轻量级的 &lt;code&gt;atomic_add_rel&lt;/code&gt; + &lt;code&gt;ld_acq&lt;/code&gt; 自旋实现。每个 SM 的一个线程递增计数器后自旋等待标志位翻转。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;NVLink Barrier&lt;/strong&gt;：跨 rank 同步。仅 SM 0 参与。使用 &lt;code&gt;red_add_rel_sys&lt;/code&gt;（PTX release-consume atomic add with system scope）向远端 GPU 的 signal buffer 写入信号，接收方自旋等待。超时 30 秒（以 2 GHz 时钟计数），超时打印所有 rank 的同步状态后触发 device assert。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Cluster Sync&lt;/strong&gt;：2-CTA 内同步。使用 SM100 的 &lt;code&gt;ClusterTransactionBarrier&lt;/code&gt;，在 2-CTA cluster 的两个 CTA 之间同步。初始化阶段使用 &lt;code&gt;cluster.arrive.relaxed&lt;/code&gt; + &lt;code&gt;cluster.wait&lt;/code&gt; 的弱序变体。&lt;/p&gt;
&lt;p&gt;三个关键调用点的 tag：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;kBeforeDispatchPullBarrier   — dispatch 开始 pull token 前，确保所有 rank 的计数/索引已完成
kBeforeCombineReduceBarrier  — combine reduction 前，确保所有 rank 的 L2 结果已写回
kAfterWorkspaceCleanBarrier  — workspace 清理完成，确保下次调用时状态正确
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;10. 与 DeepEP 的差异&lt;/h2&gt;
&lt;p&gt;MegaMoE 和 DeepEP 是两种不同的 MoE 推理实现方向：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;DeepEP&lt;/th&gt;
&lt;th&gt;MegaMoE&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;设计层级&lt;/td&gt;
&lt;td&gt;通信库（dispatch / combine 为独立 kernel）&lt;/td&gt;
&lt;td&gt;全融合 kernel（通信嵌入计算）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;目标硬件&lt;/td&gt;
&lt;td&gt;H800 (SM90)&lt;/td&gt;
&lt;td&gt;Blackwell (SM100)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;内核数量&lt;/td&gt;
&lt;td&gt;3+（dispatch、compute、combine 独立）&lt;/td&gt;
&lt;td&gt;1（mega-kernel）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;去重&lt;/td&gt;
&lt;td&gt;src→dst 相同 expert 只传输一次&lt;/td&gt;
&lt;td&gt;按 expert 粒度传输&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;通信域&lt;/td&gt;
&lt;td&gt;NVLink + RDMA（支持跨节点）&lt;/td&gt;
&lt;td&gt;仅 NVLink（单机/超节点）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;中间结果&lt;/td&gt;
&lt;td&gt;HBM&lt;/td&gt;
&lt;td&gt;SMEM/TMEM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;DeepEP 的设计更适合跨节点场景和灵活的组合——用户可以将 dispatch/combine 与任意的 GEMM 实现配合使用。MegaMoE 消除了 kernel 边界和 intermediate write 的开销，但限于 SM100 和单节点，且需要整套流程使用其内部的 GEMM。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;11. 计算-通信比的量化分析&lt;/h2&gt;
&lt;p&gt;MegaMoE 的设计建立在一个基本不等式之上：通信能否完全隐藏，取决于计算量是否足够覆盖通信时间。DeepSeek-V4 技术报告给出了量化结果。&lt;/p&gt;
&lt;p&gt;对于 DeepSeek-V4-Pro 的配置（每 token-专家对的计算量为 SwiGLU 的 gate、up、down 三个投影的总 FLOPs），每 GB/s 的互连带宽足以隐藏约 6.1 TFLOP/s 的计算对应的通信。一旦单 GPU 的 NVLink 带宽满足这个阈值，通信就不再是瓶颈。&lt;/p&gt;
&lt;p&gt;这个结果也解释了为什么 MegaMoE 宣称在小 batch（decode）场景的加速比（最高 1.96×）优于大 batch（prefill）场景（1.50×）：大 batch 时单 expert 的 token 更多，计算时间更长，通信占比本来就低，overlap 带来的收益相对较小。而在 decode 的&quot;长尾小批量&quot;场景，每次 expert 收到的 token 极少（RL rollout 可能每个 expert 只有几个 token），传统分离式方案中通信延迟占比极高，overlap 的效果最显著。&lt;/p&gt;
&lt;p&gt;反过来看，当计算和通信同时被推到极限时，功耗限制（power throttling）、NOC 拥塞、通信引发的 cache miss 等次生问题会浮现。这也是为啥 MegaMoE 目前限制在单节点 NVLink 域内——跨节点的 RDMA 延迟和功耗特征与 NVLink 差别很大，overlap 的设计参数需要重新计算。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;12. 总结&lt;/h2&gt;
&lt;p&gt;MegaMoE 将 MoE 推理的五个阶段合并到单个 kernel 中，利用 Warp Specialization 实现 NVLink 通信与 Tensor Core 计算的流水线重叠。关键设计决策包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Kernel 融合&lt;/strong&gt;：dispatch + L1 GEMM + SwiGLU + L2 GEMM + combine 五合一，中间数据走 SMEM/TMEM&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Warp Specialization&lt;/strong&gt;：四种子角色在同一 SM 内并发，通过 &lt;code&gt;l1_arrival_count&lt;/code&gt;、&lt;code&gt;l2_arrival_mask&lt;/code&gt;、&lt;code&gt;tmem_full/empty_barrier&lt;/code&gt; 等同步原语协调&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Symmetric Memory&lt;/strong&gt;：基于 NVLink P2P 的远端内存直接访问，dispatch 用 pull（NVLink read），combine 用 push（NVLink write）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AB Swap&lt;/strong&gt;：交换 GEMM 的 A/B 操作数以突破 SM100 UMMA 指令的 M=256 维度约束，使 &lt;code&gt;BLOCK_M&lt;/code&gt; 可以自由取小值&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heuristic JIT 配置&lt;/strong&gt;：根据运行时 token 数和硬件参数动态选择 &lt;code&gt;BLOCK_M&lt;/code&gt;、&lt;code&gt;num_experts_per_wave&lt;/code&gt;、&lt;code&gt;num_stages&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计算-通信比&lt;/strong&gt;：每 GB/s NVLink 带宽可隐藏约 6.1 TFLOP/s 计算，构成 overlap 可行的理论基础&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;核心实现约 1380 行 CUDA C++（&lt;code&gt;sm100_fp8_fp4_mega_moe.cuh&lt;/code&gt;），加上调度器 221 行、同步原语 83 行和启发式配置，总计不到 2000 行。&lt;/p&gt;
</content:encoded></item><item><title>PTX ISA</title><link>https://infra.simphoni.uk/posts/ptx-arch/</link><guid isPermaLink="true">https://infra.simphoni.uk/posts/ptx-arch/</guid><pubDate>Sat, 30 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Reference: &lt;a href=&quot;https://docs.nvidia.com/cuda/parallel-thread-execution/&quot;&gt;PTX ISA 8.3 (nvidia.com)&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;编程模型&lt;/h2&gt;
&lt;h3&gt;线程层次结构&lt;/h3&gt;
&lt;p&gt;执行一个内核的一批线程被组织成一个 Grid 执行，CUDA 线程块由 CTA 实现，CUDA cluster 块由 cluster 实现。&lt;/p&gt;
&lt;h4&gt;CTA&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Cooperative Thread Arrays (CTA)&lt;/em&gt; 是一系列并行的线程，他们可以相互通信。线程在 CTA 中的位置可以通过 &lt;code&gt;ntid.{x|y|z}&lt;/code&gt; 向量来描述。&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Parallel Thread Execution (PTX)&lt;/em&gt; 编程模型是显式地并行的：PTX 程序指定 CTA 中的一个线程的执行逻辑。&lt;/p&gt;
&lt;p&gt;一个 warp 是某一个 CTA 的一个子集：这种子集包含最多个能并行执行相同指令的线程。 warp 的大小由硬件决定，PTX 提供立即数 &lt;code&gt;WARP_SZ&lt;/code&gt; 作为 warp 大小。&lt;/p&gt;
&lt;h4&gt;Cluster of CTA&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Cluster&lt;/em&gt; 是一组并行运行的CTA，它们可以通过共享内存进行同步和通信，不显示设置 cluster 时，视为使用以 1x1x1 的 cluster。cluster 仅在 sm_90 下支持。&lt;/p&gt;
&lt;h4&gt;Grid of Cluster/CTA&lt;/h4&gt;
&lt;p&gt;&lt;em&gt;Grid&lt;/em&gt; 可以包含任意多个 Cluster/CTA。Grid 彼此之间可以有依赖关系：一个网格可以是另一个网格的依赖/前置。&lt;/p&gt;
&lt;h3&gt;内存层次结构&lt;/h3&gt;
&lt;p&gt;&lt;img src=&quot;memory-hierarchy-with-clusters.png&quot; alt=&quot;Memory Hierarchy&quot; /&gt;&lt;/p&gt;
</content:encoded></item><item><title>Hello World</title><link>https://infra.simphoni.uk/posts/hello-world/</link><guid isPermaLink="true">https://infra.simphoni.uk/posts/hello-world/</guid><pubDate>Wed, 06 Dec 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome to &lt;a href=&quot;https://hexo.io/&quot;&gt;Hexo&lt;/a&gt;! This is your very first post. Check &lt;a href=&quot;https://hexo.io/docs/&quot;&gt;documentation&lt;/a&gt; for more info. If you get any problems when using Hexo, you can find the answer in &lt;a href=&quot;https://hexo.io/docs/troubleshooting.html&quot;&gt;troubleshooting&lt;/a&gt; or you can ask me on &lt;a href=&quot;https://github.com/hexojs/hexo/issues&quot;&gt;GitHub&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Quick Start&lt;/h2&gt;
&lt;h3&gt;Create a new post&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;$ hexo new &quot;My New Post&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info: &lt;a href=&quot;https://hexo.io/docs/writing.html&quot;&gt;Writing&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Run server&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;$ hexo server
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info: &lt;a href=&quot;https://hexo.io/docs/server.html&quot;&gt;Server&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Generate static files&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;$ hexo generate
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info: &lt;a href=&quot;https://hexo.io/docs/generating.html&quot;&gt;Generating&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Deploy to remote sites&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;$ hexo deploy
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;More info: &lt;a href=&quot;https://hexo.io/docs/one-command-deployment.html&quot;&gt;Deployment&lt;/a&gt;&lt;/p&gt;
</content:encoded></item></channel></rss>