<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>CUDA on Hellokitty&#39;s Blog</title>
    <link>https://yangyang233333.github.io/tags/cuda/</link>
    <description>Recent content in CUDA on Hellokitty&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Mon, 31 Aug 2026 10:30:00 +0800</lastBuildDate>
    <atom:link href="https://yangyang233333.github.io/tags/cuda/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>CUDA Event：GPU 时间线上的事件、同步原理与实战</title>
      <link>https://yangyang233333.github.io/posts/cuda-event-principles-demo/</link>
      <pubDate>Mon, 31 Aug 2026 10:30:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/cuda-event-principles-demo/</guid>
      <description>&lt;p&gt;CUDA kernel launch 通常是异步的：CPU 把 kernel、内存拷贝等操作提交到 stream 后便继续执行。由此产生两个常见问题：如何准确测量 GPU 工作耗时，以及如何让不同 stream 在不阻塞 CPU 的情况下建立依赖？&lt;/p&gt;
&lt;p&gt;CUDA Event 就是解决这类问题的基础设施。它可以理解为插入 GPU stream 时间线中的一个标记：当 event 之前的工作全部完成，event 才进入完成状态。借助这个状态，我们可以做 GPU 计时、CPU 等待、跨 stream 同步和异步资源回收。&lt;/p&gt;
&lt;h2 id=&#34;1-event-不是-cpu-事件而是-gpu-时间线标记&#34;&gt;1. Event 不是 CPU 事件，而是 GPU 时间线标记&lt;/h2&gt;
&lt;p&gt;一个 CUDA stream 是按序执行的 GPU 工作队列：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CPU 提交： Kernel A → memcpy → Event E → Kernel B
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                         异步提交
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GPU 执行： Kernel A ── memcpy ── E 完成 ── Kernel B
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;调用 &lt;code&gt;cudaEventRecord(event, stream)&lt;/code&gt; 时，CPU 通常只是向 &lt;code&gt;stream&lt;/code&gt; 提交一个 event 记录操作，并不会等待 GPU 执行到该位置。只有当这个 stream 中排在 event 前面的操作完成后，event 才会被标记为完成。&lt;/p&gt;</description>
    </item>
    <item>
      <title>SGLang 双 Stream 重叠调度：如何把 CPU 后处理藏到 GPU 计算背后</title>
      <link>https://yangyang233333.github.io/posts/sglang-overlap-scheduling/</link>
      <pubDate>Sun, 30 Aug 2026 23:09:10 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/sglang-overlap-scheduling/</guid>
      <description>&lt;p&gt;大模型自回归推理看起来是纯 GPU 工作：每一步做一次模型前向，采样一个 token，再把 token 喂给下一步。然而在高性能推理系统里，GPU 计算只是流水线的一部分。采样结果回传、EOS 判断、请求回收、KV Cache 管理、下一批组装和元数据准备，都可能在两次前向之间制造空洞。&lt;/p&gt;
