<?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>Tutti on Hellokitty&#39;s Blog</title>
    <link>https://yangyang233333.github.io/tags/tutti/</link>
    <description>Recent content in Tutti on Hellokitty&#39;s Blog</description>
    <generator>Hugo</generator>
    <language>zh-CN</language>
    <lastBuildDate>Thu, 03 Sep 2026 17:40:00 +0800</lastBuildDate>
    <atom:link href="https://yangyang233333.github.io/tags/tutti/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Tutti 源码阅读（二）：GPU 如何直接驱动 NVMe 队列</title>
      <link>https://yangyang233333.github.io/posts/tutti-snvme-source-reading/</link>
      <pubDate>Thu, 03 Sep 2026 17:40:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/tutti-snvme-source-reading/</guid>
      <description>&lt;p&gt;Tutti 最具辨识度的代码位于运行时以下：自定义 &lt;code&gt;snvme&lt;/code&gt; 内核模块建立受控 NVMe queue pair，&lt;code&gt;libnvm&lt;/code&gt; 管理设备资源，GPU kernel 批量写 SQE、更新 doorbell 并轮询 CQE。数据通过 PCIe P2P DMA 在 SSD 与 HBM 之间移动，CPU 不再逐条提交 I/O。&lt;/p&gt;
&lt;p&gt;本文沿一次读请求下潜，分析为什么主线 Linux NVMe 驱动不够、控制面与数据面如何分离、GPU 如何构造命令，以及条带化和 layer-wise overlap 怎样落实到代码结构。&lt;/p&gt;
&lt;p&gt;项目源码：&lt;a href=&#34;https://github.com/xPU-IO/Tutti&#34;&gt;xPU-IO/Tutti&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&#34;一为什么需要自定义-snvme&#34;&gt;一、为什么需要自定义 &lt;code&gt;snvme&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;NVMe 控制器的数据面并不复杂：主机写 Submission Queue，更新 MMIO doorbell，设备执行 DMA，再把 Completion Queue Entry 写回内存。&lt;/p&gt;
&lt;p&gt;问题是 Linux 主线 NVMe 驱动没有向普通应用提供一套稳定机制，用来同时完成：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建应用独占或受控的 I/O queue pair；&lt;/li&gt;
&lt;li&gt;将 SQ/CQ 放入可被应用或 GPU 访问的固定内存；&lt;/li&gt;
&lt;li&gt;把对应 doorbell BAR 页安全映射给应用；&lt;/li&gt;
&lt;li&gt;将 GPU HBM 注册成 NVMe 可 DMA 的 peer memory；&lt;/li&gt;
&lt;li&gt;允许应用自行轮询 CQ，而不经过每请求系统调用。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;传统 &lt;code&gt;read&lt;/code&gt;、&lt;code&gt;io_uring&lt;/code&gt; 或 GDS 可以缩短部分路径，但 NVMe 队列仍主要由内核或 CPU 侧库控制。Tutti 要让 GPU 成为请求生产者，因此需要一个负责授权与建图的内核控制面。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tutti 源码阅读（一）：StorageRuntime 如何组织 KV Cache I/O</title>
      <link>https://yangyang233333.github.io/posts/tutti-runtime-source-reading/</link>
      <pubDate>Thu, 03 Sep 2026 17:35:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/tutti-runtime-source-reading/</guid>
      <description>&lt;p&gt;Tutti 的论文强调 GPU 主导 I/O，但应用首先接触的不是 NVMe doorbell，而是一套稳定的 &lt;code&gt;StorageRuntime&lt;/code&gt; API。它负责把 URI、文件 extent、GPU 内存、后端实例和异步请求组装起来，让上层无需知道底层究竟是单盘、条带化 NVMe，还是未来的其他传输路径。&lt;/p&gt;
&lt;p&gt;本文阅读 Tutti v0.1.1 的运行时源码与设计文档，聚焦五个问题：公开 API 长什么样、&lt;code&gt;open&lt;/code&gt; 如何解析对象、&lt;code&gt;register_memory&lt;/code&gt; 为什么独立存在、&lt;code&gt;submit/wait&lt;/code&gt; 如何路由，以及 vLLM connector 如何接入。&lt;/p&gt;
&lt;p&gt;项目源码：&lt;a href=&#34;https://github.com/xPU-IO/Tutti&#34;&gt;xPU-IO/Tutti&lt;/a&gt;。&lt;/p&gt;
&lt;h2 id=&#34;一先看整体分层&#34;&gt;一、先看整体分层&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;Application / vLLM Connector
&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;      StorageRuntime
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; open · register · submit · wait
&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;   Resolver       DataPath
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; URI → target     IO → backend
&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;      └──── Binding ┘
&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;      local / striped NVMe
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;StorageRuntime&lt;/code&gt; 是唯一稳定的应用接口；Resolver、Binding 和 DataPath 是内部 SPI。这样做避免上层依赖特定 NVMe 驱动或 GPU 厂商实现。&lt;/p&gt;</description>
    </item>
    <item>
      <title>Tutti 论文阅读：让 SSD KV Cache 真正服务长上下文推理</title>
      <link>https://yangyang233333.github.io/posts/tutti-paper-reading/</link>
      <pubDate>Thu, 03 Sep 2026 17:30:00 +0800</pubDate>
      <guid>https://yangyang233333.github.io/posts/tutti-paper-reading/</guid>
      <description>&lt;p&gt;长上下文推理会生成大量 KV Cache。HBM 放不下，DRAM 成本高，NVMe SSD 容量大却经常因为 I/O 控制开销而无法进入关键路径。Tutti 的结论是：问题不只是“数据能否从 SSD 直达显存”，而是&lt;strong&gt;谁负责把数以千计的 KV 块转成设备请求、提交队列并处理完成&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;Tutti 将这条控制路径交给 GPU：CPU 按层启动 I/O kernel，GPU 批量解析 KV 对象、生成 NVMe 命令、敲 doorbell 并轮询完成，同时利用 Transformer 层之间的计算空隙隐藏读取与写回。论文报告，在其测试环境中，相比 SSD-backed LMCache，严格 SLO 下 TTFT 降低 78.3%，可承载请求率提高 2 倍，服务成本降低 27%。&lt;/p&gt;
&lt;p&gt;本文阅读论文 &lt;a href=&#34;https://arxiv.org/abs/2605.03375&#34;&gt;Tutti: Making SSD-Backed KV Cache Practical for Long-Context LLM Serving&lt;/a&gt;，重点解释它为什么需要 GPU-centric I/O、系统如何工作，以及实验结论应该怎样理解。&lt;/p&gt;
&lt;h2 id=&#34;一ssd-kv-cache-为什么难用&#34;&gt;一、SSD KV Cache 为什么难用&lt;/h2&gt;
&lt;p&gt;自回归模型在 prefill 阶段为每层生成 Key 和 Value。后续请求若共享前缀，可以直接载入已有 KV Cache，省去重复计算。&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;请求 A：系统提示词 + 文档 + 问题 A
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;请求 B：系统提示词 + 文档 + 问题 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;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;KV Cache 容量随上下文长度、层数、并发和 KV head 数增长。分层存储因此很自然：&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
