<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>L</title>
  
  <subtitle>make it simple, make it happen.</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://liujunming.github.io/"/>
  <updated>2026-05-05T12:53:23.622Z</updated>
  <id>http://liujunming.github.io/</id>
  
  <author>
    <name>liujunming</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Notes about CUDA Green Context</title>
    <link href="http://liujunming.github.io/2026/05/05/Notes-about-CUDA-Green-Context/"/>
    <id>http://liujunming.github.io/2026/05/05/Notes-about-CUDA-Green-Context/</id>
    <published>2026-05-05T10:59:21.000Z</published>
    <updated>2026-05-05T12:53:23.622Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下CUDA Green Context的相关notes。<a id="more"></a></p><h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p>Green contexts are a lightweight alternative to traditional contexts, that can be used to select a subset of device resources. This allows the developer to, for example, select <a href="/2025/11/30/Notes-of-Basic-Concepts-in-GPU-Computing/#Hardware’s-View">SMs</a> from distinct spatial partitions of the GPU and target them via CUDA stream operations, kernel launches, etc.</p><p>CUDA 中的 Green Context 是一种轻量级的上下文形式，可作为传统 CUDA 上下文的替代方案，为开发者提供更细粒度的 GPU 空间划分与资源分配能力。</p><p>Green Context 使用户能够定义和管理 GPU 资源的独立分区，主要是Streaming Multiprocessors（SM)。你可以将特定数量的 SM 分配给某个特定的 Green Context ，然后在该 context 所拥有的资源范围内启动 CUDA kernel 并管理只在此 context 内运行的 stream。</p><h2 id="技术定位"><a href="#技术定位" class="headerlink" title="技术定位"></a>技术定位</h2><p>Green Contexts 介于 CUDA Streams（动态无分区）和 MPS（有分区但动态不足）之间，支持<strong>单进程内动态 SM 资源分区</strong>，提供确定性的非对称执行能力。</p><p>Green Context enables lightweight <strong>intra-process</strong> spatial sharing. Briefly, we can create multiple CUDA streams with dedicated SM allocations for concurrent GPU kernels.</p><p><img src="/images/2026/05/009.png" alt></p><p>Green Context解决了GPU资源调度的难问题——把”碰运气式”并行升级为”精准规划”。它通过预分配SM资源池，让关键任务能独占专属算力，既保证低延迟响应，又避免多任务互相干扰。</p><h2 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h2><p>一个典型的应用场景是：你的程序中有部分代码对延迟极为敏感，并且需要优先于其他所有 GPU 工作执行。通过为这段代码单独创建一个 Green Context 并分配 SM 资源，而将剩余的 SM 分配给另一个 Green Context 处理其他任务，你就能确保始终有可用的 SM 供高优先级计算使用。</p><p>ASPLOS’26的paper: <a href="https://dl.acm.org/doi/abs/10.1145/3779212.3790236" target="_blank" rel="noopener">Towards High-Goodput LLM Serving with Prefill-decode Multiplexing</a>，就是基于Green Context做的工作，blog可参见<a href="https://www.lmsys.org/blog/2025-09-28-pdmux/" target="_blank" rel="noopener">PD-Multiplexing: Unlocking High-Goodput LLM Serving with GreenContext</a>。</p><h2 id="创建与使用流程"><a href="#创建与使用流程" class="headerlink" title="创建与使用流程"></a>创建与使用流程</h2><p><img src="/images/2026/05/010.png" alt></p><ol><li>查询 GPU 的 SM 数量（Blackwell 为 160）</li><li>制定资源分区策略</li><li>创建分区描述符</li><li>生成 Green Context 沙箱</li><li>从 Context 创建 CUDA Stream</li><li>正常向 Stream 提交核函数</li></ol><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>Green Context 的核心价值，不是简单地“限制 kernel 能用多少个 SM”，而是<u>给 CUDA 提供了一种更可控的资源管理方式</u>。它把原本机会式的并行，进一步变成了可规划的并行。通过把 SM资源按 context 进行划分，应用可以在<strong>低时延、吞吐和隔离性</strong>之间做更灵活的权衡。</p><p>对需要保障关键任务响应时间、减少多 stream 相互干扰、或验证不同资源配比效果的场景来说，Green Context 提供了一种几乎不需要修改 kernel、只需少量 host 侧改造就能落地的新手段。</p><hr><p>参考资料:</p><ol><li><a href="https://mp.weixin.qq.com/s/lDlVLpFHWwd-HE3Muaa-kQ" target="_blank" rel="noopener">刚刚，英伟达CUDA迎来史上最大更新！</a></li><li><a href="https://docs.nvidia.com/cuda/cuda-driver-api/group__CUDA__GREEN__CONTEXTS.html#group__CUDA__GREEN__CONTEXTS" target="_blank" rel="noopener">Green Contexts</a></li><li><a href="https://zhuanlan.zhihu.com/p/1928880421606753954" target="_blank" rel="noopener">简单了解下CUDA Green Context</a></li><li><a href="https://cloud.tencent.com/developer/article/2653795" target="_blank" rel="noopener">一次看懂：CUDA 最新技术与未来 3 年路线图</a></li><li><a href="https://mp.weixin.qq.com/s/daNWAWVamLa7GCI9ug28Tw" target="_blank" rel="noopener">cuda13新特性green context</a></li><li><a href="https://mp.weixin.qq.com/s/IPk6P-DzTr2c6KDJVOFdWg" target="_blank" rel="noopener">PD 多路复用：SGLang 借助 NVIDIA GreenContext 释放高有效吞吐量的大语言模型服务能力</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下CUDA Green Context的相关notes。
    
    </summary>
    
      <category term="GPU" scheme="http://liujunming.github.io/categories/GPU/"/>
    
    
      <category term="GPU" scheme="http://liujunming.github.io/tags/GPU/"/>
    
  </entry>
  
  <entry>
    <title>Notes about AI分布式训练通信原语</title>
    <link href="http://liujunming.github.io/2026/05/01/Notes-about-AI%E5%88%86%E5%B8%83%E5%BC%8F%E8%AE%AD%E7%BB%83%E9%80%9A%E4%BF%A1%E5%8E%9F%E8%AF%AD/"/>
    <id>http://liujunming.github.io/2026/05/01/Notes-about-AI分布式训练通信原语/</id>
    <published>2026-05-01T09:37:34.000Z</published>
    <updated>2026-05-01T10:54:14.455Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下AI分布式训练通信原语的相关notes。<a id="more"></a>内容主要转载自<a href="https://mp.weixin.qq.com/s?__biz=Mzk2NDEyMTM1Mg==&amp;mid=2247488493&amp;idx=1&amp;sn=265f12c2ff6ba43b5c9283724aeff550&amp;scene=21&amp;poc_token=HEfc82mjy30qeDoABDAFRwIy3BlLPJnhv7t6AFwi" target="_blank" rel="noopener">GPU售前知识—AI分布式训练通信原语</a></p><p>在大型AI模型训练中，单机单GPU的配置已无法满足算力与内存的需求。随着模型参数规模的不断扩大，分布式训练已成为深度学习发展的必由之路。而支撑分布式训练最基础的能力正是分布式训练通信原语（Communication Primitives）。</p><h2 id="分布式训练通信原语的概念"><a href="#分布式训练通信原语的概念" class="headerlink" title="分布式训练通信原语的概念"></a>分布式训练通信原语的概念</h2><p>“通信原语”并非指某个具体的框架或API，而是指各种分布式系统中高度抽象、反复出现的基础通信与协同操作。它们定义了在训练过程中多设备、多进程之间如何交换数据、同步状态、维持一致性。无论你使用PyTorch、TensorFlow还是JAX，也无论采用数据并行、模型并行还是混合并行策略，底层实现都依赖这些AI分布式训练通信原语的高效实现。可以说，通信原语的性能直接决定了分布式训练效率的上限。</p><h2 id="常见分布式训练通信原语详解"><a href="#常见分布式训练通信原语详解" class="headerlink" title="常见分布式训练通信原语详解"></a>常见分布式训练通信原语详解</h2><p>基于实际训练中最常见的通信模式，我们在此介绍八种核心AI训练通信原语：广播Broadcast、分散Scatter、聚合Gather、全聚合AllGather、规约Reduce、规约分散ReduceScatter、全规约AllReduce以及全交换All-to-All。</p><h3 id="广播Broadcast"><a href="#广播Broadcast" class="headerlink" title="广播Broadcast"></a>广播Broadcast</h3><ol><li>广播Broadcast是一对多通信原语，即一个发送者对应多个接收者。在集群中，某个节点（或GPU）将其数据广播至所有其他节点。例如将GPU0的数据同步至GPU1、GPU2与GPU3。</li></ol><p><img src="/images/2026/05/001.png" alt></p><ol start="2"><li>广播Broadcast是一对多数据同步机制，能将一个GPU的数据同步至所有其他GPU。其应用场景包括：</li></ol><ul><li>并行数据参数初始化，确保所有GPU的初始参数一致性；</li><li>AllReduce组合（广播Broadcast+规约Reduce）中的广播操作；</li><li>分布式训练参数服务器架构中，主节点向工作节点广播Broadcast数据，再由工作节点将数据规约Reduce回主节点的广播环节。</li></ul><h3 id="分散Scatter"><a href="#分散Scatter" class="headerlink" title="分散Scatter"></a>分散Scatter</h3><ol><li>分散Scatter与广播Broadcast虽同属一对多通信原语，但存在本质区别。分散与广播的核心差异在于：</li></ol><ul><li>广播Broadcast：向所有节点发送<strong>相同的完整数据</strong>。</li><li>分散Scatter：将数据<strong>拆分后分别发送</strong>给不同节点。</li></ul><ol start="2"><li>例如，将一份数据DATA拆分为DATA-A、DATA-B、DATA-C与DATA-D：</li></ol><ul><li>DATA-A → GPU0</li><li>DATA-B → GPU1</li><li>DATA-C → GPU2</li><li>DATA-D → GPU3</li></ul><p><img src="/images/2026/05/002.png" alt></p><ol start="3"><li>分散Scatter的逆操作是聚合Gather，其典型应用场景包括：</li></ol><ul><li>规约分散ReduceScatter组合中的分散Scatter操作；</li><li>模型并行中，初始化时模型参数分散至不同GPU的环节。</li></ul><h3 id="聚合Gather"><a href="#聚合Gather" class="headerlink" title="聚合Gather"></a>聚合Gather</h3><ol><li>聚合Gather是多对一通信原语，即多个数据发送者对应一个数据接收者。它将集群中多个节点的数据汇集到单个节点上。各节点将自身数据发送至主节点，聚合完成后主节点即拥有所有节点的数据。例如：</li></ol><ul><li>GPU0 → DATA-A</li><li>GPU1 → DATA-B</li><li>GPU2 → DATA-C</li><li>GPU3 → DATA-D</li><li>最终主节点将获得完整的DATA-A/B/C/D数据集。</li></ul><p><img src="/images/2026/05/003.png" alt></p><ol start="2"><li>聚合Gather是多对一数据收集方法，将多张GPU卡的数据收集到单张GPU卡上。其逆操作对应分散Scatter，应用场景即规约分散ReduceScatter组合中的分散Scatter环节。</li></ol><h3 id="全聚合AllGather"><a href="#全聚合AllGather" class="headerlink" title="全聚合AllGather"></a>全聚合AllGather</h3><ol><li>全聚合AllGather是多对多通信原语，实现多张GPU卡之间的数据同步全收集。可将其视作聚合与广播操作的组合，即：</li></ol><ul><li>首先，将各节点数据收集至主节点（Gather）；</li><li>随后，将完整数据广播至所有节点（Broadcast）。</li><li>最终Allgather的结果是每个节点都拥有完整数据。</li></ul><p><img src="/images/2026/05/004.png" alt></p><ol start="2"><li>全聚合AllGather的逆操作是规约分散ReduceScatter，其典型应用场景包括：</li></ol><ul><li>并行模型训练场景；</li><li>在并行模型训练中，前向计算所需的参数需要全量同步，此时需要通过AllGather将拆分在不同GPU上的参数同步到单张GPU上才能进行前向计算。</li></ul><h3 id="规约Reduce"><a href="#规约Reduce" class="headerlink" title="规约Reduce"></a>规约Reduce</h3><ol><li>规约（Reduce）是多对一通信原语，用于将多个节点的数据进行归约Reduce计算并将结果汇总至单个节点。常见的规约Reduce操作包括：</li></ol><ul><li>求和（SUM）</li><li>求积（PROD）</li><li>最大值/最小值（MAX/MIN）</li><li>逻辑与/或（LAND/LOR）</li><li>按位与/或/异或（BAND/BOR/BXOR）</li><li>最大值位置/最小值位置（MAXLOC/MINLOC）</li></ul><p><img src="/images/2026/05/005.png" alt></p><ol start="2"><li><p>这些规约Reduce操作通常需要GPU或加速卡硬件支持对应的算子（operator）才能实现高性能。</p></li><li><p>规约Reduce的典型应用场景包括：</p></li></ol><ul><li>全规约AllReduce中的规约Reduce环节；</li><li>规约分散ReduceScatter组合通信中的规约Reduce操作；</li><li>分布式训练参数服务器架构中，Master节点先将模型参数广播Broadcast至所有Worker节点，各Worker完成计算后通过规约Reduce操作将结果聚合回Master节点。</li></ul><h3 id="规约分散ReduceScatter"><a href="#规约分散ReduceScatter" class="headerlink" title="规约分散ReduceScatter"></a>规约分散ReduceScatter</h3><ol><li>规约分散ReduceScatter是多对多通信原语，具有多个数据发送者与多个数据接收者。它在集群所有节点上沿相同维度执行规约Reduce操作，随后将结果分发至集群每个节点。规约分散ReduceScatter等效于在每个节点上执行一次规约Reduce操作后，再进行一次分散Scatter分发操作。其逆操作是全聚合AllGather。</li></ol><p><img src="/images/2026/05/006.png" alt></p><ol start="2"><li>规约分散ReduceScatter是多对多数据操作，采用”先规约Reduce后分发”的方式。它首先对各GPU卡上的数据进行规约（例如求和），再将数据分发（分散Scatter）处理。其应用场景包括：</li></ol><ul><li>规约分散ReduceScatter可同时适用于数据并行与模型并行场景：</li><li>数据并行中规约分散ReduceScatter+全聚合AllGather组合内的规约分散ReduceScatter操作；</li><li>模型并行中前向AllGather后反向计算中的规约分散ReduceScatter环节。</li></ul><h3 id="全规约AllReduce"><a href="#全规约AllReduce" class="headerlink" title="全规约AllReduce"></a>全规约AllReduce</h3><ol><li>全规约AllReduce是多对多通信原语，具有多个数据发送者与多个数据接收者。它在集群所有节点上执行相同的规约Reduce操作，并将各节点的规约结果发送至每个节点。全规约AllReduce可通过在主节点执行规约Reduce+广播Broadcast或通过规约分散ReduceScatter+全聚合AllGather组合实现。</li></ol><p><img src="/images/2026/05/007.png" alt></p><ol start="2"><li>全规约AllReduce是多对多数据规约操作，将集群中所有GPU的数据规约（如求和）后分发至各GPU。其应用场景包括：</li></ol><ul><li>AllReduce可适用于数据并行场景；</li><li>各类通信拓扑中的数据并行场景，例如环式全规约（Ring AllReduce）与树状全规约（Tree AllReduce）中的全规约AllReduce实现。</li></ul><h3 id="全交换All-to-All"><a href="#全交换All-to-All" class="headerlink" title="全交换All-to-All"></a>全交换All-to-All</h3><ol><li>全交换All-to-All操作中，每个节点将数据分散至集群所有节点，同时各节点也从集群所有节点收集数据。全交换All-to-All是全聚合AllGather的扩展形式，其区别在于：全聚合AllGather中不同节点从给定节点收集相同数据，而全交换All-to-All中不同节点从给定节点收集不同数据，本质上实现了数据转置操作。</li></ol><p><img src="/images/2026/05/008.png" alt></p><ol start="2"><li>全交换All-to-All是多对多转置操作，将数据从所有GPU卡转置至集群中每张GPU卡。其主要应用场景包括：</li></ol><ul><li>全交换All-to-All适用于模型并行场景；</li><li>模型并行中的矩阵转置环节；</li><li>从数据并行到模型并行的矩阵转置过程。</li></ul><h2 id="从通信原语到通信库：以NCCL为例"><a href="#从通信原语到通信库：以NCCL为例" class="headerlink" title="从通信原语到通信库：以NCCL为例"></a>从通信原语到通信库：以NCCL为例</h2><p>NCCL（NVIDIA Collective Communications Library）是为GPU间通信提供原语的库。它具有拓扑感知能力，可轻松集成到各类应用中。NCCL实现了集体通信与点对点收发原语，并非完整的并行编程框架，而是专注于加速GPU间通信的工具包。</p><p>NCCL提供的集体通信原语包括AllReduce、Broadcast、Reduce、AllGather、ReduceScatter、AlltoAll、Gather与Scatter。此外，NCCL还支持点对点收发通信，可灵活实现Scatter、Gather或All-to-All操作。</p><p>通过NCCL，通信原语在概念层面被转化为可用的库函数。在传统CUDA编程中，集体通信通常通过多次CUDA内存拷贝操作与本地规约计算内核组合实现；NCCL将每个集体通信原语封装在单个内核中，同步处理通信与计算，从而实现更高效的同步并降低资源开销。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>在分布式深度学习训练中，训练框架本身通常不会直接操作底层通信网络，而是通过高性能通信库完成参数同步、梯度规约等操作。这些通信库既屏蔽了复杂的硬件细节，又提升了训练性能。不同的AI芯片和加速卡厂商会提供专属的通信库或扩展方案，例如硬件感知的MPI实现或自研CCL库，以优化底层网络的使用。</p><p>实际分布式训练集群中的网络互联形态极其多样：既可能采用以太网、InfiniBand、RoCE v1/v2等通用协议，也可能使用NVLink等专用或半专用高速互联协议。这就需要通信库能够结合厂商提供的SDK和接口，针对特定硬件进行优化，例如CUDA-aware MPI、NCCL、NVSHMEM等。同时，还需要根据实际的网络拓扑和节点布局，选择最合适的通信策略与算法。</p><hr><p>参考资料:</p><ol><li><a href="https://mp.weixin.qq.com/s?__biz=Mzk2NDEyMTM1Mg==&amp;mid=2247488493&amp;idx=1&amp;sn=265f12c2ff6ba43b5c9283724aeff550&amp;scene=21&amp;poc_token=HEfc82mjy30qeDoABDAFRwIy3BlLPJnhv7t6AFwi" target="_blank" rel="noopener">GPU售前知识—AI分布式训练通信原语</a></li><li><a href="https://developer.nvidia.com/blog/fast-multi-gpu-collectives-nccl/" target="_blank" rel="noopener">Fast Multi-GPU collectives with NCCL</a></li><li><a href="https://naddod.medium.com/in-depth-understanding-of-ai-distributed-training-communication-primitives-eb3b5fcc1f07" target="_blank" rel="noopener">In-Depth Understanding of AI Distributed Training Communication Primitives</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下AI分布式训练通信原语的相关notes。
    
    </summary>
    
      <category term="AI Infra" scheme="http://liujunming.github.io/categories/AI-Infra/"/>
    
    
      <category term="AI Infra" scheme="http://liujunming.github.io/tags/AI-Infra/"/>
    
  </entry>
  
  <entry>
    <title>Notes about PIM and PNM</title>
    <link href="http://liujunming.github.io/2026/04/26/Notes-about-PIM-Processing-In-Memory-and-PNM-Processing-Near-Memory/"/>
    <id>http://liujunming.github.io/2026/04/26/Notes-about-PIM-Processing-In-Memory-and-PNM-Processing-Near-Memory/</id>
    <published>2026-04-26T10:10:33.000Z</published>
    <updated>2026-04-27T00:14:37.562Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下PIM(Processing-In-Memory)和PNM(Processing-Near-Memory)的相关notes。<a id="more"></a></p><h2 id="Overview"><a href="#Overview" class="headerlink" title="Overview"></a>Overview</h2><p>PIM和PNM是两种用于突破“存储墙”瓶颈的计算架构，旨在通过<strong>将计算能力与内存紧密结合来提高计算效率，减少数据在处理器和内存之间的传输延迟和带宽瓶颈</strong>。</p><p><img src="/images/2026/04/023.png" alt></p><p>As shown in Figure 3 (a), PIM places a processing unit (PU) alongside each memory bank so that parallel computations can be implemented across all memory banks, exploiting the high internal memory bandwidth. A PU can be a MAC (Multiply and Accumulate) unit, a compute core, or a database query processor, specialized in workloads with low arithmetic intensity. However, due to the constraints stemming from the memory process technology applied for the memory core die, PIM logic faces inherent limitations in supporting more complex computations, thereby restricting it to wimpy processing units. On the other hand, as depicted in Figure 3 (b), PNM places processing modules not in the memory core but rather on the data read path between the host processor and the memory node or local main memory. Similar to PIM, PNM is also suitable for workloads with low arithmetic intensity. However, since PNM logic is fabricated using standard logic process nodes, it allows for a broader range of supported operations. Thus, one can fuse multiple kernels into a single module,and exploit high aggregate bandwidth for task-specific computations.</p><h2 id="PIM-存内处理"><a href="#PIM-存内处理" class="headerlink" title="PIM(存内处理)"></a>PIM(存内处理)</h2><p>PIM是<strong>指将计算单元直接集成到内存芯片内部，使得数据可以在存储位置直接进行处理</strong>。通过这种方式，PIM减少了数据在处理器（如CPU、GPU）和内存之间的传输，降低了延迟和能耗。</p><p>优势:</p><ul><li>高带宽利用：内存内的计算能够充分利用内存的高带宽优势，因为计算和数据都在内存内部完成。</li><li>低延迟：减少数据在内存和处理器之间的往返传输，降低整体延迟。</li><li>节能：通过减少数据移动，PIM能够显著降低系统能耗。</li></ul><h2 id="PNM-近存计算"><a href="#PNM-近存计算" class="headerlink" title="PNM(近存计算)"></a>PNM(近存计算)</h2><p>PNM是将计算单元放置在内存附近的芯片上，而不是直接集成在内存内部。虽然不如PIM直接在内存中处理数据，但PNM仍然通过将处理器靠近内存来减少数据传输的延迟。</p><p>相比于PIM，PNM可以在更广泛的硬件配置中实现，因为计算单元和内存是物理分开的，易于升级和扩展。</p><h2 id="PIM-vs-PNM"><a href="#PIM-vs-PNM" class="headerlink" title="PIM vs PNM"></a>PIM vs PNM</h2><ul><li>PIM (Processing-in-Memory, 存内计算): 计算逻辑和存储单元在<strong>同一个die</strong>上.</li><li>PNM (Processing-Near-Memory, 近存计算): 计算逻辑和存储单元在<strong>不同但邻近的die</strong>上.</li></ul><p>下表总结了PIM和PNM在数据中心LLM推理场景的对比:</p><table><thead><tr><th style="text-align:left"></th><th style="text-align:left">PIM</th><th style="text-align:left">PNM</th><th style="text-align:left">胜出者</th></tr></thead><tbody><tr><td style="text-align:left">数据移动功耗</td><td style="text-align:left">非常低 (片上)</td><td style="text-align:left">低 (片外但邻近)</td><td style="text-align:left">PIM</td></tr><tr><td style="text-align:left">带宽(每瓦)</td><td style="text-align:left">非常高 (标准的5-10倍)</td><td style="text-align:left">高 (标准的2-5倍)</td><td style="text-align:left">PIM</td></tr><tr><td style="text-align:left">内存-逻辑耦合</td><td style="text-align:left">内存和逻辑在同一个die上</td><td style="text-align:left">内存和逻辑在分离的die上</td><td style="text-align:left">PNM</td></tr><tr><td style="text-align:left">逻辑PPA</td><td style="text-align:left">在DRAM工艺下逻辑更慢, 功耗更高</td><td style="text-align:left">逻辑工艺有助于性能, 功耗和面积</td><td style="text-align:left">PNM</td></tr><tr><td style="text-align:left">内存密度</td><td style="text-align:left">更差, 因为与逻辑共享面积</td><td style="text-align:left">不受影响</td><td style="text-align:left">PNM</td></tr><tr><td style="text-align:left">商品化内存定价</td><td style="text-align:left">否. 量小, 供应商少, 密度低</td><td style="text-align:left">是. 不受影响</td><td style="text-align:left">PNM</td></tr><tr><td style="text-align:left">功耗/散热预算</td><td style="text-align:left">逻辑在内存die上预算紧张</td><td style="text-align:left">逻辑受限较小</td><td style="text-align:left">PNM</td></tr><tr><td style="text-align:left">软件分片</td><td style="text-align:left">需要为内存bank (如32–64 MB) 分片</td><td style="text-align:left">分片限制较小 (如16–32 GB)</td><td style="text-align:left">PNM</td></tr></tbody></table><h2 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h2><p>针对数据中心LLM <strong>PNM优于PIM</strong>: 尽管PIM在理论带宽和功耗上更有优势, 但PNM在实际应用中更胜一筹.</p><ul><li>软件分片(Sharding): PIM要求将数据切分到极小的内存bank(如32-64MB), 这对于LLM复杂的内存结构来说非常困难. PNM的分片粒度可以大得多(如16-32GB), 易于实现.</li><li>逻辑PPA (性能, 功耗, 面积): PNM的计算逻辑可以使用先进的逻辑工艺制造, PPA更优. 而PIM的计算逻辑受限于DRAM工艺, 性能较差, 功耗较高.</li><li>内存密度与成本: PNM不影响标准内存的密度和商品化定价.</li><li>功耗/散热预算: PIM中计算逻辑的功耗和散热受到DRAM die的严格限制.</li></ul><hr><p>参考资料:</p><ol><li><a href="https://mp.weixin.qq.com/s/sRXZU4B_Tb3JHPjwsccP8Q" target="_blank" rel="noopener">大语言模型推理硬件的挑战与研究方向</a></li><li><a href="https://mp.weixin.qq.com/s/q8ZJ0K4XwhOI1msK1e3ruA" target="_blank" rel="noopener">科普专栏｜PIM PNM对OpenAI O1有多么重要？</a></li><li>Accelerating Retrieval Augmented Language Model via PIM and PNM Integration(MICRO’25)</li><li><a href="https://mp.weixin.qq.com/s/lkaKPrB4jX6_e4pCxzndaw" target="_blank" rel="noopener">PIM Is All You Need: A CXL-Enabled GPU-Free System for Large Language Model Inference</a></li><li><a href="https://events.safari.ethz.ch/micro24-memorycentric-tutorial/lib/exe/fetch.php?media=geraldo-micro24-lecture2-processing-near-memory-beforelecture.pdf" target="_blank" rel="noopener">Processing-Near-Memory Systems: Developments fro Academia &amp; Industry</a></li><li><a href="https://chat.deepseek.com/share/wlf4c0qgxmv4lysv0x" target="_blank" rel="noopener">deepseek对话</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下PIM(Processing-In-Memory)和PNM(Processing-Near-Memory)的相关notes。
    
    </summary>
    
      <category term="体系结构" scheme="http://liujunming.github.io/categories/%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/"/>
    
    
      <category term="体系结构" scheme="http://liujunming.github.io/tags/%E4%BD%93%E7%B3%BB%E7%BB%93%E6%9E%84/"/>
    
  </entry>
  
  <entry>
    <title>Notes about PCIe Flit Mode, PAM4, and FEC</title>
    <link href="http://liujunming.github.io/2026/04/25/Notes-about-PCIe-flit-mode/"/>
    <id>http://liujunming.github.io/2026/04/25/Notes-about-PCIe-flit-mode/</id>
    <published>2026-04-25T14:17:26.000Z</published>
    <updated>2026-04-25T15:06:44.666Z</updated>
    
    <content type="html"><![CDATA[<p>简单来说，Flit Mode（Flow Control Unit）将传统模式下的<strong>不定长</strong>数据包，转变为<strong>固定长度（256字节）</strong>的数据包进行传输。<a id="more"></a></p><p>Flit Mode, PAM4(Pulse Amplitude Modulation with 4 levels), and FEC(Forward Error Correction)这三者构成了 PCIe 6.0 能倍增速率的核心“铁三角”。可以这样理解它们的关系：<strong>PAM4 是提速的“发动机”，FEC 是处理高误码的“安全网”，而 Flit Mode 则是为了让 FEC 能顺利工作的“标准化集装箱”</strong>。</p><p>它们是一条环环相扣的因果链：</p><h2 id="起点：PAM4-提速，但引入了严重的误码"><a href="#起点：PAM4-提速，但引入了严重的误码" class="headerlink" title="起点：PAM4 提速，但引入了严重的误码"></a>起点：PAM4 提速，但引入了严重的误码</h2><p>为了将传输速率从前代的 32 GT/s 翻倍至 64 GT/s，PCIe 6.0 将信号调制方式从 NRZ（1比特/时钟周期）换成了 PAM4（2比特/时钟周期）。代价是信号幅度被分成4级，对噪声更敏感，导致<strong>位错误率（BER）急剧上升</strong>。</p><h2 id="对策：必须用-FEC-主动纠错"><a href="#对策：必须用-FEC-主动纠错" class="headerlink" title="对策：必须用 FEC 主动纠错"></a>对策：必须用 FEC 主动纠错</h2><p>在如此高的错误率下，如果仍沿用传统的“错了就整包重传”机制，链路大部分时间都将浪费在无效的重传上，实际有效带宽可能不升反降。</p><p>因此，必须引入FEC。它在发送端加入校验数据，让接收端能<strong>直接在原地纠正大部分错误</strong>，只有遇到无法纠正的少量错误时才请求重传，从而将有效带宽保持在极高水平。</p><h2 id="条件：FEC-需要定长数据块，催生了-Flit"><a href="#条件：FEC-需要定长数据块，催生了-Flit" class="headerlink" title="条件：FEC 需要定长数据块，催生了 Flit"></a>条件：FEC 需要定长数据块，催生了 Flit</h2><p>FEC 算法(如低密度奇偶校验 LDPC)必须工作在<strong>固定长度的数据块</strong>上，通过计算整个数据块的校验位来纠错。而传统 PCIe 的 TLP长度是可变的，短至几个字节，长至几千字节，完全无法匹配 FEC 的要求。</p><p>于是，Flit应运而生。它把所有数据都打包进<strong>固定的 256 字节“集装箱”</strong>里，FEC 就能以此为基本单位进行编解码和纠错。Flit Mode 便是围绕这种固定包结构建立的全新数据交换规则。</p><h2 id="协同工作的简化流程"><a href="#协同工作的简化流程" class="headerlink" title="协同工作的简化流程"></a>协同工作的简化流程</h2><p>一条数据在 PCIe 6.0 链路中的旅程如下：</p><ol><li>打包：各种不定长的 TLP 被按照 256 字节标准封装进 Flit</li><li>编码纠错：每个 Flit 被加上 FEC 校验位，信号以 PAM4 形式高速发出</li><li>接收纠错：接收端对 PAM4 信号采样，并利用 FEC 对每个 Flit 进行纠错<ul><li>多数情况：FEC 成功纠正了 PAM4 传输引入的错误，数据直接通过</li><li>极少数情况：错误超出了 FEC 能力，则触发选择性重传，只重传出问题的那个 Flit</li></ul></li></ol><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>PAM4 是“因”：提速需求催生了 PAM4，也带来了高误码这个必须解决的技术挑战。</li><li>FEC 是“核心手段”：为对抗高误码而引入的根本性纠错方案。</li><li>Flit 是“必须的结构”：为满足 FEC 对定长数据块的要求而设计的新一代数据传输格式。</li></ul><p>三者共同将 PCIe 6.0 打造成了一个速度极快、纠错极强且效率极高的互连通道。</p><hr><p>参考资料:</p><ol><li><a href="https://pcisig.com/blog/pcie%C2%AE-60-specification-webinar-qa-deeper-dive-flit-mode-pam4-and-forward-error-correction-fec" target="_blank" rel="noopener">A Deeper Dive into FLIT Mode, PAM4, and Forward Error Correction (FEC)</a></li><li><a href="https://chat.deepseek.com/share/6gy0mgd8v8obhkp381" target="_blank" rel="noopener">deepseek对话</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;简单来说，Flit Mode（Flow Control Unit）将传统模式下的&lt;strong&gt;不定长&lt;/strong&gt;数据包，转变为&lt;strong&gt;固定长度（256字节）&lt;/strong&gt;的数据包进行传输。
    
    </summary>
    
      <category term="PCI&amp;PCIe" scheme="http://liujunming.github.io/categories/PCI-PCIe/"/>
    
    
      <category term="PCI&amp;PCIe" scheme="http://liujunming.github.io/tags/PCI-PCIe/"/>
    
  </entry>
  
  <entry>
    <title>Notes about PCIe domain和segment</title>
    <link href="http://liujunming.github.io/2026/04/25/Notes-about-PCIe-domain%E5%92%8Csegment/"/>
    <id>http://liujunming.github.io/2026/04/25/Notes-about-PCIe-domain和segment/</id>
    <published>2026-04-25T12:05:08.000Z</published>
    <updated>2026-04-25T12:17:06.923Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下PCIe domain和segment的相关notes。<a id="more"></a>内容转载自<a href="https://mp.weixin.qq.com/s/n18cF9zP7WzCKJFLDQypmA" target="_blank" rel="noopener">PCIe domain和segment介绍</a></p><p>PCIe Segment（段）是一个硬件层面的概念，指一组完全独立的PCIe总线域；而PCIe Domain（域）是Linux内核在软件层面为每个Segment分配的编号。</p><ul><li>PCIe Segment：是硬件概念。它代表一个完全独立的<strong>PCIe总线树，由独立的Root Complex（根复合体）管理</strong>。不同Segment之间的地址空间和配置空间是互相隔离的。多Segment常见于大型服务器，用于突破单个总线域只能有256个总线的限制。</li><li>PCIe Domain：是Linux内核中的软件表示。内核使用域号来区分不同的硬件Segment。因此，可以在Linux的lspci -t命令的输出中看到“Domain: Bus: Device. Function”的格式，这个Domain号实际上对应的就是硬件Segment。</li></ul><p><img src="/images/2026/04/022.png" alt></p><p>Segment和Domain的核心区别在于：一个Segment是物理上独立的总线树，而一个Domain则是内核给这个树分配的软件编号。举个例子，如果一台服务器有4个物理的PCIe Segment，在Linux中我们就会看到4个Domain（通常编号为0、1、2、3）。</p><p><strong>一个系统中的每个PCIe 设备使用Domain: Bus: Device. Function来唯一标识</strong>，具体含义与取值范围如下：</p><table><thead><tr><th style="text-align:left">标识符</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:left">Domain</td><td style="text-align:left">域号</td><td style="text-align:left">区分不同主机/根复合体（Host Bridge）。</td><td style="text-align:left">0000 - FFFF</td></tr><tr><td style="text-align:left">Bus</td><td style="text-align:left">总线号</td><td style="text-align:left">设备所连接的总线号（总线 0 为起点）。</td><td style="text-align:left">00 - FF</td></tr><tr><td style="text-align:left">Device</td><td style="text-align:left">设备号</td><td style="text-align:left">总线上的设备（槽位 / 逻辑设备），最多 32 个。</td><td style="text-align:left">00 - 1F</td></tr><tr><td style="text-align:left">Function</td><td style="text-align:left">功能号</td><td style="text-align:left">物理设备上的子功能（例如多功能网卡）。</td><td style="text-align:left">0 - 7</td></tr></tbody></table>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下PCIe domain和segment的相关notes。
    
    </summary>
    
      <category term="PCI&amp;PCIe" scheme="http://liujunming.github.io/categories/PCI-PCIe/"/>
    
    
      <category term="PCI&amp;PCIe" scheme="http://liujunming.github.io/tags/PCI-PCIe/"/>
    
  </entry>
  
  <entry>
    <title>每周分享第38期</title>
    <link href="http://liujunming.github.io/2026/04/25/%E6%AF%8F%E5%91%A8%E5%88%86%E4%BA%AB%E7%AC%AC38%E6%9C%9F/"/>
    <id>http://liujunming.github.io/2026/04/25/每周分享第38期/</id>
    <published>2026-04-25T04:03:01.000Z</published>
    <updated>2026-04-25T14:14:02.515Z</updated>
    
    <content type="html"><![CDATA[<h2 id="Prefill-as-a-Service"><a href="#Prefill-as-a-Service" class="headerlink" title="Prefill-as-a-Service"></a>Prefill-as-a-Service</h2><p>核心是将PD分离放在两个或多个Datacenter中的异构GPU集群。</p><p><img src="/images/2026/04/020.png" alt><a id="more"></a></p><ul><li>跨集群边界将Prefill从Decode中分离出来，通过将Prefill迁移到更快的计算硬件，可以降低长上下文请求的成本和延迟</li><li>这个问题的核心障碍在于 KVCache传输量太大。不过最近的混合注意力（Hybrid-attention）架构从根本上改变了这一局面，大幅减少了 KVCache的增长，通常降低了一个数量级</li><li>在真实的场景下由于请求到达的突发性和长短的不均衡，全部通过跨机房的专线传输还是很容易出现拥塞。 系统上我们需要尽可能识别值得传的 KVCache，从而实现跨机房异构 PD 不仅是更便宜，TTFT 还更低这一目标</li><li>最基本的原则就包括短的 incremental prefill 就在本地消化，长的才分到远端 prefill，但实际还需要进一步考虑网络拥塞和不同机房 KVCache 复用命中的情况</li></ul><p><a href="https://mp.weixin.qq.com/s/leWZtUDEh8jteB27F6XkQA" target="_blank" rel="noopener">Prefill-as-a-Service：KVCache的跨数据中心传输</a><br><a href="https://mp.weixin.qq.com/s/9Nm3DammCwa1Tm2pfBvklw" target="_blank" rel="noopener">Prefill-as-a-Service：跨机房异构 PD 分离的最后一块拼图是线性注意力？</a><br><a href="https://mp.weixin.qq.com/s/VvvvYy_c2g4Bnrc2qopiNw" target="_blank" rel="noopener">Kimi新论文：把KVCache玩成新商业模式了</a></p><h2 id="IPADS开源形式化方法智能体FM-Agent"><a href="#IPADS开源形式化方法智能体FM-Agent" class="headerlink" title="IPADS开源形式化方法智能体FM-Agent"></a>IPADS开源形式化方法智能体FM-Agent</h2><p><a href="https://mp.weixin.qq.com/s/AQLsy41Fx9yc5dXlokRI6w" target="_blank" rel="noopener">上海交大IPADS开源形式化方法智能体FM-Agent：让代码不仅可生成，还可推理</a><br><a href="https://mp.weixin.qq.com/s/A_gKk8ls7-w2xYDTLFuyPQ" target="_blank" rel="noopener">编程智能体的隐藏bug，被上交IPADS团队用数学逻辑给揪出来了</a></p><p>如今的Coding Agent生成十万行以上的系统级代码，甚至构建一个完整的编译器，都已不再稀奇。但一个严峻的挑战随之而来：如何保障这些大规模代码的正确性？上海交大IPADS团队推出形式化方法智能体FM-Agent，通过将形式化验证方法与LLM结合，首次实现了面向大规模软件的全自动正确性推理，对27万多行已经过层层测试的系统代码进行“深度体检”，找到522个被遗漏的隐蔽bug。</p><p>霍尔逻辑由图灵奖得主托尼·霍尔于约六十年前提出，但受限于人工成本，形式化方法在大规模软件中的应用始终未能普及。FM-Agent并未追求传统形式化验证所依赖的严格公式证明，而是借助大模型的强大推理能力，首次实现了面向大规模系统软件的全自动正确性推理。这一工作延续了霍尔逻辑的核心思想，站在巨人的肩膀上，同时也为形式化方法的实际落地提供了新的可行路径。</p><h2 id="Harness-Engineering"><a href="#Harness-Engineering" class="headerlink" title="Harness Engineering"></a>Harness Engineering</h2><p><a href="https://mp.weixin.qq.com/s/jlYHOardcQaEx4BdMuNOPA" target="_blank" rel="noopener">别再说”Prompt工程”了！2026全网爆火的Harness Engineering是什么鬼？</a><br><img src="/images/2026/04/021.png" alt></p><h2 id="A-Survey-of-Context-Engineering-for-Large-Language-Models"><a href="#A-Survey-of-Context-Engineering-for-Large-Language-Models" class="headerlink" title="A Survey of Context Engineering for Large Language Models"></a>A Survey of Context Engineering for Large Language Models</h2><p><a href="https://mp.weixin.qq.com/s/deBKVO_TpuoYIfaXb6KlWw" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/deBKVO_TpuoYIfaXb6KlWw</a></p><p><a href="https://mp.weixin.qq.com/s/9KrnTk9LwWGmsiaypu-AVw" target="_blank" rel="noopener">上下文工程（Context Engineering）原理简介</a></p><h2 id="Nsight-Systems"><a href="#Nsight-Systems" class="headerlink" title="Nsight Systems"></a>Nsight Systems</h2><p>NVIDIA Nsys 通常指的是 NVIDIA Nsight Systems（命令行工具<code>nsys</code>），是 NVIDIA 官方的系统级性能分析工具。它主要用于对 CUDA 应用程序进行全系统时间线分析，帮助开发者快速定位 CPU 和 GPU 之间的瓶颈，而不仅仅是 GPU 内核内部的耗时。</p><p><a href="https://chat.deepseek.com/share/kw68e7wlf5s356if9u" target="_blank" rel="noopener">deepseek对话</a></p><h2 id="Nsight-Compute"><a href="#Nsight-Compute" class="headerlink" title="Nsight Compute"></a>Nsight Compute</h2><p>Nsight Compute：专攻 GPU 内核内部的微架构分析（如带宽、占用率、指令吞吐），属于“内核级”分析。</p><p><a href="https://developer.nvidia.com/nsight-compute" target="_blank" rel="noopener">https://developer.nvidia.com/nsight-compute</a></p><h2 id="manim"><a href="#manim" class="headerlink" title="manim"></a>manim</h2><p>可视化数学<br><a href="https://github.com/3b1b/manim" target="_blank" rel="noopener">https://github.com/3b1b/manim</a></p><h2 id="dmidecode"><a href="#dmidecode" class="headerlink" title="dmidecode"></a>dmidecode</h2><p><a href="https://github.com/mirror/dmidecode" target="_blank" rel="noopener">https://github.com/mirror/dmidecode</a></p><p>Dmidecode reports information about your system’s hardware as described in your system BIOS according to the SMBIOS/DMI standard. This information typically includes system manufacturer, model name, serial number, BIOS version, asset tag as well as a lot of other details of varying level of interest and reliability depending on the manufacturer. This will often include usage status for the CPU sockets, expansion slots (e.g. AGP, PCI, ISA) and memory module slots, and the list of I/O ports (e.g. serial, parallel, USB).</p><h2 id="2025阿里云技术年报-基础设施篇"><a href="#2025阿里云技术年报-基础设施篇" class="headerlink" title="2025阿里云技术年报 基础设施篇"></a>2025阿里云技术年报 基础设施篇</h2><p><a href="https://mp.weixin.qq.com/s/ykEFWsM1VrYcDSj9KRdzaQ" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/ykEFWsM1VrYcDSj9KRdzaQ</a></p><h2 id="如何在短时间内提升自己"><a href="#如何在短时间内提升自己" class="headerlink" title="如何在短时间内提升自己"></a>如何在短时间内提升自己</h2><p><a href="https://mp.weixin.qq.com/s/LdeBYWcxb3ZSASf6aGo7aQ" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/LdeBYWcxb3ZSASf6aGo7aQ</a></p>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;Prefill-as-a-Service&quot;&gt;&lt;a href=&quot;#Prefill-as-a-Service&quot; class=&quot;headerlink&quot; title=&quot;Prefill-as-a-Service&quot;&gt;&lt;/a&gt;Prefill-as-a-Service&lt;/h2&gt;&lt;p&gt;核心是将PD分离放在两个或多个Datacenter中的异构GPU集群。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2026/04/020.png&quot; alt&gt;
    
    </summary>
    
      <category term="经验" scheme="http://liujunming.github.io/categories/%E7%BB%8F%E9%AA%8C/"/>
    
    
      <category term="经验" scheme="http://liujunming.github.io/tags/%E7%BB%8F%E9%AA%8C/"/>
    
  </entry>
  
  <entry>
    <title>Notes about Intel&#39;s Flat Memory Mode</title>
    <link href="http://liujunming.github.io/2026/04/19/Notes-about-Intel-s-flat-memory-mode/"/>
    <id>http://liujunming.github.io/2026/04/19/Notes-about-Intel-s-flat-memory-mode/</id>
    <published>2026-04-19T02:03:16.000Z</published>
    <updated>2026-04-19T09:30:25.908Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下Intel Flat Memory Mode (FMM) 的相关notes。<a id="more"></a></p><h2 id="Backgrpund"><a href="#Backgrpund" class="headerlink" title="Backgrpund"></a>Backgrpund</h2><p><img src="/images/2026/04/010.png" alt></p><p><img src="/images/2026/04/011.png" alt></p><p><img src="/images/2026/04/012.png" alt></p><h2 id="Overview"><a href="#Overview" class="headerlink" title="Overview"></a>Overview</h2><p><img src="/images/2026/04/013.png" alt></p><p>This design fully utilizes the capacity of both local DRAM and CXL memory by placing data <code>exclusively</code> at either of them, but not both. For example, once a cacheline is moved to local DRAM, it will no longer occupy any space in CXL memory.</p><p>The associativity between physical memory and local memory is direct-mapped, which means each line in the physical memory address space can only be cached at one location in local memory.</p><p><img src="/images/2026/04/014.png" alt></p><p><img src="/images/2026/04/015.png" alt></p><p><img src="/images/2026/04/016.png" alt></p><p><img src="/images/2026/04/017.png" alt></p><h2 id="Details"><a href="#Details" class="headerlink" title="Details"></a>Details</h2><p>参考<a href="https://www.usenix.org/system/files/osdi24-zhong-yuhong.pdf" target="_blank" rel="noopener">Managing Memory Tiers with CXL in Virtualized Environments</a>中的3.1 即可。</p><p><img src="/images/2026/04/018.png" alt></p><p><img src="/images/2026/04/019.png" alt></p><hr><p>参考资料:</p><ol><li><a href="https://www.intel.com/content/www/us/en/content-details/886601/the-advantages-of-managing-the-cxl-memory-tier-in-hardware.html" target="_blank" rel="noopener">The Advantages of Managing the CXL Memory Tier in Hardware</a></li><li>Managing Memory Tiers with CXL in Virtualized Environments(OSDI’24)</li><li><a href="https://chat.deepseek.com/share/r66602rkw3x1tc5xdl" target="_blank" rel="noopener">deepseek会话</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下Intel Flat Memory Mode (FMM) 的相关notes。
    
    </summary>
    
      <category term="Intel" scheme="http://liujunming.github.io/categories/Intel/"/>
    
    
      <category term="内存管理" scheme="http://liujunming.github.io/tags/%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86/"/>
    
      <category term="Intel" scheme="http://liujunming.github.io/tags/Intel/"/>
    
  </entry>
  
  <entry>
    <title>Notes about IB交换机中的SHARP技术</title>
    <link href="http://liujunming.github.io/2026/04/18/Notes-about-IB%E4%BA%A4%E6%8D%A2%E6%9C%BA%E4%B8%AD%E7%9A%84SHARP%E6%8A%80%E6%9C%AF/"/>
    <id>http://liujunming.github.io/2026/04/18/Notes-about-IB交换机中的SHARP技术/</id>
    <published>2026-04-18T07:48:27.000Z</published>
    <updated>2026-04-18T14:49:16.749Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下IB交换机中SHARP(Scalable Hierarchical Aggregation and Reduction Protocol)技术的相关notes。<a id="more"></a></p><h2 id="In-Network-Computing"><a href="#In-Network-Computing" class="headerlink" title="In-Network Computing"></a>In-Network Computing</h2><p>在网计算(In-Network Computing)，可以简单理解为：让网络在传输数据的过程中，顺便完成一部分原本属于主机的计算任务。这里的“计算”通常不是通用计算，而是聚合、归约、统计、筛选，以及某些固定模式的算术或逻辑操作。</p><p><img src="/images/2026/04/008.png" alt></p><p>在 AI 和 HPC 场景中，最有价值的一类在网计算，就是对集合通信中的归约操作进行卸载。因为归约是最常见、最频繁、也最容易在规模扩展后成为瓶颈的环节；如果交换机能够在数据流经时，先把多个节点发来的数据做一轮聚合，那么继续向上传输的数据量就会变少，最终回到端点的也不再是大量原始中间值，而是更接近结果的数据。</p><p>这会同时带来几个好处：</p><ol><li>降低端点参与归约的负担</li><li>减少网络中传输的中间数据</li><li>缩短集合通信完成时间</li><li>提高系统扩展效率</li></ol><p>而 SHARP，就是这种思想在高性能网络中的代表性实现。</p><h2 id="SHARP的介绍"><a href="#SHARP的介绍" class="headerlink" title="SHARP的介绍"></a>SHARP的介绍</h2><p>传统模式下，交换机只负责收包、转发、出包；即使是 AllReduce 这类高度结构化的操作，交换机本身也并不真正“理解”归约，因此大量中间数据仍需要在端点之间来回流动，归约主要还是由主机侧完成。</p><p>SHARP(Scalable Hierarchical Aggregation and Reduction Protocol)是 NVIDIA 的一种<strong>in-network computing</strong>技术，<u>用来把 AllReduce、Reduce、Broadcast 等集合通信操作从 CPU/GPU 卸载到 InfiniBand 交换网络中执行</u>。</p><h2 id="AllReduce"><a href="#AllReduce" class="headerlink" title="AllReduce"></a>AllReduce</h2><p>现代AI训练（如大语言模型）和科学计算严重依赖于<strong>集合通信</strong>，尤其是 <strong>AllReduce</strong> 操作（用于同步梯度、参数等）。AllReduce的通信开销常常成为训练瓶颈。</p><ol><li>传统AllReduce（无SHARP）</li></ol><ul><li>数据在GPU间多次传输。</li><li>最终聚合计算由某个GPU的CUDA核心完成。</li><li>占用宝贵的GPU计算资源（尽管是轻量计算）。</li><li>产生大量网络流量，消耗带宽，增加延迟。</li></ul><ol start="2"><li>使用SHARP的AllReduce</li></ol><ul><li>计算卸载： 聚合计算（如求和）由交换机内部的专用硬件引擎执行。</li><li>流量锐减： 数据在交换机树形网络的每一级就开始聚合，网络中传输的数据量逐级减少，极大降低了最终的网络流量（可降低高达50%以上）。</li><li>解放GPU： GPU无需处理聚合计算，可以更专注于张量核心的计算。</li><li>降低延迟： 在网络中就近计算，减少了端到端的通信延迟。</li></ul><ol start="3"><li>核心价值： 将网络从一个被动的“数据搬运工”，转变为一个主动的“计算参与者”，从而打破集合通信的瓶颈。</li></ol><h2 id="工作原理"><a href="#工作原理" class="headerlink" title="工作原理"></a>工作原理</h2><p><img src="/images/2026/04/009.png" alt></p><p>以最常见的“求和”AllReduce为例，剖析SHARP工作原理：</p><ol><li>初始化与配置： 集群管理软件（如NCCL）识别到支持SHARP的交换机拓扑，并为本次AllReduce操作在交换机上配置一个“聚合树”。</li><li>Leaf叶子节点发送： 每个GPU（主机）将其需要聚合的数据块发送到它所连接的第一级（Leaf叶子）交换机。</li><li>第一级聚合： Leaf叶子交换机的SHARP引擎接收来自其下所有GPU的数据，在交换机内部硬件中直接进行求和计算，生成一个部分聚合的结果。</li><li>向上传播： Leaf叶子交换机将部分聚合的结果（数据量已小于原始多份数据的总和）发送到上一级（Spine主干）交换机。</li><li>递归聚合： Spine主干交换机的SHARP引擎再次接收来自多个下级交换机的部分聚合结果，并进行第二次聚合。此过程在交换机的层次结构中持续向上，直到到达聚合树的根交换机。</li><li>生成全局结果： 根交换机生成最终的全局聚合结果（所有GPU数据的总和）。</li><li>结果广播： 根交换机再将这个最终结果沿聚合树向下广播到所有参与计算的GPU。</li></ol><p>关键点： 数据在向上传输的过程中不断被“压缩”（聚合），因此从根节点向下广播的数据量是最小的（一份完整结果）。这相比于传统的环状或树状AllReduce算法，显著减少了网络的总数据吞吐量。</p><h2 id="SHARP-vs-GPUDirect-RDMA"><a href="#SHARP-vs-GPUDirect-RDMA" class="headerlink" title="SHARP vs. GPUDirect RDMA"></a>SHARP vs. GPUDirect RDMA</h2><ol><li>GPUDirect RDMA： 解决的是“路径”问题，允许第三方设备（如网卡）直接访问GPU显存，绕过CPU和系统内存拷贝，降低延迟。它优化的是点对点通信。</li><li>SHARP： 解决的是“流量和计算”问题，在网络内对多个数据流进行聚合计算，优化的是集体通信。</li><li>关系： 它们是互补的，可以同时启用。GPUDirect RDMA确保数据从GPU到网络的路径最优，而SHARP确保数据在网络中的聚合效率最高。现代AI集群通常同时启用这两项技术。</li></ol><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>SHARP是构建大规模、高效率GPU计算集群的一项革命性网络技术。它通过“网络内计算”的理念，直接攻克了分布式AI训练中最耗时的集合通信瓶颈，是当今万卡级GPU集群不可或缺的关键技术之一。</p><hr><p>参考资料:</p><ol><li><a href="https://zhuanlan.zhihu.com/p/27394787474" target="_blank" rel="noopener">【论文阅读】Scalable Hierarchical Aggregation Protocol (SHArP)</a></li><li><a href="https://conferences.sigcomm.org/events/apnet2019/slides/Industrial_1_3.pdf" target="_blank" rel="noopener">Pushing the Limits of AI with In-Network Computing</a></li><li><a href="https://mp.weixin.qq.com/s/GkctRBBjRyhraIfBdTKX4Q" target="_blank" rel="noopener">GPU集群性能提升技术——IB交换机中的SHARP详解</a></li><li><a href="https://mp.weixin.qq.com/s/YhD_e6kH9lhA360t5yC2iQ" target="_blank" rel="noopener">SHARP与在网计算</a></li><li><a href="https://mp.weixin.qq.com/s/K5o57R5bdW6DjUkme0Gf8g" target="_blank" rel="noopener">NCCL 原理详解：让多GPU通信更高效</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下IB交换机中SHARP(Scalable Hierarchical Aggregation and Reduction Protocol)技术的相关notes。
    
    </summary>
    
      <category term="AI Infra" scheme="http://liujunming.github.io/categories/AI-Infra/"/>
    
    
      <category term="AI Infra" scheme="http://liujunming.github.io/tags/AI-Infra/"/>
    
      <category term="RDMA" scheme="http://liujunming.github.io/tags/RDMA/"/>
    
  </entry>
  
  <entry>
    <title>每周分享第37期</title>
    <link href="http://liujunming.github.io/2026/04/18/%E6%AF%8F%E5%91%A8%E5%88%86%E4%BA%AB%E7%AC%AC37%E6%9C%9F/"/>
    <id>http://liujunming.github.io/2026/04/18/每周分享第37期/</id>
    <published>2026-04-18T06:08:42.000Z</published>
    <updated>2026-04-18T07:36:13.972Z</updated>
    
    <content type="html"><![CDATA[<h2 id="CubeSandbox"><a href="#CubeSandbox" class="headerlink" title="CubeSandbox"></a>CubeSandbox</h2><ul><li><a href="https://mp.weixin.qq.com/s/d6toVeZzrUc1C4g1EJRPnQ" target="_blank" rel="noopener">当 Docker 不再安全：腾讯云 CubeSandbox 如何用 Rust+KVM 重塑 AI Agent 沙箱</a></li><li><a href="https://github.com/TencentCloud/CubeSandbox" target="_blank" rel="noopener">TencentCloud/CubeSandbox</a><a id="more"></a></li></ul><p><img src="/images/2026/04/005.png" alt></p><p><strong>核心优势</strong></p><ul><li>极致冷启动： 基于资源池化预置和快照克隆技术，直接跳过耗时初始化流程。整个沙箱服务端到端冷启动一个可服务的沙箱时间平均 &lt; 60ms</li><li>单机千例的高密部署： 基于 CoW 技术实现极致内存复用，用 Rust 重构底层极致裁剪，使得单实例内存开销低至 &lt;5MB，轻松在一台机器上跑起数千个 Agent。</li><li>真正的内核级隔离： 告别不安全的 Docker 共享内核（Namespace）。每个 Agent 拥有独立的 Guest OS 内核，杜绝容器逃逸，放心运行任何大模型生成的未知代码。</li><li>零成本迁移（E2B 完美平替）： 原生兼容 E2B SDK 接口规范。只需替换一个 URL 环境变量，无需业务代码改动就可切换到免费的 Cube Sandbox，并获得更好的性能体验。</li><li>网络安全： 基于 eBPF 的 CubeVS 在内核态实现严格的沙箱间网络隔离，支持细粒度出站流量过滤策略。</li><li>开箱即用： 可一键快速部署，同时支持单机部署和集群部署。</li><li>事件级快照回滚（coming soon）： 百毫秒级的高频快照回滚能力，基于快照快速创建分叉探索环境</li></ul><p>历史文档:</p><ul><li><a href="https://mp.weixin.qq.com/s/r22ECd7t_alO8VfxTWOU_w" target="_blank" rel="noopener">Cube轻量虚拟化如何做到100ms交付一个安全容器</a></li></ul><h2 id="IPADS开源SkVM"><a href="#IPADS开源SkVM" class="headerlink" title="IPADS开源SkVM"></a>IPADS开源SkVM</h2><p><a href="https://mp.weixin.qq.com/s/W9zPy0R8eqIPjh3MzWoAbg" target="_blank" rel="noopener">上海交大IPADS开源SkVM：让Agent Skill”一次编写，处处高效运行”</a></p><p>Agent时代重新思考编译技术：Skill是代码，LLM+Harness是异构处理器，借鉴语言虚拟机（Language VM）的设计理念，首次将传统编译器与运行时思想系统性地引入Agent技能领域，<strong>SkVM让Skill一次编写，到处高效执行</strong>。</p><p>核心理念：把Skill当作程序来编译</p><p><img src="/images/2026/04/006.png" alt></p><h2 id="英伟达-GPU-机密计算"><a href="#英伟达-GPU-机密计算" class="headerlink" title="英伟达 GPU 机密计算"></a>英伟达 GPU 机密计算</h2><p><a href="https://mp.weixin.qq.com/s/Zx2ocq9RTSx3AsNch0AUYg" target="_blank" rel="noopener">英伟达 GPU 机密计算：AI 时代机密计算边界的延伸</a></p><p>传统机密计算主要保护 CPU 执行环境中的数据与代码，其目标是在操作系统、虚拟化层乃至平台管理员不完全可信的前提下，仍然保证工作负载的机密性与完整性。Intel TDX、AMD SEV-SNP 和 Arm CCA 虽然实现路径不同，但本质上都属于 CPU 侧可信执行环境基础设施：通过硬件隔离、内存保护、启动测量和远程证明，为虚拟机或受保护执行域建立一个不依赖宿主软件信任的安全边界。<strong>它们解决的核心问题是，应用在 CPU 和系统内存中运行时，如何不被宿主环境窥探或篡改</strong>。</p><p>但在 AI 基础设施中，仅有 CPU 侧保护并不充分。因为真正承载高价值数据和核心计算的，往往已经不是 CPU，而是 GPU。<strong>模型权重、推理输入、检索增强数据、中间激活值乃至部分业务逻辑，都会进入 GPU 显存并在加速器上执行</strong>。如果机密计算只覆盖 CPU 虚拟机，而无法覆盖 GPU 执行路径，那么对 AI 而言，这种保护就是不完整的。英伟达 GPU 机密计算的意义，正是在于<strong>把机密计算的保护边界从 CPU 扩展到 GPU，使 GPU 成为整个可信执行体系的一部分，保护模型参数、数据和其他重要客户资产</strong>。</p><p><img src="/images/2026/04/007.png" alt></p><h2 id="为什么-AI-时代值得重新讨论-OS：从-Linux-Kernel-到-GPU-执行栈的系统重构"><a href="#为什么-AI-时代值得重新讨论-OS：从-Linux-Kernel-到-GPU-执行栈的系统重构" class="headerlink" title="为什么 AI 时代值得重新讨论 OS：从 Linux Kernel 到 GPU 执行栈的系统重构"></a>为什么 AI 时代值得重新讨论 OS：从 Linux Kernel 到 GPU 执行栈的系统重构</h2><p><a href="https://mp.weixin.qq.com/s/dVpd5_99co4wk0L-tOpiJQ" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/dVpd5_99co4wk0L-tOpiJQ</a></p><p>AI时代的操作系统革新，核心不在于推翻Linux，而在于围绕<code>tensor</code>、<code>graph</code>、<code>kernel</code>、<code>KV cache</code>等新的一等对象，建立一套从驱动、编译器到运行时服务的全新系统抽象，以管理和调度异构计算资源。</p><h2 id="DPU-PCC"><a href="#DPU-PCC" class="headerlink" title="DPU PCC"></a>DPU PCC</h2><p><a href="https://mp.weixin.qq.com/s/Br_DimiEOPkjBYy4Kw_d9A" target="_blank" rel="noopener">DPU PCC：为什么拥塞控制从“固定算法”走向“可编程”</a></p><p>DOCA 官方给出的定义非常直接：<strong>Programmable Congestion Control（PCC）允许用户设计并实现自定义的拥塞控制算法，以更灵活地处理集群中的网络拥塞问题</strong>。<br>PCC 不是一个具体的拥塞控制算法，而是一个<strong>拥塞控制开发框架</strong>。它的目标是提供一套 API 和执行环境，让客户可以自己写算法、加载算法、运行算法，并基于网络反馈动态调整每条流的发送速率。</p><p>DPU PCC 的本质，是把拥塞控制从一个封闭的网卡内置算法，升级成一个运行在 DPU 数据路径加速环境中的可编程控制框架。它让开发者能够围绕真实业务需求，自定义反馈机制、流状态管理和速率调节逻辑，从而在 AI、存储和多租户集群中获得更合适的网络行为。</p><h2 id="Sandlock：最轻量级的-AI-Agent-沙箱"><a href="#Sandlock：最轻量级的-AI-Agent-沙箱" class="headerlink" title="Sandlock：最轻量级的 AI Agent 沙箱"></a>Sandlock：最轻量级的 AI Agent 沙箱</h2><p>The lightest AI sandbox. A process-based sandbox for Linux, no container, no VM, no root.</p><p>应对AI Agent的安全问题，不应盲目堆叠重量级的硬件隔离，而应针对其应用层的行为模式，设计精细、轻量的访问控制策略。Sandlock正是这一理念的实践，它提供了一种更贴合Agent本质的安全方案。</p><ul><li><a href="https://mp.weixin.qq.com/s/ICxIj6ydpftSLwgjA9zZAg" target="_blank" rel="noopener">https://mp.weixin.qq.com/s/ICxIj6ydpftSLwgjA9zZAg</a></li><li><a href="https://github.com/multikernel/sandlock" target="_blank" rel="noopener">https://github.com/multikernel/sandlock</a></li></ul><p>Lightweight process sandbox for Linux. Confines untrusted code using Landlock (filesystem + network + IPC), seccomp-bpf (syscall filtering), and seccomp user notification (resource limits, IP enforcement, /proc virtualization). No root, no cgroups, no containers.<br><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">sandlock run -w /tmp -r /usr -r /lib -m 512M -- python3 untrusted.py</span><br></pre></td></tr></table></figure></p><h2 id="Bubblewrap-vs-Sandlock"><a href="#Bubblewrap-vs-Sandlock" class="headerlink" title="Bubblewrap vs Sandlock"></a>Bubblewrap vs Sandlock</h2><p>Bubblewrap和Sandlock是两种设计理念和实现路径都截然不同的沙箱工具。简单来说，Bubblewrap是一个通用的、轻量级的“容器构建工具箱”，而Sandlock是一个为AI Agent场景专门设计的、高密度的“进程执行沙箱”。</p><h3 id="目标定位不同"><a href="#目标定位不同" class="headerlink" title="目标定位不同"></a>目标定位不同</h3><p><a href="/2026/03/22/Notes-about-Bubblewrap/">Bubblewrap</a>是一个通用的工具，旨在安全地运行一个浏览器或一个游戏等普通应用。而Sandlock则是专为AI Agent量身定做，它思考的问题是：“如何安全、高效地让大模型生成的上万个代码片段并发执行？”。</p><h3 id="安全模型的根本分歧"><a href="#安全模型的根本分歧" class="headerlink" title="安全模型的根本分歧"></a>安全模型的根本分歧</h3><p>这源于它们对“敌人”的不同理解。</p><ul><li>Bubblewrap默认环境中可能<strong>存在主动的攻击者</strong>，因此首要任务是利用Namespace创建一个与外界隔绝的<strong>“硬边界”</strong>。</li><li>Sandlock则认为Agent不是攻击者，真正的风险是提示词注入。它的核心不是建立边界，而是通过Landlock和Seccomp执行一套精细的访问控制<strong>策略（Policy）</strong>，例如这个Agent只能读<code>/data</code>目录，只能写<code>/tmp</code>。</li></ul><h3 id="效率的极致追求"><a href="#效率的极致追求" class="headerlink" title="效率的极致追求"></a>效率的极致追求</h3><p>在AI场景中，常需同时运行成百上千个沙箱实例。Bubblewrap每个实例都需要独立的初始化过程，资源开销会线性增长。而Sandlock通过其写时复制（COW） 技术，可以瞬间从一个“黄金镜像”克隆出上千个实例，共享内存，极大节省了时间和空间。同时，Sandlock的开销极低，启动仅需5毫秒，远快于传统容器或虚拟机。</p><h3 id="如何选择"><a href="#如何选择" class="headerlink" title="如何选择"></a>如何选择</h3><p>选择Bubblewrap，如果你的目标是：</p><ul><li>为普通桌面应用（如一个闭源游戏或聊天软件）提供一个基础的运行沙箱。</li><li>需要一个无需守护进程、轻量级的通用沙箱工具。</li></ul><p>选择Sandlock，如果你的目标是：</p><ul><li>在AI Agent系统中安全地执行由模型生成的不可信代码。</li><li>需要高并发、低延迟地执行大量短暂任务（如批量代码评估）。</li><li>需要精细到每个工具调用的访问控制策略。</li></ul><h2 id="基于GPU加速的内存回收方案"><a href="#基于GPU加速的内存回收方案" class="headerlink" title="基于GPU加速的内存回收方案"></a>基于GPU加速的内存回收方案</h2><p><a href="https://mp.weixin.qq.com/s/cnAB_8DHaTJRYjVKpcoH_A" target="_blank" rel="noopener">vivo的ZRAM异构压缩技术：基于GPU加速的内存回收方案</a></p><p>key idea: 将zram压缩内存数据的操作由CPU offload到GPU以进行加速。</p>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;CubeSandbox&quot;&gt;&lt;a href=&quot;#CubeSandbox&quot; class=&quot;headerlink&quot; title=&quot;CubeSandbox&quot;&gt;&lt;/a&gt;CubeSandbox&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://mp.weixin.qq.com/s/d6toVeZzrUc1C4g1EJRPnQ&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;当 Docker 不再安全：腾讯云 CubeSandbox 如何用 Rust+KVM 重塑 AI Agent 沙箱&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/TencentCloud/CubeSandbox&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;TencentCloud/CubeSandbox&lt;/a&gt;
    
    </summary>
    
      <category term="经验" scheme="http://liujunming.github.io/categories/%E7%BB%8F%E9%AA%8C/"/>
    
    
      <category term="经验" scheme="http://liujunming.github.io/tags/%E7%BB%8F%E9%AA%8C/"/>
    
  </entry>
  
  <entry>
    <title>LLM KV Cache文章汇总</title>
    <link href="http://liujunming.github.io/2026/04/12/LLM-KV-Cache%E6%96%87%E7%AB%A0%E6%B1%87%E6%80%BB/"/>
    <id>http://liujunming.github.io/2026/04/12/LLM-KV-Cache文章汇总/</id>
    <published>2026-04-12T08:33:41.000Z</published>
    <updated>2026-04-11T08:46:45.880Z</updated>
    
    <content type="html"><![CDATA[<p>本文将持续收集LLM KV Cache相关的文章。<a id="more"></a></p><ul><li><a href="https://developer.aliyun.com/article/1713501" target="_blank" rel="noopener">当我们谈论 AI 推理的 KV Cache，我们在说什么？</a></li><li><a href="https://mp.weixin.qq.com/s/lE5TX3V7qdvYJIECrdsxAw" target="_blank" rel="noopener">阿里云提出基于CXL的KV缓存管理内存架构Beluga</a></li></ul>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将持续收集LLM KV Cache相关的文章。
    
    </summary>
    
      <category term="AI Infra" scheme="http://liujunming.github.io/categories/AI-Infra/"/>
    
    
      <category term="AI Infra" scheme="http://liujunming.github.io/tags/AI-Infra/"/>
    
  </entry>
  
  <entry>
    <title>Notes about Memory Mirroring</title>
    <link href="http://liujunming.github.io/2026/04/11/Notes-about-Address-Range-Partial-Memory-Mirroring/"/>
    <id>http://liujunming.github.io/2026/04/11/Notes-about-Address-Range-Partial-Memory-Mirroring/</id>
    <published>2026-04-11T03:49:10.000Z</published>
    <updated>2026-04-10T15:00:19.749Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下Memory Mirroring相关notes。<a id="more"></a></p><h2 id="Memory-Mirroring"><a href="#Memory-Mirroring" class="headerlink" title="Memory Mirroring"></a>Memory Mirroring</h2><p>The Intel Xeon processor family-based platform offers a RAS (Reliability Availability Serviceability) feature called <strong>Memory Mirroring</strong>. This feature allows users to configure the memory in a highly reliable mode such that system uptime can be maintained—even when a memory component is affected by an uncorrectable fault. When enabled, a trade-off between memory capacity and reliability is required. For example, <u>user-accessible memory may be reduced to half of the total available memory</u>.</p><h2 id="Address-Range-Partial-Memory-Mirroring"><a href="#Address-Range-Partial-Memory-Mirroring" class="headerlink" title="Address Range Partial Memory Mirroring"></a>Address Range Partial Memory Mirroring</h2><p>The Intel Xeon processor E7 v3 product family-based platform introduces a new layer of support for partial memory mirroring called Address Range Mirroring. When Address Range Mirroring is used, the platform allows an OS to specify a subset of total available memory for mirroring (and also to optionally specify whether to mirror the range 0–4 GB). This capability allows a user to make an appropriate trade-off between non-mirrored memory range and mirrored memory range, thus optimizing total available memory while keeping highly reliable memory range available for mission-critical workloads and/or kernel space.</p><p>Legacy memory mirroring is transparent to the OS; however, address range mirroring requires a firmware-OS interface for a user to specify the desired subset of memory to mirror. To fully utilize Address Range Mirroring:</p><ul><li>Present partial or total mirrored memory on the platform to the OS.</li><li>Provide the OS a method to request the amount of mirrored memory that takes effect on subsequent boots.</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ol><li>Legacy Memory Mirroring是将所有内存都做mirror，因而available memory会减半</li><li>Address Range Partial Memory Mirroring是选择部分内存做mirror</li></ol><hr><p>参考资料:</p><ol><li><a href="https://www.intel.com/content/www/us/en/developer/articles/technical/address-range-partial-memory-mirroring.html" target="_blank" rel="noopener">Address Range Partial Memory Mirroring</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下Memory Mirroring相关notes。
    
    </summary>
    
      <category term="RAS" scheme="http://liujunming.github.io/categories/RAS/"/>
    
    
      <category term="RAS" scheme="http://liujunming.github.io/tags/RAS/"/>
    
  </entry>
  
  <entry>
    <title>Notes about RDMA MPT and MTT</title>
    <link href="http://liujunming.github.io/2026/04/11/Notes-about-RDMA-MPT-and-MTT/"/>
    <id>http://liujunming.github.io/2026/04/11/Notes-about-RDMA-MPT-and-MTT/</id>
    <published>2026-04-11T00:58:21.000Z</published>
    <updated>2026-04-11T12:00:11.148Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark RDMA的MPT(Memory Protection Table) and MTT(Memory Translation Table)相关notes。<a id="more"></a></p><h2 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h2><p><img src="/images/2026/04/001.png" alt></p><p><img src="/images/2026/04/002.png" alt></p><p>每一次内存访问都会指定一个mkey和一个VA地址，mkey来自WQE或报文里的LKEY/RKEY，它是一个32bits的地址空间标识，包含index和key两部分。MTT地址翻译过程如下：</p><ol><li>使用mkey.index索引mkey context table(MPT)得到mkey context。</li><li>Key检查：对比mkey.key和mkey context里的key是否一致。</li><li>PD检查：对比发起内存访问的QP里的PD和mkey context里的PD是否一致。</li><li>地址范围检查：mkey context对应了一个MR，里面包含address和length两个字段用于指明MR的范围，这里需要检查当前正在进行的内存访问是否在这个MR范围内。</li><li>访问权限检查：根据mkey context内的local/remote read/write/atomic权限检查当前操作是否合法。</li><li>当上面的检查通过时，就可以使用mtt pointer了，它是MTT表的基地址。</li><li>访问MTT表需要一个索引MTT index=当前访问地址accessing VA - mkey_context.va得到，其中mkey_context.va是MR的起始地址。另外需要考虑PA所指向的page大小，当page为4K时，上面的MTT index还要右移12位。</li><li>用上面的index索引MTT表就能得到一个MTT entry，它里面包含一个PA地址，即page number页号。如果page为4KB则最终的PA = (page number &lt;&lt; 12) + (accessing VA &amp; 0xfff)。</li></ol><p>上述步骤均由RDMA硬件完成。</p><h2 id="MTT-entry"><a href="#MTT-entry" class="headerlink" title="MTT entry"></a>MTT entry</h2><p>MTT entry的细节可以<a href="https://network.nvidia.com/files/doc-2020/ethernet-adapters-programming-manual.pdf" target="_blank" rel="noopener">Mellanox Adapters Programmer’s Reference Manual (PRM)</a>:</p><p><img src="/images/2026/04/003.png" alt></p><h2 id="State-Machine"><a href="#State-Machine" class="headerlink" title="State Machine"></a>State Machine</h2><p><img src="/images/2026/04/004.png" alt></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><ul><li>MTT:用于记录本地内存的物理地址映射，以便远端节点可以直接访问这些内存区域。</li><li>MPT:用于定义哪些本地内存区域可以被远端节点访问，以及它们的访问权限（如读/写）。每当有新的 RDMA 操作请求到来时，RDMA硬件会检查 MPT，以确定是否允许此次访问。</li><li>MTT 和 MPT 是 RDMA 技术中不可或缺的组成部分，前者负责将虚拟地址转换为物理地址，后者则提供内存访问的安全性和隔离性。两者共同作用，确保了 RDMA 操作既高效又安全。</li></ul><hr><p>参考资料:</p><ol><li><a href="https://zhuanlan.zhihu.com/p/567720023" target="_blank" rel="noopener">RDMA 高级</a></li><li><a href="https://network.nvidia.com/files/doc-2020/ethernet-adapters-programming-manual.pdf" target="_blank" rel="noopener">Mellanox Adapters Programmer’s Reference Manual (PRM)</a></li><li><a href="https://mp.weixin.qq.com/s/crz1PG0sLnQDVn03pokV1Q" target="_blank" rel="noopener">RDMA 关键技术研究：Memory Region</a></li><li><a href="https://mp.weixin.qq.com/s/w2wBzx1nkR6S6Cb68PkaEw" target="_blank" rel="noopener">从阿里云eRDMA看如何解决RDMA在数据中心大规模使用问题</a></li><li><a href="https://mp.weixin.qq.com/s/fdYYkc8hAarrsvclyU2LUQ" target="_blank" rel="noopener">【RDMA MPT &amp;&amp; MTT简介】</a></li><li><a href="https://www.ctyun.cn/developer/article/491807389945925" target="_blank" rel="noopener">自研RDMA的地址翻译表的实现技术</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark RDMA的MPT(Memory Protection Table) and MTT(Memory Translation Table)相关notes。
    
    </summary>
    
      <category term="RDMA" scheme="http://liujunming.github.io/categories/RDMA/"/>
    
    
      <category term="RDMA" scheme="http://liujunming.github.io/tags/RDMA/"/>
    
  </entry>
  
  <entry>
    <title>Notes about CUDA Zero-Copy Memory</title>
    <link href="http://liujunming.github.io/2026/04/05/Notes-about-CUDA-Zero-MemCopy/"/>
    <id>http://liujunming.github.io/2026/04/05/Notes-about-CUDA-Zero-MemCopy/</id>
    <published>2026-04-05T08:24:56.000Z</published>
    <updated>2026-04-05T23:47:11.346Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下CUDA Zero-Copy Memory的相关notes。<a id="more"></a></p><h2 id="原理"><a href="#原理" class="headerlink" title="原理"></a>原理</h2><ul><li>pin住host的dram内存</li><li>host CPU mmu建立VA到pinned memory的映射</li><li>GPU mmu建立VA到pinned memory的映射</li></ul><p>通过将一段pin住的物理内存，同时映射到CPU和GPU的虚拟地址空间来实现。这样一来，GPU内核就能像访问自己的显存一样，直接读写这块主机内存，省去了显式的<code>cudaMemcpy</code>操作。</p><h2 id="Advantages"><a href="#Advantages" class="headerlink" title="Advantages"></a>Advantages</h2><p>GPU threads can directly access zero-copy memory. There are several advantages to using zero-copy memory in CUDA kernels, such as:</p><ul><li>Leveraging host memory when there is insufficient device memory</li><li>Avoiding explicit data transfer between the host and device</li><li>Improving PCIe transfer rates</li></ul><h2 id="劣势与挑战"><a href="#劣势与挑战" class="headerlink" title="劣势与挑战"></a>劣势与挑战</h2><ul><li>带宽瓶颈: 访问速度受限于PCIe总线带宽。对频繁访问的数据，效率远低于本地显存。</li><li>高延迟: 每次访问都需经过PCIe总线，延迟比本地显存高几个数量级。</li></ul><h2 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h2><p><strong>分配并映射新的pinned内存</strong><br>这种方式直接分配并映射一块全新的host pinned内存，是最常见的方法。</p><ul><li>核心API: <code>cudaHostAlloc</code></li><li>关键步骤:<ul><li>分配：使用 <code>cudaHostAlloc</code> 并指定 <code>cudaHostAllocMapped</code> 标志。</li><li>获取设备指针：通过 <code>cudaHostGetDevicePointer</code> 获取该内存对应的GPU侧有效指针。</li><li>在核函数中使用：将设备指针传入核函数。</li></ul></li></ul><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><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></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cuda_runtime.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="comment">// GPU 核函数：直接对主机上的锁页内存进行操作</span></span><br><span class="line">__<span class="function">global__ <span class="keyword">void</span> <span class="title">vector_add_kernel</span><span class="params">(<span class="keyword">float</span> *a, <span class="keyword">float</span> *b, <span class="keyword">float</span> *c, <span class="keyword">int</span> n)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> idx = blockIdx.x * blockDim.x + threadIdx.x;</span><br><span class="line">    <span class="keyword">if</span> (idx &lt; n) &#123;</span><br><span class="line">        <span class="comment">// 直接访问主机上的锁页内存，如同访问显存</span></span><br><span class="line">        c[idx] = a[idx] + b[idx];</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">int</span> n = <span class="number">1024</span>;</span><br><span class="line">    <span class="keyword">size_t</span> size = n * <span class="keyword">sizeof</span>(<span class="keyword">float</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 1. 在主机上分配并映射锁页内存</span></span><br><span class="line">    <span class="keyword">float</span> *h_a, *h_b, *h_c;</span><br><span class="line">    cudaHostAlloc((<span class="keyword">void</span> **)&amp;h_a, size, cudaHostAllocMapped);</span><br><span class="line">    cudaHostAlloc((<span class="keyword">void</span> **)&amp;h_b, size, cudaHostAllocMapped);</span><br><span class="line">    cudaHostAlloc((<span class="keyword">void</span> **)&amp;h_c, size, cudaHostAllocMapped);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 2. 在主机端初始化数据</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; ++i) &#123;</span><br><span class="line">        h_a[i] = <span class="number">1.0f</span>;</span><br><span class="line">        h_b[i] = <span class="number">2.0f</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 3. 获取该主机内存对应的GPU设备指针</span></span><br><span class="line">    <span class="keyword">float</span> *d_a, *d_b, *d_c;</span><br><span class="line">    cudaHostGetDevicePointer((<span class="keyword">void</span> **)&amp;d_a, (<span class="keyword">void</span> *)h_a, <span class="number">0</span>);</span><br><span class="line">    cudaHostGetDevicePointer((<span class="keyword">void</span> **)&amp;d_b, (<span class="keyword">void</span> *)h_b, <span class="number">0</span>);</span><br><span class="line">    cudaHostGetDevicePointer((<span class="keyword">void</span> **)&amp;d_c, (<span class="keyword">void</span> *)h_c, <span class="number">0</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 4. 配置核函数并启动</span></span><br><span class="line">    <span class="keyword">int</span> threadsPerBlock = <span class="number">256</span>;</span><br><span class="line">    <span class="keyword">int</span> blocksPerGrid = (n + threadsPerBlock - <span class="number">1</span>) / threadsPerBlock;</span><br><span class="line">    vector_add_kernel&lt;&lt;&lt;blocksPerGrid, threadsPerBlock&gt;&gt;&gt;(d_a, d_b, d_c, n);</span><br><span class="line">    cudaDeviceSynchronize();</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 5. 检查结果，此时结果已直接写入主机的 h_c 中</span></span><br><span class="line">    <span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; n; ++i) &#123;</span><br><span class="line">        <span class="keyword">if</span> (h_c[i] != <span class="number">3.0f</span>) &#123;</span><br><span class="line">            <span class="built_in">printf</span>(<span class="string">"Error: h_c[%d] = %f\n"</span>, i, h_c[i]);</span><br><span class="line">            <span class="keyword">break</span>;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">printf</span>(<span class="string">"Test passed!\n"</span>);</span><br><span class="line"></span><br><span class="line">    <span class="comment">// 6. 清理资源</span></span><br><span class="line">    cudaFreeHost(h_a);</span><br><span class="line">    cudaFreeHost(h_b);</span><br><span class="line">    cudaFreeHost(h_c);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><hr><p>参考资料:</p><ol><li><a href="https://github.com/NVIDIA/cuda-samples/tree/master/Samples/0_Introduction#simplezerocopy" target="_blank" rel="noopener">cuda-samples</a></li><li><a href="https://docs.nvidia.com/cuda/cuda-programming-guide/02-basics/understanding-memory.html#page-locked-host-memory" target="_blank" rel="noopener">Page-Locked Host Memory</a></li><li>Professional CUDA C Programming</li><li><a href="https://chat.deepseek.com/share/ran9srj0hi8t35xmsw" target="_blank" rel="noopener">https://chat.deepseek.com/share/ran9srj0hi8t35xmsw</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下CUDA Zero-Copy Memory的相关notes。
    
    </summary>
    
      <category term="GPU" scheme="http://liujunming.github.io/categories/GPU/"/>
    
    
      <category term="GPU" scheme="http://liujunming.github.io/tags/GPU/"/>
    
      <category term="CUDA" scheme="http://liujunming.github.io/tags/CUDA/"/>
    
  </entry>
  
  <entry>
    <title>Bubblewrap vs Docker</title>
    <link href="http://liujunming.github.io/2026/03/22/Notes-about-Bubblewrap/"/>
    <id>http://liujunming.github.io/2026/03/22/Notes-about-Bubblewrap/</id>
    <published>2026-03-22T11:41:46.000Z</published>
    <updated>2026-03-22T12:46:45.303Z</updated>
    
    <content type="html"><![CDATA[<p>Bubblewrap is a minimal, low-level sandboxing tool, while Docker is a comprehensive platform for building, distributing, and running application containers. The key difference is their purpose: Bubblewrap provides simple, direct process isolation, whereas Docker offers a complete ecosystem for application bundling and deployment. <a id="more"></a></p><h2 id="Why-Bubblewrap-Beats-Docker"><a href="#Why-Bubblewrap-Beats-Docker" class="headerlink" title="Why Bubblewrap Beats Docker"></a>Why Bubblewrap Beats Docker</h2><p>This beats Docker for quick workflows. Docker requires a running daemon and lots of configuration files. Bubblewrap lets you execute your app directly—no daemon, no stale containers cluttering your system.<br>这比 Docker 更适合快速工作流。Docker 需要运行一个守护进程，还要准备一大堆配置文件。而 Bubblewrap 让你可以直接运行应用程序——没有守护进程，也不会有残留的容器把系统搞得乱七八糟。</p><p>If you’re experienced enough to worry about Docker misconfigurations, Bubblewrap gives you more control when you need it. You just run a command. No YAML files or debugging background services.<br>如果你经验足够丰富，会担心 Docker 配置不当带来的问题，那么 Bubblewrap 能在你需要的时候给你更强的控制力。你只需要执行一条命令就行，无需编写 YAML 文件，也不用去排查后台服务的故障。</p><h2 id="Key-Differences"><a href="#Key-Differences" class="headerlink" title="Key Differences"></a>Key Differences</h2><table><thead><tr><th style="text-align:left">Feature</th><th style="text-align:center">Bubblewrap</th><th style="text-align:right">Docker</th></tr></thead><tbody><tr><td style="text-align:left">Primary Use</td><td style="text-align:center">Sandboxing single commands/processes, desktop app isolation (via Flatpak)</td><td style="text-align:right">Packaging and deploying entire applications and their dependencies</td></tr><tr><td style="text-align:left">Complexity</td><td style="text-align:center">Minimal and lightweight; a single command-line utility (<code>bwrap</code>)</td><td style="text-align:right">Complex ecosystem with images, layers, storage drivers, and a daemon</td></tr><tr><td style="text-align:left">Daemon</td><td style="text-align:center">No daemon required; runs as an unprivileged process (using user namespaces)</td><td style="text-align:right">Typically requires a running daemon (though rootless Podman offers a daemonless alternative)</td></tr><tr><td style="text-align:left">Images</td><td style="text-align:center">No concept of container images; uses host binaries and requires explicit directory mapping</td><td style="text-align:right">Relies on images and Dockerfiles to bundle the required software and environment</td></tr><tr><td style="text-align:left">Control Level</td><td style="text-align:center">Lower-level control over Linux namespaces (mount, network, PID, etc.) and Seccomp filters</td><td style="text-align:right">Higher-level abstraction; automates much of the underlying container setup</td></tr></tbody></table><h2 id="When-to-Use-Which"><a href="#When-to-Use-Which" class="headerlink" title="When to Use Which?"></a>When to Use Which?</h2><p>Use Bubblewrap when:</p><ul><li>You need to run a single, untrusted command in an existing shell session with limited file system or network access (e.g., running untrusted code from an AI agent).</li><li>You want a lightweight security sandbox without the overhead of building full container images or running a daemon.</li><li>You are developing or using desktop applications (it is a core component of Flatpak for sandboxing applications).</li></ul><p>Use Docker when:</p><ul><li>You need to package an application and all its dependencies into a consistent, portable unit for deployment across different environments (development, staging, production).</li><li>You require an ecosystem for managing container lifecycles, orchestration (e.g., Kubernetes integration), and large-scale application delivery.</li><li>You are building microservices or other server-side applications that need a repeatable build process. </li></ul><hr><p>参考资料:</p><ol><li><a href="https://patrickmccanna.net/a-better-way-to-limit-claude-code-and-other-coding-agents-access-to-secrets/" target="_blank" rel="noopener">A better way to limit Claude Code (and other coding agents!) access to Secrets</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;Bubblewrap is a minimal, low-level sandboxing tool, while Docker is a comprehensive platform for building, distributing, and running application containers. The key difference is their purpose: Bubblewrap provides simple, direct process isolation, whereas Docker offers a complete ecosystem for application bundling and deployment.
    
    </summary>
    
      <category term="sandbox" scheme="http://liujunming.github.io/categories/sandbox/"/>
    
    
      <category term="sandbox" scheme="http://liujunming.github.io/tags/sandbox/"/>
    
  </entry>
  
  <entry>
    <title>Notes about ECMP and packet spraying</title>
    <link href="http://liujunming.github.io/2026/03/08/Notes-about-ECMP-Equal-Cost-Multi-Path-Routing/"/>
    <id>http://liujunming.github.io/2026/03/08/Notes-about-ECMP-Equal-Cost-Multi-Path-Routing/</id>
    <published>2026-03-08T06:38:28.000Z</published>
    <updated>2026-03-08T09:32:48.139Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下计算机网络中ECMP(Equal-Cost Multi-Path)和packet spraying的相关notes。<a id="more"></a></p><h2 id="ECMP"><a href="#ECMP" class="headerlink" title="ECMP"></a>ECMP</h2><p>在路由协议中，如果下一跳有多个路径可以选择，并且多个路径的 cost metric 相等，那么路由器就会根据包的 header，计算一个 hash 值，然后根据这个 hash 值对这个 flow 选择一条固定的路径，作为下一跳。</p><p><img src="/images/2026/03/006.png" alt></p><p><img src="/images/2026/03/007.png" alt></p><p>ECMP是一个基于流的负载均衡策略，当路由器发现同一目的地址出现多个最优路径时，会更新路由表，为此目的地址添加多条规则，对应于多个下一跳。可同时利用这些路径转发数据，增加带宽。ECMP算法被多种路由协议支持，例如： OSPF、ISIS、EIGRP、BGP等。</p><p>对于未开启ECMP的网络来说，无法充分利用路径资源。例如下图所示：</p><p><img src="/images/2026/03/008.png" alt></p><p>假设从<code>S0</code>到Server的路径为S0-S1-S2-S4（即图中橘色路径），那么即便存在另一条等价路径（即图中蓝色路径），路由器仍然会每次选择第一条橘色路径转发数据。除非此条路径发生拥塞，才会重新选择路径。</p><p>当开启ECMP功能时，便可同时利用两条路径，进行基于流的负载均衡。例如<code>主机A</code>到Server的数据流选择橘色路径，<code>主机B</code>到Server的数据流选择蓝色路径。</p><p>ECMP的路径选择策略有多种方法：</p><ul><li>哈希： 例如根据源IP地址的哈希为流选择路径</li><li>轮询： 各个流在多条路径之间轮询传输</li><li>基于路径权重： 根据路径的权重分配流，权重大的路径分配的流数量更多</li></ul><h2 id="ECMP’s-Dilemma-in-AI-Workloads"><a href="#ECMP’s-Dilemma-in-AI-Workloads" class="headerlink" title="ECMP’s Dilemma in AI Workloads"></a>ECMP’s Dilemma in AI Workloads</h2><p>Datacenters often utilize Clos networks as their underlying fabric, which provides multiple equal-cost paths between any source and destination. To distribute traffic across these paths,ECMP is the most widely used load balancing(LB) mechanism, which determines the path of a flow by hashing the 5-tuple in the packet header. ECMP works well for traditional workloads, where there are millions of flows that ensure a relatively even distribution of traffic. However, unlike traditional datacenter workloads, AI training workloads exhibit traffic patterns that are fundamentally mismatched with ECMP’s design:</p><ol><li>Small number of flows: In AI training job, each node establishes very few connections, as communication is only required with a limited set of peers.</li><li>Large flow sizes: The flow sizes typically range from several MBs to hundreds of MBs.</li><li>Bursty traffic: AI training is an inherently synchronized process, where most nodes enter the communication phase almost simultaneously. This synchronization results in a bursty traffic pattern, with large volumes of data being exchanged in a short period of time.</li></ol><p>These flow characteristics (i.e., few in number, large in size) result in a high ECMP collision rate, as the small number of flows can’t be evenly distributed across available paths, leading to severe performance degradation in AI training workloads.</p><h2 id="packet-spraying"><a href="#packet-spraying" class="headerlink" title="packet spraying"></a>packet spraying</h2><p>Packet spraying is a high-performance network load-balancing technique that distributes individual packets of a data flow across multiple available network paths rather than relying on a single path. By utilizing all paths, it achieves high link utilization and reduces tail latency, particularly beneficial for data center AI/ML workloads and bursty traffic.</p><p>Key details about packet spraying:</p><ul><li>Benefits: It provides high throughput, mitigates congestion, and is effective for short-lived, latency-sensitive traffic.</li><li>Techniques:<ul><li>Random Packet Spraying (RPS): Randomly assigns packets to paths to balance load.</li><li>Deterministic Packet Spraying: Uses a counter to distribute packets to ensure even path distribution.</li><li>Adaptive Packet Spraying (APS): Dynamically steers packets away from congested paths based on real-time feedback.</li></ul></li><li>Challenges: The main drawback is potential out-of-order packet delivery, which can trigger unnecessary retransmissions.</li></ul><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p><img src="/images/2026/03/009.png" alt></p><ul><li>ECMP是flow粒度的Load Balance技术</li><li>packet spraying是packet粒度的Load Balance技术，粒度更细，但是会引入out-of-order packet delivery问题</li></ul><hr><p>参考资料:</p><ol><li>Unlocking ECMP Programmability for Precise Traffic Control(NSDI’25)</li><li><a href="https://www.kawabangga.com/posts/6732" target="_blank" rel="noopener">数据中心网络高可用技术：ECMP</a></li><li><a href="https://ivanzz1001.github.io/records/post/network/2018/08/01/network-ecmp" target="_blank" rel="noopener">ECMP网络的介绍(转)</a></li><li><a href="https://www.youtube.com/watch?v=KICp-9yXOT0" target="_blank" rel="noopener">Equal-Cost Multi-Path Routing (ECMP)</a></li><li>Enabling Packet Spraying over Commodity RNICs with In-Network Support(APNET’25)</li><li>On the Impact of Packet Spraying in Data Center Networks(Infocom’13)</li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下计算机网络中ECMP(Equal-Cost Multi-Path)和packet spraying的相关notes。
    
    </summary>
    
      <category term="计算机网络" scheme="http://liujunming.github.io/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/"/>
    
    
      <category term="计算机网络" scheme="http://liujunming.github.io/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/"/>
    
      <category term="Load Balance" scheme="http://liujunming.github.io/tags/Load-Balance/"/>
    
  </entry>
  
  <entry>
    <title>Notes about NVMe HMB(Host Memory Buffer)</title>
    <link href="http://liujunming.github.io/2026/03/07/Notes-about-NVMe-HMB-Host-Memory-Buffer/"/>
    <id>http://liujunming.github.io/2026/03/07/Notes-about-NVMe-HMB-Host-Memory-Buffer/</id>
    <published>2026-03-07T11:39:19.000Z</published>
    <updated>2026-03-07T23:47:18.678Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下NVMe HMB(Host Memory Buffer)的相关notes。<a id="more"></a></p><h2 id="Background"><a href="#Background" class="headerlink" title="Background"></a>Background</h2><p>现代固态硬盘(SSD)内部通常配备了一定容量的DRAM作为缓存，它的主要作用是存放FTL(Flash Translation Layer)映射表和其他临时数据，以加速SSD的数据处理效率。</p><p><img src="/images/2026/03/002.png" alt></p><p>FTL映射表记录了逻辑地址到物理地址之间的转换关系，因为NAND闪存的特性决定了其不能像传统硬盘那样进行直接的线性读写，必须通过FTL层来管理块擦除、页编程等操作。由于NAND闪存的每个块或页都有一个唯一的物理地址，当操作系统请求对某个逻辑地址进行读写时，SSD需要查询FTL表以找到对应的物理位置。如果FTL表能存储在快速访问的DRAM中，那么SSD就可以更快地完成地址转换，从而提高整体I/O性能。</p><p>在传统的SSD中，DRAM起着至关重要的作用，包括存储元数据、缓冲写入数据、合并短写入为长写入以及在SSD内部为了垃圾回收而移动数据等。由于NAND闪存与传统硬盘的工作机制有显著差异，DRAM有助于弥补两者间的交互问题，并优化整体性能。</p><p>DRAM-less SSD是一种不内置独立DRAM芯片的固态硬盘，它依赖于主机服务器的部分DRAM内存来执行原本由SSD内部DRAM承担的任务。这种设计的主要优点在于降低成本和降低功耗，尤其是在大规模数据中心用户中受到欢迎。</p><h2 id="What"><a href="#What" class="headerlink" title="What"></a>What</h2><p><img src="/images/2026/03/001.png" alt></p><p>DRAM-less SSD通过利用主机内存中的Host Memory Buffer (HMB)替代内部DRAM，这使得主机能够更紧密地控制SSD的操作时机和行为。</p><p><img src="/images/2026/03/004.jpg" alt></p><p><img src="/images/2026/03/003.png" alt></p><h2 id="Spec"><a href="#Spec" class="headerlink" title="Spec"></a>Spec</h2><p>NVME协议中对HMB有2个关键参数：</p><p><img src="/images/2026/03/005.png" alt></p><ul><li>HMB建议值（HMPRE）：设定实际分配给HMB使用的主机内存容量，为设备提供最优性能的内存分配量</li><li>HMB最小值（HMMIN）：确保设备正常工作的HMB的最低内存分配量，低于这个值可能影响性能</li></ul><hr><p>参考资料 ：</p><ol><li><a href="https://mp.weixin.qq.com/s/Uvheog_Ih6hm-nxFg1VAxg" target="_blank" rel="noopener">探究NVMe SSD HMB应用场景与影响</a></li><li><a href="https://www.youtube.com/watch?v=X826mrcfzrk" target="_blank" rel="noopener">Exploring Performance Paradigm of HMB NVMe SSD’s</a></li><li>NVMe spec</li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下NVMe HMB(Host Memory Buffer)的相关notes。
    
    </summary>
    
      <category term="NVMe" scheme="http://liujunming.github.io/categories/NVMe/"/>
    
    
      <category term="NVMe" scheme="http://liujunming.github.io/tags/NVMe/"/>
    
  </entry>
  
  <entry>
    <title>Notes about NVMe PMR(Persistent Memory Region)</title>
    <link href="http://liujunming.github.io/2026/02/23/Notes-about-NVMe-PMR-Persistent-Memory-Regions/"/>
    <id>http://liujunming.github.io/2026/02/23/Notes-about-NVMe-PMR-Persistent-Memory-Regions/</id>
    <published>2026-02-23T11:23:04.000Z</published>
    <updated>2026-02-25T14:04:23.999Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下NVMe PMR(Persistent Memory Region)的相关notes。<a id="more"></a></p><p><img src="/images/2026/02/021.png" alt></p><h2 id="Prerequisite"><a href="#Prerequisite" class="headerlink" title="Prerequisite"></a>Prerequisite</h2><p><a href="/2024/06/30/深入理解NVMe-CMB机制/">NVMe CMB机制</a></p><p>While CMB and PMR are PCIe-based memory on the NVMe drive, the PMR is specifically designed to be non-volatile (persistent), whereas the CMB is typically volatile.</p><p>PMRs <strong>add persistent to CMBs</strong>.</p><h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p><img src="/images/2026/02/020.png" alt></p><p>Persistent Memory Region (PMR) is an optinal area of persistent memory that is located on the NVMe device, that can be read with standard PCIe memory reads/writes. This could be extra DRAM that is power protected, storage class memory or other new memory types.</p><h2 id="Mode-of-Operation"><a href="#Mode-of-Operation" class="headerlink" title="Mode of Operation"></a>Mode of Operation</h2><p><img src="/images/2026/02/019.png" alt></p><hr><p>参考资料:</p><ol><li><a href="https://mp.weixin.qq.com/s/niZmq170l4HDnfyw0rmRFg" target="_blank" rel="noopener">太强大了！NVMe SSD变身内存！</a></li><li><a href="https://nvmexpress.org/faq-items/what-is-persistent-memory-region/" target="_blank" rel="noopener">What is Persistent Memory Region?</a></li><li><a href="https://files.futurememorystorage.com/proceedings/2018/20180808_NVME-202-2_Chadha.pdf" target="_blank" rel="noopener">NVMe SSDs with Persistent Memory Regions </a></li><li><a href="https://files.futurememorystorage.com/proceedings/2018/20180808_SOFT-201-1_Bates.pdf" target="_blank" rel="noopener">Important new NVMe features for optimizing the data pipeline</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下NVMe PMR(Persistent Memory Region)的相关notes。
    
    </summary>
    
      <category term="NVMe" scheme="http://liujunming.github.io/categories/NVMe/"/>
    
    
      <category term="NVMe" scheme="http://liujunming.github.io/tags/NVMe/"/>
    
  </entry>
  
  <entry>
    <title>Notes about VXLAN</title>
    <link href="http://liujunming.github.io/2026/02/23/Notes-about-VXLAN/"/>
    <id>http://liujunming.github.io/2026/02/23/Notes-about-VXLAN/</id>
    <published>2026-02-23T10:23:04.000Z</published>
    <updated>2026-02-23T14:03:30.631Z</updated>
    
    <content type="html"><![CDATA[<p>本文将mark下VXLAN(Virtual Extensible LAN)的相关notes。<a id="more"></a></p><h2 id="Prerequisite"><a href="#Prerequisite" class="headerlink" title="Prerequisite"></a>Prerequisite</h2><p><a href="/2019/09/02/introduction-to-vlan/">VLAN</a></p><h2 id="Motivation"><a href="#Motivation" class="headerlink" title="Motivation"></a>Motivation</h2><h3 id="虚拟机规模受限制"><a href="#虚拟机规模受限制" class="headerlink" title="虚拟机规模受限制"></a>虚拟机规模受限制</h3><p>一台物理服务器上可能运行几十甚至上百台虚拟机，但接入交换机的 MAC 地址表容量有限，无法支撑海量虚拟机的 MAC 学习需求。</p><h3 id="网络隔离能力弱"><a href="#网络隔离能力弱" class="headerlink" title="网络隔离能力弱"></a>网络隔离能力弱</h3><p>传统 VLAN 只有 12个比特位，最多支持 4096 个隔离域。对于大型云平台而言，租户数量可能远超这个数字，VLAN不够用了。</p><h3 id="虚拟机迁移范围受限"><a href="#虚拟机迁移范围受限" class="headerlink" title="虚拟机迁移范围受限"></a>虚拟机迁移范围受限</h3><p>虚拟机迁移通常要求目标主机在同一个二层广播域内，这就限制了迁移只能在一个较小的物理范围内进行，无法实现跨机房、跨数据中心的灵活迁移。</p><h2 id="Introduction"><a href="#Introduction" class="headerlink" title="Introduction"></a>Introduction</h2><p>VXLAN是主流的overlay技术，通过“<strong>MAC in UDP</strong>”的封装方式，将二层以太网帧封装在 UDP 报文中，通过三层 IP 网络进行传输。</p><p>这样一来再也不怕虚机“乱跑”了：</p><p>虚拟机的 MAC 地址只在 VXLAN 边缘设备（VTEP）之间可见，中间网络设备无需学习，解决了 MAC 表瓶颈。</p><p>使用 24 位的VNI（VXLAN Network Identifier），支持多达 1600万个隔离段。</p><p>只要IP可达，虚拟机就可以跨任意三层网络迁移，构建了一个“虚拟大二层”。</p><h2 id="核心组件"><a href="#核心组件" class="headerlink" title="核心组件"></a>核心组件</h2><h3 id="VTEP"><a href="#VTEP" class="headerlink" title="VTEP"></a>VTEP</h3><p>A VTEP(VXLAN tunnel endpoint) is an edge device on a VXLAN network and the start or end point of a VXLAN tunnel. The source VTEP encapsulates the original data frames sent by the source server into VXLAN packets and transmits them to the destination VTEP on the IP network. The destination VTEP then decapsulates the VXLAN packets into the original data frames and forwards the frames to the destination server.</p><h3 id="VNI"><a href="#VNI" class="headerlink" title="VNI"></a>VNI</h3><p>A VNI(VXLAN Network Identifier) is a user identifier similar to a VLAN ID. A VNI identifies a tenant. VMs with different VNIs cannot communicate at Layer 2.</p><h3 id="VXLAN-Gateway"><a href="#VXLAN-Gateway" class="headerlink" title="VXLAN Gateway"></a>VXLAN Gateway</h3><p>Similar to in VLANs, hosts with different VNIs or those on VXLAN and non-VXLAN networks should be unable to directly communicate with each other. To meet these communication requirements, VXLAN introduces VXLAN gateways. </p><h2 id="packet"><a href="#packet" class="headerlink" title="packet"></a>packet</h2><p><img src="/images/2026/02/016.png" alt></p><p>VXLAN packet format (outer IPv4 header used as an example)<br>As shown in the preceding figure, a VXLAN tunnel endpoint (VTEP) encapsulates the following headers into the original Ethernet frame (original L2 frame) sent by a VM:</p><ul><li>VXLAN header<br>A VXLAN header (8 bytes) contains a 24-bit VNI field, which is used to define different tenants on the VXLAN network. It also contains a VXLAN Flags field (8 bits, set to 00001000) and two reserved fields (24 bits and 8 bits, respectively).</li><li>UDP header<br>The VXLAN header and the original Ethernet frame are used as UDP data. In the UDP header, the destination port number (VXLAN Port) is fixed at 4789, and the source port number (UDP Src. Port) is calculated using a hash algorithm based on the original Ethernet frame.</li><li>Outer IP header<br>In the outer IP header, the source IP address (Outer Src. IP) is the IP address of the VTEP connected to the source VM, and the destination IP address (Outer Dst. IP) is the IP address of the VTEP connected to the destination VM.</li><li>Outer MAC header<br>The outer MAC header is also called the outer Ethernet header. In this header, the source MAC address (Src. MAC Addr.) is the MAC address of the VTEP connected to the source VM, and the destination MAC address (Dst. MAC Addr.) is the MAC address of the next hop along the path to the destination VTEP.</li></ul><p><img src="/images/2026/02/018.png" alt></p><p>So basically the underlay is the actual physical topology doing the routing. While the overlay is the virtual network interconnecting the end devices between which overlay protocol is configured. </p><p>If we look at the packet itself, this is how it looks in overlay (the blue portion - the original frame) vs underlay (the red+blue - the encapsulated frame):<br><img src="/images/2026/02/017.png" alt></p><h2 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h2><p><img src="/images/2026/02/015.png" alt></p><p>如图所示：VM A发出数据包给VTEP后，VTEP-1 收到这个包，查表发现 VM B 在远端的 VTEP-2 下面，便开始封装vxlan包。VTEP-2 收到这个 IP 包，发现目的端口是 4789，知道这是个 VXLAN 包后剥离外层 MAC、IP、UDP、VXLAN 头，取出里面的原始以太网报文送给VM B，VM B 收到的就是一个标准的以太网报文，完全感知不到经历了中间的“包装”。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>VXLAN 不仅是技术的演进，更是云时代网络架构的必然选择。它通过封装与隧道技术，在 IP 网络上构建出灵活、可扩展、多租户隔离的虚拟二层网络，真正实现了“<strong>网络随业务而动</strong>”。</p><hr><p>参考资料:</p><ol><li><a href="https://mp.weixin.qq.com/s/FbOYV3Q9bPb-Gp68SQlykw" target="_blank" rel="noopener">一文搞懂VXLAN：云计算背后的网络“黑科技”</a></li><li><a href="https://networklessons.com/cisco/ccnp-encor-350-401/introduction-to-virtual-extensible-lan-vxlan" target="_blank" rel="noopener">Introduction to Virtual Extensible LAN (VXLAN)</a></li><li><a href="https://community.cisco.com/t5/data-center-switches/understanding-underlay-and-overlay-networks/td-p/4295870" target="_blank" rel="noopener">Understanding Underlay and Overlay networks</a></li><li><a href="https://info.support.huawei.com/info-finder/encyclopedia/en/VXLAN.html" target="_blank" rel="noopener">What Is VXLAN?</a></li><li><a href="https://www.youtube.com/watch?v=F1Vq8YwxCXU" target="_blank" rel="noopener">Vxlan explained in simple terms | Cisco CCNA 200-301</a></li><li><a href="https://www.youtube.com/watch?v=YNqKDI_bnPM&amp;list=PLDQaRcbiSnqFe6pyaSy-Hwj8XRFPgZ5h8" target="_blank" rel="noopener">VxLAN | Part 1 - How VxLAN Works</a></li><li><a href="https://www.rfc-editor.org/rfc/pdfrfc/rfc7348.txt.pdf" target="_blank" rel="noopener">rfc7348</a></li><li><a href="https://mp.weixin.qq.com/s/bLhhBtc2HUhPCJ_g-e_kLw" target="_blank" rel="noopener">VXLAN原理介绍以及Linux和OvS的实现分析</a></li><li><a href="https://mp.weixin.qq.com/s/vjOqBGm8SykePlSNsnptvg" target="_blank" rel="noopener">Linux 网络虚拟化隧道技术 VxLAN 全面了解</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;本文将mark下VXLAN(Virtual Extensible LAN)的相关notes。
    
    </summary>
    
      <category term="计算机网络" scheme="http://liujunming.github.io/categories/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/"/>
    
    
      <category term="虚拟化" scheme="http://liujunming.github.io/tags/%E8%99%9A%E6%8B%9F%E5%8C%96/"/>
    
      <category term="计算机网络" scheme="http://liujunming.github.io/tags/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/"/>
    
  </entry>
  
  <entry>
    <title>Notes about NVMe over Fabrics P2P</title>
    <link href="http://liujunming.github.io/2026/02/08/Notes-about-NVMe-oF-Offload/"/>
    <id>http://liujunming.github.io/2026/02/08/Notes-about-NVMe-oF-Offload/</id>
    <published>2026-02-08T11:56:35.000Z</published>
    <updated>2026-02-11T14:18:47.517Z</updated>
    
    <content type="html"><![CDATA[<p>NVMe over Fabrics P2P ,如下图所示，黄色虚线是非P2P数据通信路径，绿色虚线是P2P的通信路径。</p><p><img src="/images/2026/02/010.jpg" alt><a id="more"></a></p><p>黄色路径非P2P路径，RDMA CX5网卡接后收到数据后，先写到主存DRAM中， NVME 设备驱动从主存读取数据再写入NVME SSD硬盘中。</p><p>绿色P2P路径， RDMA NIC网卡获取数据后直接写入NVME SSD硬盘。</p><p>P2P通信带来的收益:</p><ol><li>减少了主存DRAM的使用</li><li>缩短了通信路径，提升了数据传输的效率</li></ol><p><a href="/2024/06/30/深入理解NVMe-CMB机制/#5-p2p操作序列">p2p操作序列</a></p><p><img src="/images/2026/02/011.jpg" alt></p><p><img src="/images/2026/02/012.jpg" alt></p><p><img src="/images/2026/02/013.jpg" alt></p><p><img src="/images/2026/02/014.jpg" alt></p><hr><p>参考资料:</p><ol><li><a href="https://files.futurememorystorage.com/proceedings/2018/20180808_SOFT-201-1_Bates.pdf" target="_blank" rel="noopener">Important new NVMe features for optimizing the data pipeline </a></li><li><a href="https://zhuanlan.zhihu.com/p/386153789" target="_blank" rel="noopener">PCIe P2P</a></li><li><a href="https://www.youtube.com/watch?v=d31foQpoaDg" target="_blank" rel="noopener">NVMe Over Fabrics Offload video</a></li><li><a href="https://www.openfabrics.org/wp-content/uploads/204_TOved.pdf" target="_blank" rel="noopener">NVMe Over Fabrics Offload slides</a></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;NVMe over Fabrics P2P ,如下图所示，黄色虚线是非P2P数据通信路径，绿色虚线是P2P的通信路径。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/2026/02/010.jpg&quot; alt&gt;
    
    </summary>
    
      <category term="NVMe" scheme="http://liujunming.github.io/categories/NVMe/"/>
    
    
      <category term="PCI&amp;PCIe" scheme="http://liujunming.github.io/tags/PCI-PCIe/"/>
    
      <category term="NVMe" scheme="http://liujunming.github.io/tags/NVMe/"/>
    
      <category term="RDMA" scheme="http://liujunming.github.io/tags/RDMA/"/>
    
  </entry>
  
  <entry>
    <title>DPU offload File Client论文整理</title>
    <link href="http://liujunming.github.io/2026/02/07/file-client-offload-to-DPU%E8%AE%BA%E6%96%87%E6%95%B4%E7%90%86/"/>
    <id>http://liujunming.github.io/2026/02/07/file-client-offload-to-DPU论文整理/</id>
    <published>2026-02-07T14:30:51.000Z</published>
    <updated>2026-02-23T07:51:31.790Z</updated>
    
    <content type="html"><![CDATA[<ol><li><a href="https://app.yinxiang.com/fx/205cbf92-a508-4a55-bb53-bcf1bfc91205" target="_blank" rel="noopener">(FAST’23)Fisc: A Large-scale Cloud-native-oriented File System</a></li><li><a href="https://app.yinxiang.com/fx/b2e60428-c9d0-4bc2-a462-c0a54daff3f3" target="_blank" rel="noopener">(ICPP’24)DPC:DPU-accelerated High-Performance File System Client</a></li><li><a href="https://app.yinxiang.com/fx/1eefa177-f1bd-4639-adb6-77eb83a62f98" target="_blank" rel="noopener">(SYSTOR’23)DPFS: DPU-Powered File System Virtualization</a></li><li><a href="https://app.yinxiang.com/fx/922ea368-4f00-4e04-996b-b0d51124274a" target="_blank" rel="noopener">(ASPLOS’25)OS2G: A High-Performance DPU Offloading Architecture for GPU-based Deep Learning with Object Storage</a></li></ol>]]></content>
    
    <summary type="html">
    
      
      
        &lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://app.yinxiang.com/fx/205cbf92-a508-4a55-bb53-bcf1bfc91205&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(FAST’23)Fisc: A Large-sc
      
    
    </summary>
    
      <category term="文件系统" scheme="http://liujunming.github.io/categories/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/"/>
    
    
      <category term="存储" scheme="http://liujunming.github.io/tags/%E5%AD%98%E5%82%A8/"/>
    
      <category term="文件系统" scheme="http://liujunming.github.io/tags/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F/"/>
    
      <category term="DPU" scheme="http://liujunming.github.io/tags/DPU/"/>
    
  </entry>
  
</feed>