&lt;p&gt;SGLang 的 Overlap Scheduling 解决的正是这个问题。它不是简单地“多开一条 CUDA stream”，而是同时完成两件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;让当前步产生的 token 留在 GPU，直接作为下一步输入，解除下一次 forward 对 CPU 读值的依赖；&lt;/li&gt;
&lt;li&gt;用 scheduler stream 和 engine stream 构造软件流水线，让 GPU 计算当前批次时，调度器处理上一批次的结果。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;本文以 Mini-SGLang 的 &lt;code&gt;python/minisgl/scheduler/scheduler.py&lt;/code&gt; 为线索，解释 &lt;code&gt;overlap_loop&lt;/code&gt;、&lt;code&gt;_forward&lt;/code&gt; 和 &lt;code&gt;_process_last_data&lt;/code&gt; 背后的依赖重排。&lt;/p&gt;
&lt;h2 id=&#34;先看结论优化的不是提交速度而是依赖关系&#34;&gt;先看结论：优化的不是“提交速度”，而是依赖关系&lt;/h2&gt;
&lt;p&gt;CUDA kernel 的提交本来就是异步的。CPU 把工作放进 stream 后，不必等待 GPU 完成。因此一个自然的问题是：只用一条 stream，只要 CPU 提交得足够快，不也能让 GPU 连续工作吗？&lt;/p&gt;
&lt;p&gt;如果系统只有计算任务，这个判断基本成立。但自回归推理存在一个控制依赖：调度器通常要知道采样出的 token，才能判断请求是否命中 EOS、是否应该释放资源，以及下一轮有哪些请求仍应留在 batch 中。&lt;/p&gt;
&lt;p&gt;串行执行会形成如下链条：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GPU:  forward(B1) ── idle ── forward(B2) ── idle ── forward(B3)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CPU:               处理 B1                 处理 B2
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   读 token                读 token
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   判 EOS                  判 EOS
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                   组 B2                   组 B3
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;GPU 完成 &lt;code&gt;B1&lt;/code&gt; 后，CPU 才读取结果并决定 &lt;code&gt;B2&lt;/code&gt;。此时 GPU 没有可执行的新工作，只能等待。这不是 CPU 调用 CUDA API 太慢，而是 &lt;code&gt;B2&lt;/code&gt; 在逻辑上依赖 &lt;code&gt;B1&lt;/code&gt; 的结果。&lt;/p&gt;</description>
    </item>
    <item>
      <title>从朴素循环到硬件极限：GEMM / GEMV 高性能算子优化指南</title>
      <link>https://yangyang233333.github.io/posts/gemm-gemv-optimization/</link>
      <pubDate>Wed, 26 Aug 2026 14:20:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/gemm-gemv-optimization/</guid>
      <description>从 Roofline、数据布局和分层分块出发，逐步分析如何在 CPU 与 GPU 上优化 GEMM/GEMV，并建立可复现的性能验证方法。</description>
    </item>
    <item>
      <title>Phoenix 源码解读：把 GPU 显存变成 Linux I/O 可直达的内存</title>
      <link>https://yangyang233333.github.io/posts/phoenix-source-code-reading/</link>
      <pubDate>Mon, 24 Aug 2026 14:40:15 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/phoenix-source-code-reading/</guid>
      <description>深入解析 xPU-IO/Phoenix：它如何通过内核模块、用户态库和应用适配器，将 SSD 数据直接送入 GPU 显存；并比较 full BAR、staging、batch、stream 等数据路径的实现与取舍。</description>
    </item>
    <item>
      <title>uGDS 原理解析：在用户态打通 NVMe SSD 与 GPU 显存</title>
      <link>https://yangyang233333.github.io/posts/ugds-userspace-gpu-direct-storage/</link>
      <pubDate>Thu, 20 Aug 2026 13:55:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/ugds-userspace-gpu-direct-storage/</guid>
      <description>&lt;p&gt;大模型推理正在把存储重新推到系统性能的核心位置。模型权重、KV Cache、Embedding 和训练检查点都可能在 SSD、主存与 GPU 显存之间频繁搬运。传统路径通常要经过文件系统、内核块层、页缓存或用户态中转缓冲区，不但增加 CPU 开销，也让小块 I/O 延迟变得难以控制。&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ScaleX-IO/uGDS&#34;&gt;uGDS&lt;/a&gt; 是 ScaleX-IO 开源的一套用户态 GPU Direct Storage 开发库。它的核心思路很直接：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;让 CPU 在用户态构造 NVMe 命令并管理提交队列与完成队列，由 SSD 通过 PCIe P2P DMA 直接读写 GPU 显存，从数据路径中绕开内核 NVMe 驱动和文件系统。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本文结合 uGDS 当前源码，解释它为什么快、一次 I/O 如何执行、内核模块与用户态库如何分工，以及使用这类“绕过内核”的存储栈时必须承担哪些工程责任。&lt;/p&gt;
&lt;h2 id=&#34;一ugds-想解决什么问题&#34;&gt;一、uGDS 想解决什么问题&lt;/h2&gt;
&lt;p&gt;先看一条常见的数据读取路径：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NVMe SSD
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;内核 NVMe 驱动 → 块层 → 文件系统
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;主机内存缓冲区
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GPU 显存
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;即使系统支持 Direct I/O，应用仍然通常要进入内核，由内核驱动准备 NVMe 命令、完成 DMA 映射并处理中断或轮询。若数据还要经过主机内存，再复制到 GPU，路径会更长。&lt;/p&gt;</description>
    </item>
    <item>
      <title>NVIDIA GPU-Initiated Data Storage（GIDS）详解：让 GPU Kernel 主动访问存储</title>
      <link>https://yangyang233333.github.io/posts/nvidia-gpu-initiated-data-storage-gids/</link>
      <pubDate>Wed, 19 Aug 2026 14:05:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/nvidia-gpu-initiated-data-storage-gids/</guid>
      <description>&lt;p&gt;GPUDirect Storage（GDS）已经能够让存储数据绕过 CPU 内存，直接进入 GPU 显存。但经典 GDS 仍有一个重要特征：I/O 请求由 CPU 侧应用代码提交。&lt;/p&gt;
&lt;p&gt;当 GPU kernel 在执行过程中才知道下一份数据位于哪里时，控制权必须在 GPU 与 CPU 之间往返。对于图计算、向量检索、稀疏模型和超大规模数据分析，这种细粒度同步可能比数据传输本身更昂贵。&lt;/p&gt;
&lt;p&gt;NVIDIA GPU-Initiated Data Storage，简称 &lt;strong&gt;GIDS&lt;/strong&gt;，试图进一步消除这层控制瓶颈：让 GPU kernel 直接发起存储 I/O，使 GPU 不仅是数据的接收者，也是 I/O 请求的生产者。&lt;/p&gt;
&lt;p&gt;本文介绍 GIDS 的动机、架构、工作流程、适用场景，以及它和 GDS 的本质区别。&lt;/p&gt;
&lt;h2 id=&#34;一为什么有了-gds-还需要-gids&#34;&gt;一、为什么有了 GDS 还需要 GIDS&lt;/h2&gt;
&lt;p&gt;GDS 优化了数据路径：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CPU 发起请求
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;     ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;存储 ─────────────► GPU 显存
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       数据不经过 CPU 内存
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这已经消除了大量主机内存中转，但控制路径仍然经过 CPU。经典流程可能是：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;GPU 执行 kernel；&lt;/li&gt;
&lt;li&gt;GPU 产生下一批要访问的数据索引；&lt;/li&gt;
&lt;li&gt;kernel 结束或与 CPU 同步；&lt;/li&gt;
&lt;li&gt;CPU 读取结果并构造文件 I/O；&lt;/li&gt;
&lt;li&gt;CPU 调用 cuFile；&lt;/li&gt;
&lt;li&gt;数据进入 GPU；&lt;/li&gt;
&lt;li&gt;CPU 再次启动 kernel。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;如果每次请求都是大块、批量且可提前预测，这种方式通常没有问题。但如果 GPU 在计算过程中产生数以万计甚至更多的动态访问，频繁的 GPU—CPU 往返会带来：&lt;/p&gt;</description>
    </item>
    <item>
      <title>NVIDIA GPUDirect Storage（GDS）详解：让存储数据绕过 CPU 直达 GPU</title>
      <link>https://yangyang233333.github.io/posts/nvidia-gpudirect-storage-gds/</link>
      <pubDate>Wed, 19 Aug 2026 14:00:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/nvidia-gpudirect-storage-gds/</guid>
      <description>&lt;p&gt;在 AI 训练、科学计算和数据分析系统中，GPU 的算力越来越强，但数据从存储设备进入 GPU 的路径却可能成为瓶颈。传统 I/O 通常要先把数据读入 CPU 内存，再复制到 GPU 显存，不仅增加内存带宽消耗，还让 CPU 承担大量数据搬运工作。&lt;/p&gt;
&lt;p&gt;NVIDIA GPUDirect Storage，简称 &lt;strong&gt;GDS&lt;/strong&gt;，解决的正是这个问题：它在存储设备与 GPU 显存之间建立更直接的数据路径，使应用能够通过 &lt;code&gt;cuFile&lt;/code&gt; API 将文件数据读入 GPU 缓冲区，减少 CPU bounce buffer 和不必要的数据复制。&lt;/p&gt;
&lt;p&gt;本文介绍 GDS 的工作原理、软件栈、典型使用方式、适用场景以及它与 GPU-Initiated Data Storage（GIDS）的关系。&lt;/p&gt;
&lt;h2 id=&#34;一传统-gpu-io-为什么效率不高&#34;&gt;一、传统 GPU I/O 为什么效率不高&lt;/h2&gt;
&lt;p&gt;传统文件读取到 GPU 的路径大致如下：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;NVMe / 文件系统
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       │
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;CPU 内存缓冲区
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       │ cudaMemcpy
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;       ▼
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;GPU 显存
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;应用通常先调用 &lt;code&gt;read&lt;/code&gt;、&lt;code&gt;pread&lt;/code&gt; 或异步 I/O 接口，把文件内容读入主机内存，然后再调用 CUDA memcpy 将数据复制到 GPU。&lt;/p&gt;
&lt;p&gt;这条路径存在几个问题：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;同一份数据先经过 CPU 内存，再进入 GPU 显存；&lt;/li&gt;
&lt;li&gt;存储流量和 GPU 传输流量竞争 CPU 内存带宽；&lt;/li&gt;
&lt;li&gt;CPU 需要提交、管理和完成数据搬运；&lt;/li&gt;
&lt;li&gt;大规模 GPU 系统中，CPU 和内存通道容易成为共享瓶颈；&lt;/li&gt;
&lt;li&gt;应用需要维护主机端 staging buffer，并处理双重缓冲。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当 GPU 计算越来越快、单机挂载更多 NVMe 或更高速的并行文件系统后，这些额外开销会更加明显。&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
