<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>GPU on JasperSao的博客</title><link>https://jasperstonnne.github.io/MyBlog/tags/gpu/</link><description>Recent content in GPU on JasperSao的博客</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sun, 30 Aug 2026 08:12:59 +0000</lastBuildDate><atom:link href="https://jasperstonnne.github.io/MyBlog/tags/gpu/index.xml" rel="self" type="application/rss+xml"/><item><title>AI Infra 讲座：从并行计算到 CUDA、Triton 与 TileLang</title><link>https://jasperstonnne.github.io/MyBlog/p/ai-infra-parallel-computing-cuda-triton-tilelang/</link><pubDate>Sat, 25 Jul 2026 00:00:00 +0800</pubDate><guid>https://jasperstonnne.github.io/MyBlog/p/ai-infra-parallel-computing-cuda-triton-tilelang/</guid><description>&lt;img src="https://jasperstonnne.github.io/MyBlog/p/ai-infra-parallel-computing-cuda-triton-tilelang/cover.svg" alt="Featured image of post AI Infra 讲座：从并行计算到 CUDA、Triton 与 TileLang" /&gt;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;面向刚进入 Infra / AI Infra 领域的初学者&#10;课程时间：2026-07-25&#10;整理依据：96 页课件 + 约 3 小时逐字稿&#10;说明：本文不是逐页复述，而是按知识依赖关系重构。逐字稿中的语音识别错误（如把 warp 写成 work、grid 写成 grade、Triton 写成 ten、TileLang 写成 tell long）均已按上下文纠正。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="0-先给出整场讲座的主线"&gt;0. 先给出整场讲座的主线&#10;&lt;/h2&gt;&lt;p&gt;这场讲座其实在回答一个连续的问题：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;为什么 AI 需要并行计算？&lt;/strong&gt;&#10;大模型中的矩阵乘法、逐元素运算、通信和流水线，都含有大量可以同时完成的工作。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;为什么 GPU 适合做这些计算？&lt;/strong&gt;&#10;GPU 用大量计算单元和高带宽内存换取高吞吐量，并通过并发执行许多 warp 来隐藏单个任务的延迟。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;程序员怎样把计算映射到 GPU？&lt;/strong&gt;&#10;CUDA 用 &lt;code&gt;grid → block/CTA → warp → thread&lt;/code&gt; 描述并行任务，并要求程序员显式处理索引、内存、同步和边界。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;为什么还需要 Triton / TileLang？&lt;/strong&gt;&#10;手写每个线程过于繁琐。Tile-level DSL 让程序员先描述&amp;quot;一块数据如何搬运和计算&amp;quot;，再由编译器完成更细的线程映射。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;这与 AI Infra 有什么关系？&lt;/strong&gt;&#10;算子、编译器、分布式训练、集群通信、推理服务和强化学习系统，本质上都在解决：&#10;&lt;strong&gt;怎样切分计算、放置数据、协调执行，并让昂贵硬件尽可能持续地做有效工作。&lt;/strong&gt;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;可以把全文压缩成一句话：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;AI Infra 的核心不是&amp;quot;GPU 比 CPU 快&amp;quot;，而是识别并行性，并在计算、内存和通信之间设计高效的数据流。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="1-活动定位与课程地图"&gt;1. 活动定位与课程地图&#10;&lt;/h2&gt;&lt;p&gt;本次暑期活动的目标是&amp;quot;学习和实践 AI Infra&amp;quot;，除课程外还计划提供算力、练习、评测排行、交流讨论和业界连接。整体内容分为四个主题：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;主题&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;主要内容&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Kernel 与 ML Compiler&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;CUDA、GPU 编程、DSL、数据布局、流水线、编译器栈、性能上限分析&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Interconnect 与 Communication&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Scale-up / Scale-out、网络互联、P2P、集合通信、MoE/EP、通信计算重叠、存储协同&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;LLM Serving 与 Inference&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;KV Cache、vLLM/SGLang、算子与框架、并行策略、Prefill-Decode 分离、投机解码&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Distributed RL Systems&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;RL 算法、Rollout、训推一致性、分布式 RL、Agentic RL&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;Session 1 是后续所有主题的&amp;quot;地基层&amp;quot;：先建立并行计算、GPU 执行模型和 Kernel 编程的共同语言。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h1 id="第一部分从计算到并行计算"&gt;第一部分：从计算到并行计算&#10;&lt;/h1&gt;&lt;h2 id="2-什么是计算"&gt;2. 什么是计算&#10;&lt;/h2&gt;&lt;p&gt;课程给出的朴素定义是：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;计算是把输入值按照某种规则变换为输出值的过程。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;这个定义可以拆成两件事：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;数据及其搬运&lt;/strong&gt;：输入在哪里？输出写到哪里？中间数据怎样流动？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;计算规则及其执行单元&lt;/strong&gt;：加法、乘法、比较、矩阵乘法由什么硬件完成？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这是一个很重要的 Infra 视角。应用开发常把&amp;quot;算法&amp;quot;当作核心，但性能工程会同时追问：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;算了多少次？&lt;/li&gt;&#10;&lt;li&gt;每次计算需要读写多少字节？&lt;/li&gt;&#10;&lt;li&gt;数据位于寄存器、缓存、显存，还是另一张卡？&lt;/li&gt;&#10;&lt;li&gt;计算单元是在工作，还是在等数据？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;很多程序&amp;quot;算得慢&amp;quot;并不是算术运算慢，而是数据没有及时到达计算单元。&lt;/p&gt;&#10;&lt;h2 id="3-指令时钟周期流水线与-ipc"&gt;3. 指令、时钟周期、流水线与 IPC&#10;&lt;/h2&gt;&lt;p&gt;一个经典处理器执行指令大致经过：&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;取指 → 译码 → 执行 → 访存 → 写回&lt;/code&gt;&lt;/p&gt;&#10;&lt;p&gt;如果把每条指令完整做完才开始下一条，硬件的大量部件会闲置。流水线让不同指令同时处于不同阶段。例如：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;指令 1 正在写回；&lt;/li&gt;&#10;&lt;li&gt;指令 2 正在访存；&lt;/li&gt;&#10;&lt;li&gt;指令 3 正在执行；&lt;/li&gt;&#10;&lt;li&gt;指令 4 正在译码；&lt;/li&gt;&#10;&lt;li&gt;指令 5 正在取指。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&lt;strong&gt;IPC（Instructions Per Cycle）&lt;/strong&gt; 表示平均每周期完成多少条指令。需要注意：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;IPC 不是频率；频率表示一秒有多少周期。&lt;/li&gt;&#10;&lt;li&gt;IPC 也不是程序性能的全部；不同指令的工作量、延迟和吞吐不同。&lt;/li&gt;&#10;&lt;li&gt;超标量处理器能在同一周期发射或完成多条互不依赖的指令，因此 IPC 可能大于 1。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这已经是一种并行：它发生在单个处理器内部，称为&lt;strong&gt;指令级并行（ILP）&lt;/strong&gt;。&lt;/p&gt;&#10;&lt;h2 id="4-延迟与吞吐量"&gt;4. 延迟与吞吐量&#10;&lt;/h2&gt;&lt;p&gt;这是全场最重要的一组区分。&lt;/p&gt;&#10;&lt;h3 id="延迟latency"&gt;延迟（Latency）&#10;&lt;/h3&gt;&lt;p&gt;完成一个任务要等多久。&lt;/p&gt;&#10;&lt;p&gt;例：一个请求从进入推理服务到收到第一个 token 的时间。&lt;/p&gt;&#10;&lt;h3 id="吞吐量throughput"&gt;吞吐量（Throughput）&#10;&lt;/h3&gt;&lt;p&gt;单位时间完成多少任务或多少计算。&lt;/p&gt;&#10;&lt;p&gt;例：一个推理集群每秒处理多少 token。&lt;/p&gt;&#10;&lt;p&gt;GPU 的优势主要是吞吐量，而不是每个单独运算的最低延迟。它的策略是：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;当一个任务在等待数据时，迅速执行另一个已就绪的任务，用大量并发工作隐藏等待。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;因此，&amp;ldquo;GPU 快&amp;quot;必须补全为：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;对具有足够并行度、规则控制流和合适访存模式的工作负载，GPU 往往能提供很高的总吞吐量。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;h2 id="5-什么样的计算能够并行"&gt;5. 什么样的计算能够并行&#10;&lt;/h2&gt;&lt;h3 id="51-数据依赖"&gt;5.1 数据依赖&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;c = a * b&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d = 3 * c&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;d&lt;/code&gt; 必须等待 &lt;code&gt;c&lt;/code&gt;，二者存在真数据依赖，不能直接同时执行。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;c = a * b&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;d = 3 * b&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;e = a + b&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;三条计算只读相同输入、写不同输出，可以并行。&lt;/p&gt;&#10;&lt;p&gt;更系统地说，判断能否并行要看读写集合是否冲突。常见依赖包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;RAW（Read After Write）&lt;/strong&gt;：后者要读前者写出的值，是真依赖。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;WAR（Write After Read）&lt;/strong&gt;：后者写入的位置仍需被前者读取。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;WAW（Write After Write）&lt;/strong&gt;：两个任务写同一位置，最终结果依赖顺序。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="52-竞争互斥和锁"&gt;5.2 竞争、互斥和锁&#10;&lt;/h3&gt;&lt;p&gt;多个执行单元同时读写同一资源，可能产生 race condition。锁、原子操作、屏障可以恢复正确性，但会带来等待和串行化。&lt;/p&gt;&#10;&lt;p&gt;所以，并行化不只是&amp;quot;把任务分成 N 份&amp;rdquo;，还要保证：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;每份任务的读写范围清楚；&lt;/li&gt;&#10;&lt;li&gt;共享状态受到正确保护；&lt;/li&gt;&#10;&lt;li&gt;同步频率不过高；&lt;/li&gt;&#10;&lt;li&gt;结果与执行顺序无关，或执行顺序被明确控制。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="53-通信与同步"&gt;5.3 通信与同步&#10;&lt;/h3&gt;&lt;p&gt;任务即使能拆开，也常常需要交换中间结果。例如：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;多卡训练中聚合梯度；&lt;/li&gt;&#10;&lt;li&gt;求所有设备上的最大值或总和；&lt;/li&gt;&#10;&lt;li&gt;流水线后一阶段等待前一阶段输出；&lt;/li&gt;&#10;&lt;li&gt;MoE 中把 token 路由到不同专家。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;并行收益最终要减去：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;通信时间；&lt;/li&gt;&#10;&lt;li&gt;同步等待；&lt;/li&gt;&#10;&lt;li&gt;数据重新布局；&lt;/li&gt;&#10;&lt;li&gt;任务调度；&lt;/li&gt;&#10;&lt;li&gt;负载不均衡。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这解释了为什么&amp;quot;设备数翻倍&amp;quot;通常不等于&amp;quot;性能翻倍&amp;quot;。&lt;/p&gt;&#10;&lt;h2 id="6-两类基本拆分方法"&gt;6. 两类基本拆分方法&#10;&lt;/h2&gt;&lt;h3 id="61-domain-decomposition按数据域拆分"&gt;6.1 Domain Decomposition：按数据域拆分&#10;&lt;/h3&gt;&lt;p&gt;把一个大数据集切成若干块，让不同计算单元处理不同区域。&lt;/p&gt;&#10;&lt;p&gt;常见切法：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;连续分块（block）；&lt;/li&gt;&#10;&lt;li&gt;循环分配（cyclic）；&lt;/li&gt;&#10;&lt;li&gt;block-cyclic；&lt;/li&gt;&#10;&lt;li&gt;二维或三维网格切分。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;选择切法时要考虑：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;各块计算量是否均衡；&lt;/li&gt;&#10;&lt;li&gt;相邻数据是否频繁交互；&lt;/li&gt;&#10;&lt;li&gt;数据是否连续，能否高效访问；&lt;/li&gt;&#10;&lt;li&gt;每块能否放入更快的存储层。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;矩阵乘法是典型例子。输出矩阵 &lt;code&gt;C = A × B&lt;/code&gt; 的不同块可以独立计算，因此可以先按 &lt;code&gt;M&lt;/code&gt;、&lt;code&gt;N&lt;/code&gt; 维切分输出，再沿归约维 &lt;code&gt;K&lt;/code&gt; 分块累加。&lt;/p&gt;&#10;&lt;h3 id="62-functional-decomposition按功能或阶段拆分"&gt;6.2 Functional Decomposition：按功能或阶段拆分&#10;&lt;/h3&gt;&lt;p&gt;把不同类型的计算放到不同执行单元，或让不同设备负责流水线的不同阶段。&lt;/p&gt;&#10;&lt;p&gt;例：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;CPU 负责调度和控制，GPU 负责密集计算；&lt;/li&gt;&#10;&lt;li&gt;流水线并行中，不同 GPU 负责模型的不同层；&lt;/li&gt;&#10;&lt;li&gt;推理系统中，Prefill 和 Decode 由不同资源池承担。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="63-大模型训练中的典型映射"&gt;6.3 大模型训练中的典型映射&#10;&lt;/h3&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;并行方式&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;拆什么&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;主要代价&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据并行 DP&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不同设备处理不同 batch，模型副本相同&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;梯度 All-Reduce&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;张量并行 TP&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;把单层矩阵按行或列拆到多卡&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;层内频繁通信&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;流水线并行 PP&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不同设备负责不同层&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;流水线气泡、激活传输&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;专家并行 EP&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;不同设备放不同 MoE 专家&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;All-to-All、负载不均&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;序列/上下文并行&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;按序列维切分&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;注意力相关通信&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;现实系统经常组合多种并行方式，形成多维并行拓扑。&lt;/p&gt;&#10;&lt;h2 id="7-flynn-分类从指令流与数据流看硬件"&gt;7. Flynn 分类：从指令流与数据流看硬件&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;类型&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;含义&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;直觉&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SISD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单指令流、单数据流&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;经典串行处理&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SIMD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单指令流、多数据流&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;同一指令同时作用于多个数据元素&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;MISD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多指令流、单数据流&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;很少有严格对应的通用硬件&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;MIMD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多指令流、多数据流&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多核 CPU、集群等通用并行系统&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;这个分类是抽象模型，不应把复杂现代处理器硬塞进唯一格子。GPU 在不同层级上会同时呈现不同特征：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;不同 block 可以执行不同任务，整体具有 MIMD 味道；&lt;/li&gt;&#10;&lt;li&gt;单个 warp 通常以相同指令推进，具有 SIMD/SIMT 味道。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="8-并行编程模型程序员怎样描述计算"&gt;8. 并行编程模型：程序员怎样描述计算&#10;&lt;/h2&gt;&lt;p&gt;课程提到的主要模型包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;共享内存&lt;/strong&gt;：执行单元通过同一地址空间读写数据。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;线程模型&lt;/strong&gt;：创建、同步和管理多个线程。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;分布式内存 / 消息传递&lt;/strong&gt;：不同进程拥有独立内存，通过 send/receive、broadcast、reduce 等显式通信；MPI 是代表。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;PGAS&lt;/strong&gt;：逻辑上提供全局地址空间，但数据具有物理归属。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;SPMD&lt;/strong&gt;：多个执行单元运行同一程序，但依据自身编号处理不同数据。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;MPMD&lt;/strong&gt;：不同执行单元可以运行不同程序。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;混合模型&lt;/strong&gt;：例如节点间 MPI、节点内线程、GPU 上 CUDA。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;不要把 &lt;strong&gt;SPMD&lt;/strong&gt; 和&amp;quot;数据并行训练&amp;quot;混为一谈：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;SPMD 描述&amp;quot;程序是否相同&amp;quot;；&lt;/li&gt;&#10;&lt;li&gt;数据并行描述&amp;quot;模型和数据如何切分&amp;quot;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h1 id="第二部分cuda-编程模型"&gt;第二部分：CUDA 编程模型&#10;&lt;/h1&gt;&lt;h2 id="9-为什么-gpu-适合-aihpc"&gt;9. 为什么 GPU 适合 AI/HPC&#10;&lt;/h2&gt;&lt;p&gt;课程用&amp;quot;三胜&amp;quot;概括 GPU：&lt;/p&gt;&#10;&lt;h3 id="91-更多晶体管用于吞吐型计算"&gt;9.1 更多晶体管用于吞吐型计算&#10;&lt;/h3&gt;&lt;p&gt;CPU 要做好分支预测、乱序执行、低延迟缓存和复杂控制；GPU 把更多面积用于大量相对简单的计算单元。&lt;/p&gt;&#10;&lt;p&gt;这不是&amp;quot;GPU 每个核心都比 CPU 核心强&amp;quot;，而是：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;CPU 强于低延迟、复杂控制和串行任务；&lt;/li&gt;&#10;&lt;li&gt;GPU 强于规则、密集、批量、可并行的任务。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="92-用并发隐藏延迟"&gt;9.2 用并发隐藏延迟&#10;&lt;/h3&gt;&lt;p&gt;GPU 的单次操作或显存访问可能并不低延迟，但 SM 保存大量 warp 的执行状态。一个 warp 等待内存时，调度器可以选择另一个就绪 warp。&lt;/p&gt;&#10;&lt;h3 id="93-高显存带宽"&gt;9.3 高显存带宽&#10;&lt;/h3&gt;&lt;p&gt;训练和推理频繁搬运权重、激活和 KV Cache，高带宽显存非常关键。但标称带宽只有在访问足够连续、事务利用率高时才可能接近。&lt;/p&gt;&#10;&lt;p&gt;课堂中的具体延迟、吞吐和&amp;quot;HBM 比 DDR 快多少倍&amp;quot;是用于建立直觉的示例，不是跨所有 CPU/GPU/内存配置都成立的常数。&lt;/p&gt;&#10;&lt;h2 id="10-cuda-的软件层级与硬件层级"&gt;10. CUDA 的软件层级与硬件层级&#10;&lt;/h2&gt;&lt;h3 id="101-软件视角"&gt;10.1 软件视角&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Kernel launch&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── Grid&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── Block / CTA&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ ├── Warp（NVIDIA 当前通常为 32 threads）&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ ├── Thread&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ └── ...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ └── ...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── ...&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;thread&lt;/strong&gt;：CUDA 编程中最细的逻辑执行实例。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;warp&lt;/strong&gt;：硬件调度与执行的一组线程。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;block / CTA&lt;/strong&gt;：线程合作、共享 shared memory 和执行块级同步的范围。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;grid&lt;/strong&gt;：一次 kernel launch 创建的所有 block。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="102-硬件视角"&gt;10.2 硬件视角&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;GPU&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└── GPC 等更高层组织&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 多个 SM&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── warp schedulers&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── register file&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── shared memory / L1&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── CUDA cores / ALUs&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── Tensor Cores&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── SFU 等专用单元&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一个 block 会被调度到某个 SM，并通常在该 SM 上运行至结束。block 数可以远多于 SM 数，剩余 block 等待调度。&lt;/p&gt;&#10;&lt;h3 id="103-自动可扩展性的来源"&gt;10.3 自动可扩展性的来源&#10;&lt;/h3&gt;&lt;p&gt;一般 CUDA kernel 应让不同 block 相互独立，因为：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;block 的执行顺序没有保证；&lt;/li&gt;&#10;&lt;li&gt;设备可能有几十、几百或更多 SM；&lt;/li&gt;&#10;&lt;li&gt;同一程序无需根据 SM 数重写。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这是一种软件与硬件规模解耦。例外包括 cooperative launch、thread block cluster 等有额外约束的机制，但初学阶段先遵守&amp;quot;block 独立&amp;quot;最安全。&lt;/p&gt;&#10;&lt;h2 id="11-cuda-程序的基本生命周期"&gt;11. CUDA 程序的基本生命周期&#10;&lt;/h2&gt;&lt;p&gt;典型流程：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;CPU（host）准备输入；&lt;/li&gt;&#10;&lt;li&gt;分配 GPU（device）内存；&lt;/li&gt;&#10;&lt;li&gt;把数据从 host memory 复制到 device memory；&lt;/li&gt;&#10;&lt;li&gt;使用 &lt;code&gt;&amp;lt;&amp;lt;&amp;lt;gridDim, blockDim, ...&amp;gt;&amp;gt;&amp;gt;&lt;/code&gt; 启动 kernel；&lt;/li&gt;&#10;&lt;li&gt;GPU 并行执行；&lt;/li&gt;&#10;&lt;li&gt;必要时同步；&lt;/li&gt;&#10;&lt;li&gt;将结果复制回 CPU；&lt;/li&gt;&#10;&lt;li&gt;释放资源并检查错误。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;CUDA C++ 中常见执行空间修饰符：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;__host__&lt;/code&gt;：在 CPU 上执行；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;__device__&lt;/code&gt;：在 GPU 上执行，由 device 代码调用；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;__global__&lt;/code&gt;：声明 kernel，通常由 host 发起并在 device 上执行，返回类型为 &lt;code&gt;void&lt;/code&gt;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;编译链可粗略理解为：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;CUDA C++ (.cu)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── host code → host compiler → CPU code&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── device code → nvcc toolchain → PTX / device binary&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;PTX&lt;/strong&gt; 是虚拟指令集/中间表示，便于在不同代际 GPU 上进一步生成机器代码。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;CUBIN&lt;/strong&gt; 包含面向具体 GPU 架构的机器代码。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="12-从线程编号映射到数据"&gt;12. 从线程编号映射到数据&#10;&lt;/h2&gt;&lt;h3 id="121-一维向量"&gt;12.1 一维向量&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blockIdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;blockDim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;threadIdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;threadIdx.x&lt;/code&gt;：线程在 block 内的局部编号；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;blockIdx.x&lt;/code&gt;：block 在 grid 内的编号；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;blockDim.x&lt;/code&gt;：每个 block 的线程数；&lt;/li&gt;&#10;&lt;li&gt;边界判断处理 &lt;code&gt;N&lt;/code&gt; 不是 block 大小整数倍的情况。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="122-二维矩阵"&gt;12.2 二维矩阵&#10;&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blockIdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;blockDim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;threadIdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;blockIdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;blockDim&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;threadIdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;row&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;col&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;二维数组在内存中仍然是一段线性地址。以行主序为例：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;address(i, j) = base + i * stride_row + j * stride_col&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;对连续张量，通常 &lt;code&gt;stride_col = 1&lt;/code&gt;，&lt;code&gt;stride_row = 列数&lt;/code&gt;。理解 stride 是之后看 Triton 矩阵乘法指针计算的关键。&lt;/p&gt;&#10;&lt;h2 id="13-warpsimt-与分支发散"&gt;13. Warp、SIMT 与分支发散&#10;&lt;/h2&gt;&lt;h3 id="131-simt"&gt;13.1 SIMT&#10;&lt;/h3&gt;&lt;p&gt;SIMT 是 Single Instruction, Multiple Threads。程序员看到独立线程，但硬件通常以 warp 为单位发射指令。&lt;/p&gt;&#10;&lt;p&gt;SIMT 与 SIMD 的直觉差异：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;SIMD 直接表达&amp;quot;一条向量指令作用于多个数据 lane&amp;quot;；&lt;/li&gt;&#10;&lt;li&gt;SIMT 表达&amp;quot;许多逻辑线程运行同一 kernel&amp;quot;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;在 NVIDIA GPU 上，每个线程具有独立执行状态，但同一 warp 中的活跃线程仍以共同指令高效推进。&lt;/p&gt;&#10;&lt;h3 id="132-warp-divergence"&gt;13.2 Warp divergence&#10;&lt;/h3&gt;&lt;p&gt;若同一 warp 内部分线程走 &lt;code&gt;if&lt;/code&gt;，另一部分走 &lt;code&gt;else&lt;/code&gt;，硬件可能依次执行不同路径，并 mask 掉当前路径不参与的线程。&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;threadIdx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;expensive_a&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;expensive_b&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这会让每个 warp 都经历两条路径。优化方向是让相同分支的数据按 warp 边界聚集，使一个 warp 尽量只执行一条路径。&lt;/p&gt;&#10;&lt;p&gt;但不要把&amp;quot;任何 if 都很慢&amp;quot;当成规则：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;所有线程条件一致时没有发散；&lt;/li&gt;&#10;&lt;li&gt;很短的分支可能被编译为 predication；&lt;/li&gt;&#10;&lt;li&gt;边界判断通常只影响少量 warp；&lt;/li&gt;&#10;&lt;li&gt;真正是否成为瓶颈应由 profiler 判断。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="133-warp-level-primitives"&gt;13.3 Warp-level primitives&#10;&lt;/h3&gt;&lt;p&gt;warp 内线程可以通过 shuffle 等原语交换寄存器数据。例如 reduction 可在 &lt;code&gt;log2(32)&lt;/code&gt; 轮中逐步求和，而不必经过 shared memory。&lt;/p&gt;&#10;&lt;h2 id="14-block-内协作与同步"&gt;14. Block 内协作与同步&#10;&lt;/h2&gt;&lt;p&gt;同一 block 内的线程可以：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;访问 shared memory；&lt;/li&gt;&#10;&lt;li&gt;使用原子操作；&lt;/li&gt;&#10;&lt;li&gt;使用内存屏障；&lt;/li&gt;&#10;&lt;li&gt;使用 &lt;code&gt;__syncthreads()&lt;/code&gt; 进行块级同步。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;关键规则：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;&lt;code&gt;__syncthreads()&lt;/code&gt; 必须由 block 中所有相关线程以一致的控制流到达，否则可能死锁或产生未定义行为。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;不能仅仅因为&amp;quot;每个线程最终都会调用一次&amp;quot;就认为安全；它们必须在相同的同步阶段到达。&lt;/p&gt;&#10;&lt;p&gt;Compute Capability 9.0 起，CUDA 还提供可选的 &lt;strong&gt;thread block cluster&lt;/strong&gt;，使一组 block 在受约束的硬件范围内协作，并可使用 distributed shared memory。它是进阶机制，不改变初学者优先保证普通 block 独立的原则。&lt;/p&gt;&#10;&lt;h2 id="15-gpu-内存层次"&gt;15. GPU 内存层次&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;层次&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;可见范围&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;容量/速度直觉&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;主要用途&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Register&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单个 thread&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最小、最快&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;当前值、累加器&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Shared memory&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单个 block/CTA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;小、低延迟、显式管理&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据复用、线程协作&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;L1 cache&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;通常 SM 层级&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;硬件管理&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;缓存局部访问&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;L2 cache&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;全 GPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;更大、更慢&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;跨 SM 数据缓存&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Global memory / HBM&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;全 GPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最大、高延迟、高总带宽&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;权重、激活、输入输出&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Local memory&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;逻辑上 thread 私有，物理上通常在 device memory&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可能很慢&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;寄存器不足时的 spill 等&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Constant memory&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;全局只读且有缓存&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;适合 warp 内相同地址读取&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;常量参数&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;重要纠偏：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&amp;ldquo;local&amp;quot;描述可见性，不保证物理位置靠近线程，也不保证快。&lt;/li&gt;&#10;&lt;li&gt;shared memory 与 L1 常共享片上资源或可配置容量，但具体组织取决于架构。&lt;/li&gt;&#10;&lt;li&gt;寄存器不是无限的；每线程用得太多，会减少同一 SM 可驻留的 warp/block。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="16-合并访存coalescing"&gt;16. 合并访存（Coalescing）&#10;&lt;/h2&gt;&lt;p&gt;一个 warp 的线程访问 global memory 时，硬件会把地址请求合并为尽量少的内存事务。&lt;/p&gt;&#10;&lt;p&gt;理想模式：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lane 0 → A[k]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lane 1 → A[k+1]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;lane 2 → A[k+2]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;...&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;不理想模式：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;大步长跨越；&lt;/li&gt;&#10;&lt;li&gt;随机地址；&lt;/li&gt;&#10;&lt;li&gt;每个事务只使用很少字节；&lt;/li&gt;&#10;&lt;li&gt;未对齐访问导致额外事务。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这就是为什么行主序矩阵中，常把 &lt;code&gt;threadIdx.x&lt;/code&gt; 映射到连续列：同一 warp 内连续线程访问连续地址。&lt;/p&gt;&#10;&lt;h2 id="17-tiling-与矩阵乘法"&gt;17. Tiling 与矩阵乘法&#10;&lt;/h2&gt;&lt;p&gt;朴素矩阵乘法：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;C[m, n] = Σ_k A[m, k] * B[k, n]&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;一个高性能分块思路：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;每个 block 负责 &lt;code&gt;C&lt;/code&gt; 的一个 &lt;code&gt;BLOCK_M × BLOCK_N&lt;/code&gt; 输出块；&lt;/li&gt;&#10;&lt;li&gt;沿 &lt;code&gt;K&lt;/code&gt; 维以 &lt;code&gt;BLOCK_K&lt;/code&gt; 为步长循环；&lt;/li&gt;&#10;&lt;li&gt;每轮把 &lt;code&gt;A&lt;/code&gt;、&lt;code&gt;B&lt;/code&gt; 的对应 tile 从 global memory 搬到 shared memory；&lt;/li&gt;&#10;&lt;li&gt;block 内线程复用这些数据并进行乘加；&lt;/li&gt;&#10;&lt;li&gt;结果在寄存器中累加；&lt;/li&gt;&#10;&lt;li&gt;最后写回 global memory。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;核心收益不是减少数学运算，而是增加数据复用：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;A&lt;/code&gt; 的一个元素可参与同一输出块的多列计算；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;B&lt;/code&gt; 的一个元素可参与同一输出块的多行计算；&lt;/li&gt;&#10;&lt;li&gt;从 HBM 读取一次后，在 shared memory / register 中多次使用。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;这正是后续 Triton 与 TileLang 都以 tile 为核心抽象的原因。&lt;/p&gt;&#10;&lt;h2 id="18-warp-调度延迟隐藏与-occupancy"&gt;18. Warp 调度、延迟隐藏与 Occupancy&#10;&lt;/h2&gt;&lt;h3 id="181-延迟隐藏"&gt;18.1 延迟隐藏&#10;&lt;/h3&gt;&lt;p&gt;当 warp A 等待 global memory 时，调度器可以发射 warp B。要做到这一点，SM 中必须有足够多的可运行 warp。&lt;/p&gt;&#10;&lt;h3 id="182-occupancy"&gt;18.2 Occupancy&#10;&lt;/h3&gt;&lt;p&gt;常用定义：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Occupancy = SM 上实际驻留的 active warps / 该 SM 支持的最大 active warps&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;限制驻留数量的资源包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;每 block 的线程数；&lt;/li&gt;&#10;&lt;li&gt;每线程的寄存器数；&lt;/li&gt;&#10;&lt;li&gt;每 block 的 shared memory；&lt;/li&gt;&#10;&lt;li&gt;架构对 block、warp 的数量上限。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="183-高-occupancy-不等于最高性能"&gt;18.3 高 Occupancy 不等于最高性能&#10;&lt;/h3&gt;&lt;p&gt;更高 occupancy 通常有利于隐藏延迟，但可能与其他优化冲突：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;更多寄存器可减少 spill 和重复访存；&lt;/li&gt;&#10;&lt;li&gt;更大的 shared-memory tile 可提高数据复用；&lt;/li&gt;&#10;&lt;li&gt;但它们会降低可同时驻留的 block/warp 数。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;所以目标不是机械追求 100%，而是找到足以隐藏主要延迟、同时保留高数据复用和低指令开销的配置。&lt;/p&gt;&#10;&lt;h2 id="19-cuda-优化检查表"&gt;19. CUDA 优化检查表&#10;&lt;/h2&gt;&lt;p&gt;课程总结的四个方向可以扩展成：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;暴露足够并行度&lt;/strong&gt;：grid 足够大，能覆盖全部 SM。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;提高数据复用&lt;/strong&gt;：用 register/shared memory 减少重复 HBM 访问。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;改善访存模式&lt;/strong&gt;：合并访问、对齐、减少无效事务。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;减少控制流浪费&lt;/strong&gt;：降低 warp divergence。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;控制资源使用&lt;/strong&gt;：在寄存器、shared memory、occupancy 之间权衡。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;使用专用单元&lt;/strong&gt;：适合时使用 Tensor Core、SFU 等。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;让搬运与计算重叠&lt;/strong&gt;：异步拷贝、pipeline、多 stream。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;基于测量优化&lt;/strong&gt;：先验证正确性，再 benchmark，再 profiler。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h3 id="api-选讲的准确理解"&gt;API 选讲的准确理解&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;CUDA events&lt;/strong&gt;：适合测量 GPU 时间；不要只用 CPU 墙钟且忘记异步执行。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Streams&lt;/strong&gt;：同一 stream 内有序；不同 stream 的工作&amp;quot;有机会&amp;quot;并发，但是否真正重叠取决于依赖、资源、硬件能力和默认 stream 语义。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Unified Memory&lt;/strong&gt;：简化地址与迁移管理，但数据迁移仍有成本；性能敏感场景需要关注预取、驻留和缺页。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;P2P&lt;/strong&gt;：在支持的拓扑与配置下允许 GPU 间直接访问或复制；不是所有 GPU 对都支持，性能也取决于 PCIe/NVLink 等互联。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;hr&gt;&#10;&lt;h1 id="第三部分从-thread-level-到-tile-level"&gt;第三部分：从 Thread-level 到 Tile-level&#10;&lt;/h1&gt;&lt;h2 id="20-为什么需要-tile-level-programming"&gt;20. 为什么需要 Tile-level Programming&#10;&lt;/h2&gt;&lt;p&gt;CUDA 的控制力强，但程序员要显式完成：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;每个 thread 负责什么；&lt;/li&gt;&#10;&lt;li&gt;thread/block 的索引如何映射到数据；&lt;/li&gt;&#10;&lt;li&gt;global/shared/register 之间怎样搬运；&lt;/li&gt;&#10;&lt;li&gt;如何同步；&lt;/li&gt;&#10;&lt;li&gt;如何处理边界；&lt;/li&gt;&#10;&lt;li&gt;如何避免 bank conflict、发散和低效访存。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;但很多 AI Kernel 的自然表述是：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;取一块张量 → 做一次块级计算 → 把结果写回。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;因此 Tile-level DSL 把 block 内的大量线程协作抽象成 tile 操作：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;确定当前 tile；&lt;/li&gt;&#10;&lt;li&gt;加载 tile；&lt;/li&gt;&#10;&lt;li&gt;计算；&lt;/li&gt;&#10;&lt;li&gt;写回；&lt;/li&gt;&#10;&lt;li&gt;用 mask 处理边界。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;程序员仍决定关键分块，编译器负责把 tile 内计算映射到 thread/warp。&lt;/p&gt;&#10;&lt;h2 id="21-triton-编程模型"&gt;21. Triton 编程模型&#10;&lt;/h2&gt;&lt;h3 id="211-基本视角"&gt;21.1 基本视角&#10;&lt;/h3&gt;&lt;ul&gt;&#10;&lt;li&gt;CUDA 从 &lt;strong&gt;thread&lt;/strong&gt; 出发；&lt;/li&gt;&#10;&lt;li&gt;Triton 从 &lt;strong&gt;program instance&lt;/strong&gt; 出发；&lt;/li&gt;&#10;&lt;li&gt;一个 Triton program 通常负责一个输出 tile；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;tl.program_id(axis=...)&lt;/code&gt; 类似取得当前 program 在 launch grid 中的位置；&lt;/li&gt;&#10;&lt;li&gt;thread ID 通常不显式出现。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;&amp;ldquo;一个 Triton program 约等于一个 CUDA block/CTA&amp;quot;是有用的初学者类比，但不是所有情况下都应理解成严格的一对一源码映射。&lt;/p&gt;&#10;&lt;h3 id="212-向量加法"&gt;21.2 向量加法&#10;&lt;/h3&gt;&lt;p&gt;核心结构：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;program_id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;offsets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_SIZE&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;arange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_SIZE&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;offsets&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n_elements&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offsets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offsets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;z_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offsets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;理解重点：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;offsets&lt;/code&gt; 是一组下标，不是单个线程的一个下标；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;mask&lt;/code&gt; 防止最后一个 tile 越界；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;other=0.0&lt;/code&gt; 为越界 load 提供填充值；&lt;/li&gt;&#10;&lt;li&gt;写法表达的是&amp;quot;整个 tile 的向量操作&amp;rdquo;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h3 id="213-矩阵乘法"&gt;21.3 矩阵乘法&#10;&lt;/h3&gt;&lt;p&gt;每个 program 负责 &lt;code&gt;C&lt;/code&gt; 的一个输出块：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acc = zeros(BLOCK_M, BLOCK_N)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;for k0 in range(0, K, BLOCK_K):&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; a_tile = load A[m:m+BLOCK_M, k0:k0+BLOCK_K]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; b_tile = load B[k0:k0+BLOCK_K, n:n+BLOCK_N]&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; acc += dot(a_tile, b_tile)&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;store C tile&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这里有三个分块尺度：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;&lt;code&gt;BLOCK_M&lt;/code&gt;：输出 tile 的行数；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;BLOCK_N&lt;/code&gt;：输出 tile 的列数；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;BLOCK_K&lt;/code&gt;：归约维每轮处理的长度。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;指针计算依赖 stride：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;A[i,j] 地址 = A_base + i * stride_am + j * stride_ak&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;B[i,j] 地址 = B_base + i * stride_bk + j * stride_bn&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;性能还受 program 执行顺序影响，因为相邻 program 是否复用同一批 A/B 数据会改变 L2 命中率。&lt;/p&gt;&#10;&lt;h3 id="214-triton-的真实优缺点"&gt;21.4 Triton 的真实优缺点&#10;&lt;/h3&gt;&lt;p&gt;优点：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Python 风格、代码短；&lt;/li&gt;&#10;&lt;li&gt;保留 tile shape、program 排列等重要决策；&lt;/li&gt;&#10;&lt;li&gt;适合 elementwise、reduction、matmul、attention 和融合算子；&lt;/li&gt;&#10;&lt;li&gt;支持 autotune；&lt;/li&gt;&#10;&lt;li&gt;可显著降低手写 CUDA 的工程成本。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;代价：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;一些线程级布局、shared memory 组织和流水线由编译器决定；&lt;/li&gt;&#10;&lt;li&gt;当性能瓶颈恰好位于这些细节时，调优空间较受限；&lt;/li&gt;&#10;&lt;li&gt;复杂硬件特化和某些 pipeline 表达可能更困难。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;课堂把编译器称为&amp;quot;黑盒&amp;rdquo;、说 PTX/SASS 不透明，是强调控制粒度的说法，不应理解为&amp;quot;完全无法查看生成代码&amp;quot;。实践中可以 dump IR/PTX、结合 profiler 分析；只是源码与最终机器行为之间的映射比手写 CUDA 更间接。&lt;/p&gt;&#10;&lt;h2 id="22-tilelang-编程模型"&gt;22. TileLang 编程模型&#10;&lt;/h2&gt;&lt;p&gt;TileLang 的目标位置可以理解为：&lt;/p&gt;&#10;&#10; &lt;blockquote&gt;&#10; &lt;p&gt;保留 tile-level 的简洁，同时把影响性能的数据流和内存层次更明确地写出来。&lt;/p&gt;&#10;&#10; &lt;/blockquote&gt;&#10;&lt;p&gt;课程中的关键层次：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;函数参数 &lt;code&gt;T.Tensor&lt;/code&gt;：global memory 中的输入输出；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;T.alloc_shared&lt;/code&gt;：CTA 内共享的 tile；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;T.alloc_fragment&lt;/code&gt;：寄存器中的局部累加结果；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;T.copy&lt;/code&gt;：不同内存层次之间搬运；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;T.gemm&lt;/code&gt;：tile 级矩阵乘加；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;T.Pipelined&lt;/code&gt;：沿分块循环表达搬运与计算重叠；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;T.Kernel(...)&lt;/code&gt;：定义 launch grid / CTA 级程序实例。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;一个矩阵乘法的数据流可以写成：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Global A/B&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ T.copy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Shared-memory tiles&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ T.gemm&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Register fragment / accumulator&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ T.copy&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Global C&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其价值在于，读代码时能直接看到：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;数据在哪一层；&lt;/li&gt;&#10;&lt;li&gt;什么数据会被复用；&lt;/li&gt;&#10;&lt;li&gt;沿哪个维度循环；&lt;/li&gt;&#10;&lt;li&gt;搬运和计算是否流水化。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="23-cudatritontilelang-怎样选择"&gt;23. CUDA、Triton、TileLang 怎样选择&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;维度&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;CUDA C++&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;Triton&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;TileLang&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;主要抽象&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;thread / warp / block&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;program / tensor tile&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;tile + 显式内存层次和数据流&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;控制粒度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;最细&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;较高层&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;介于二者之间&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;开发效率&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;较低&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;高&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中等&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;硬件细节负担&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;高&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;较低&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;中等&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;典型场景&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;极端调优、特殊机制、库级实现&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;快速开发与融合常见算子&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;需要显式数据流、pipeline 和可读结构的高性能 kernel&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;选择不是&amp;quot;谁永远更快&amp;quot;，而要问：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;算子是否规则？&lt;/li&gt;&#10;&lt;li&gt;瓶颈是计算、访存、同步还是 launch overhead？&lt;/li&gt;&#10;&lt;li&gt;是否需要特殊硬件指令或复杂流水线？&lt;/li&gt;&#10;&lt;li&gt;是否需要跨硬件后端？&lt;/li&gt;&#10;&lt;li&gt;团队能承担多少开发和维护成本？&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;h2 id="24-torchcompile-与手写-kernel-的关系"&gt;24. &lt;code&gt;torch.compile&lt;/code&gt; 与手写 Kernel 的关系&#10;&lt;/h2&gt;&lt;p&gt;课堂问答认为二者大体正交，这个方向是对的，但机制需要更精确地区分：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;TorchDynamo 负责从 Python 程序捕获可编译的计算图；&lt;/li&gt;&#10;&lt;li&gt;TorchInductor 等后端进行融合、布局、调度和代码生成，GPU 上常生成 Triton kernel；&lt;/li&gt;&#10;&lt;li&gt;CUDA Graphs 可用于减少 CPU launch overhead，但它不是 &lt;code&gt;torch.compile&lt;/code&gt; 捕获 Python 计算图的同义词；&lt;/li&gt;&#10;&lt;li&gt;手写 Triton/TileLang/CUDA 仍有价值，因为通用编译器不一定能生成最适合特殊算子、数据布局或硬件特性的实现。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;因此可以同时使用：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;模型/图级优化：torch.compile&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; +&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;关键热点算子：手写或定制 Kernel&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;&#10;&lt;h1 id="第四部分把这些知识连回-ai-infra"&gt;第四部分：把这些知识连回 AI Infra&#10;&lt;/h1&gt;&lt;h2 id="25-ai-infra-的共同问题"&gt;25. AI Infra 的共同问题&#10;&lt;/h2&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;层级&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;典型对象&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;核心问题&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单条指令/单个 warp&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SIMD/SIMT、分支&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;lane 是否都做有效工作&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单个 block/CTA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;tiling、shared memory&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据能否在片上复用&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单个 GPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SM 调度、HBM、stream&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;是否计算饱和、带宽饱和、延迟被隐藏&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多 GPU&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;TP/PP/DP/EP、collectives&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;计算与通信如何重叠&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;单机推理服务&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;batching、KV Cache、调度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;吞吐、首 token 延迟、显存容量如何权衡&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;集群&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;网络拓扑、容错、资源调度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;如何扩展并保持利用率&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;同一个思想不断重复：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;找到可并行部分；&lt;/li&gt;&#10;&lt;li&gt;选择分块；&lt;/li&gt;&#10;&lt;li&gt;把块映射到硬件；&lt;/li&gt;&#10;&lt;li&gt;把数据放到合适存储层；&lt;/li&gt;&#10;&lt;li&gt;安排通信和同步；&lt;/li&gt;&#10;&lt;li&gt;用并发隐藏不可避免的延迟；&lt;/li&gt;&#10;&lt;li&gt;测量瓶颈并迭代。&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;h2 id="26-为什么矩阵乘法贯穿整个课程"&gt;26. 为什么矩阵乘法贯穿整个课程&#10;&lt;/h2&gt;&lt;p&gt;Transformer 的大量计算最终落在 GEMM 或 GEMM-like Kernel 上，包括：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;Q/K/V 线性投影；&lt;/li&gt;&#10;&lt;li&gt;attention 中的 &lt;code&gt;QKᵀ&lt;/code&gt; 和 &lt;code&gt;PV&lt;/code&gt;；&lt;/li&gt;&#10;&lt;li&gt;MLP 的上投影、门控、下投影；&lt;/li&gt;&#10;&lt;li&gt;训练中的梯度计算；&lt;/li&gt;&#10;&lt;li&gt;张量并行下的分片矩阵乘。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;矩阵乘法同时包含：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;大量独立输出元素；&lt;/li&gt;&#10;&lt;li&gt;沿 K 维的归约；&lt;/li&gt;&#10;&lt;li&gt;明确的数据复用；&lt;/li&gt;&#10;&lt;li&gt;对布局、带宽、缓存和专用矩阵单元的强依赖。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;因此它是学习并行化、tiling、memory hierarchy 和 pipeline 的最佳样例。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h1 id="第五部分课程之外必须补上的性能模型"&gt;第五部分：课程之外必须补上的性能模型&#10;&lt;/h1&gt;&lt;h2 id="27-amdahl-定律串行部分决定强扩展上限"&gt;27. Amdahl 定律：串行部分决定强扩展上限&#10;&lt;/h2&gt;&lt;p&gt;若程序中可并行比例为 &lt;code&gt;p&lt;/code&gt;，使用 &lt;code&gt;N&lt;/code&gt; 个处理单元，理想加速比为：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Speedup(N) = 1 / ((1 - p) + p / N)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;例如 95% 可并行，即使设备无限多，最大加速也只有 &lt;code&gt;1 / 0.05 = 20&lt;/code&gt; 倍。&lt;/p&gt;&#10;&lt;p&gt;现实还要加上通信、同步和调度开销，所以实际更低。它解释了为什么优化最后一点串行瓶颈可能比继续加卡更重要。&lt;/p&gt;&#10;&lt;h2 id="28-strong-scaling-与-weak-scaling"&gt;28. Strong Scaling 与 Weak Scaling&#10;&lt;/h2&gt;&lt;ul&gt;&#10;&lt;li&gt;&lt;strong&gt;Strong scaling&lt;/strong&gt;：总问题规模不变，增加设备，看运行时间能否下降。&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;Weak scaling&lt;/strong&gt;：每台设备的工作量不变，设备与总问题规模一起增长，看总时间能否保持。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;训练一个固定模型更接近 strong scaling；随着 GPU 数增加同时增大 batch 或模型规模，则包含 weak scaling 的味道。&lt;/p&gt;&#10;&lt;h2 id="29-arithmetic-intensity-与-roofline"&gt;29. Arithmetic Intensity 与 Roofline&#10;&lt;/h2&gt;&lt;p&gt;算术强度：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Arithmetic Intensity = 运算次数 FLOPs / 从慢速内存搬运的字节数 Bytes&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;粗略性能上限：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Performance ≤ min(Peak Compute, Memory Bandwidth × Arithmetic Intensity)&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;ul&gt;&#10;&lt;li&gt;算术强度低：通常 &lt;strong&gt;memory-bound&lt;/strong&gt;；&lt;/li&gt;&#10;&lt;li&gt;算术强度高：可能 &lt;strong&gt;compute-bound&lt;/strong&gt;。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;向量加法每个元素只做一次加法，却要读两个输入、写一个输出，通常是 memory-bound。分块矩阵乘法可让载入的数据被多次复用，算术强度高得多，更容易接近计算峰值。&lt;/p&gt;&#10;&lt;p&gt;这比&amp;quot;看到 GPU 峰值 FLOPS 就估算程序速度&amp;quot;可靠得多。&lt;/p&gt;&#10;&lt;h2 id="30-little-定律式的延迟隐藏直觉"&gt;30. Little 定律式的延迟隐藏直觉&#10;&lt;/h2&gt;&lt;p&gt;要维持高吞吐，系统中需要足够多的在途工作：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;并发在途量 ≈ 吞吐量 × 单次延迟&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;显存延迟很高时，需要许多 warp 在途；推理服务中单请求生成有等待时，需要 continuous batching 等调度策略维持设备利用率。底层 GPU 调度和上层服务调度，在这里有相似的结构。&lt;/p&gt;&#10;&lt;h2 id="31-数值精度不是附属问题"&gt;31. 数值精度不是附属问题&#10;&lt;/h2&gt;&lt;p&gt;GPU 的不同单元和编译选项可能在速度与精度之间取舍：&lt;/p&gt;&#10;&lt;ul&gt;&#10;&lt;li&gt;FP32、TF32、FP16、BF16、FP8 等格式吞吐不同；&lt;/li&gt;&#10;&lt;li&gt;累加精度可能高于输入精度；&lt;/li&gt;&#10;&lt;li&gt;&lt;code&gt;--use_fast_math&lt;/code&gt; 等选项可能使用更快但精度/语义不同的近似；&lt;/li&gt;&#10;&lt;li&gt;并行 reduction 改变求和顺序，浮点结果可能与串行结果略有不同。&lt;/li&gt;&#10;&lt;/ul&gt;&#10;&lt;p&gt;性能优化必须同时定义正确性容忍度：绝对误差、相对误差、ULP、任务指标或训练稳定性。&lt;/p&gt;&#10;&lt;hr&gt;&#10;&lt;h1 id="第六部分容易误解的课堂表述"&gt;第六部分：容易误解的课堂表述&#10;&lt;/h1&gt;&lt;h2 id="32-纠偏清单"&gt;32. 纠偏清单&#10;&lt;/h2&gt;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;GPU 比 CPU 快&amp;rdquo;&lt;/strong&gt;&#10;只对适合高吞吐并行、具有足够工作量和良好数据访问的任务成立。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;有 N 个核心就快 N 倍&amp;rdquo;&lt;/strong&gt;&#10;这是无依赖、无通信、无调度开销、负载完全均衡时的理想上限。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;一个 warp 的 32 个线程必须一直执行相同指令&amp;rdquo;&lt;/strong&gt;&#10;它们可以发生分支，但不同路径通常会被分阶段执行，造成发散开销。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;block 之间绝对不能通信&amp;rdquo;&lt;/strong&gt;&#10;普通 kernel 的可扩展模型要求 block 独立；现代 CUDA 有 cooperative groups、cluster 等受约束机制，但不能默认依赖任意 block 的调度顺序。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Shared memory 一定比 global memory 快&amp;rdquo;&lt;/strong&gt;&#10;通常低延迟且可控，但 bank conflict、额外同步、低复用或过高资源占用都可能抵消收益。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Occupancy 越高越好&amp;rdquo;&lt;/strong&gt;&#10;需要&amp;quot;足够高&amp;quot;来隐藏延迟，不必盲目追求 100%。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;多个 stream 就一定并发&amp;rdquo;&lt;/strong&gt;&#10;stream 只提供并发机会；真实重叠取决于依赖和硬件资源。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Unified Memory 不需要考虑拷贝&amp;rdquo;&lt;/strong&gt;&#10;API 简化了，但迁移、缺页和驻留成本仍然存在。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;Triton 看不到生成代码&amp;rdquo;&lt;/strong&gt;&#10;可检查编译中间表示和生成代码；真正的限制是控制较间接、调优与定位成本可能较高。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;torch.compile 就是 CUDA Graph&amp;rdquo;&lt;/strong&gt;&#10;计算图捕获、编译优化、代码生成和 CUDA Graphs 是不同环节，可能组合使用。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;strong&gt;&amp;ldquo;TileLang 一定跨平台且性能都好&amp;rdquo;&lt;/strong&gt;&#10;可移植抽象能减少迁移成本，但新后端仍需要编译器支持、调度适配和性能验证。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;hr&gt;&#10;&lt;h1 id="第七部分术语速查"&gt;第七部分：术语速查&#10;&lt;/h1&gt;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;术语&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;一句话解释&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HPC&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;High Performance Computing，高性能计算&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;AI Infra&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;支撑 AI 训练、推理和部署的软硬件系统&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Kernel&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;在加速器上执行的一段计算函数&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Host / Device&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;通常分别指 CPU 侧 / GPU 侧&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Grid&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;一次 CUDA kernel launch 的全部 block&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Block / CTA&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;可在同一 SM 上合作、共享 shared memory 的线程组&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Warp&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NVIDIA GPU 的线程调度/执行分组，通常含 32 个线程&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SM&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Streaming Multiprocessor，执行 block/warp 的硬件单元&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SIMT&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Single Instruction, Multiple Threads&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SIMD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Single Instruction, Multiple Data&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SPMD&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Single Program, Multiple Data&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Tile&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;数据张量的一个分块&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Tiling&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;把大计算分成适合并行和存储层次的小块&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Coalescing&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;合并同一 warp 的连续内存请求&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Divergence&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;同一 warp 的线程走不同控制路径&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Occupancy&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;SM 实际驻留 warp 与架构上限之比&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Register pressure&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;每线程寄存器需求对驻留并发度造成的压力&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Spill&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;寄存器不足，变量被放到更慢的 local/device memory&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Reduction&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;把多个值按加、最大值等操作聚合&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Collective&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;多进程/多设备共同参与的通信操作&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;DSL&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Domain-Specific Language，面向特定领域的语言&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;PTX / SASS&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;NVIDIA 的虚拟指令集 / 更接近实际 GPU 机器指令的表示&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;HBM&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;High Bandwidth Memory，高带宽显存&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;Arithmetic Intensity&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;每搬运一字节数据能完成多少运算&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;hr&gt;&#10;&lt;h1 id="第八部分推荐的权威延伸资料"&gt;第八部分：推荐的权威延伸资料&#10;&lt;/h1&gt;&lt;ol&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://docs.nvidia.com/cuda/cuda-programming-guide/01-introduction/programming-model.html" target="_blank" rel="noopener"&#10; &gt;NVIDIA CUDA Programming Guide：Programming Model&lt;/a&gt;&#10;优先读 thread block、grid、SM、block 独立性和内存层次。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://docs.nvidia.com/cuda/cuda-programming-guide/02-basics/intro-to-cuda-cpp.html" target="_blank" rel="noopener"&#10; &gt;NVIDIA CUDA Programming Guide：Introduction to CUDA C++&lt;/a&gt;&#10;对照课堂中的 kernel、内置索引和 thread block cluster。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://triton-lang.org/main/getting-started/tutorials/" target="_blank" rel="noopener"&#10; &gt;Triton 官方教程总览&lt;/a&gt;&#10;推荐依次做 vector add、fused softmax、matrix multiplication。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://triton-lang.org/main/getting-started/tutorials/01-vector-add.html" target="_blank" rel="noopener"&#10; &gt;Triton Vector Addition&lt;/a&gt;&#10;用于掌握 &lt;code&gt;program_id → offsets → mask → load → compute → store&lt;/code&gt;。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://triton-lang.org/main/getting-started/tutorials/03-matrix-multiplication.html" target="_blank" rel="noopener"&#10; &gt;Triton Matrix Multiplication&lt;/a&gt;&#10;重点看三维分块、pointer arithmetic、L2-friendly program ordering 和 autotune。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://tilelang.com/language_ref/tilelibrary.html" target="_blank" rel="noopener"&#10; &gt;TileLang TileLibrary Reference&lt;/a&gt;&#10;查阅 &lt;code&gt;T.alloc_shared&lt;/code&gt;、&lt;code&gt;T.Pipelined&lt;/code&gt; 等原语。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;li&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://docs.pytorch.org/docs/stable/generated/torch.compile.html" target="_blank" rel="noopener"&#10; &gt;PyTorch &lt;code&gt;torch.compile&lt;/code&gt; 文档&lt;/a&gt;&#10;用于区分图编译、Inductor/Triton 代码生成和 CUDA Graphs。&lt;/p&gt;&#10;&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;hr&gt;&#10;&lt;h2 id="结语应该带走的不是术语而是一个分析模板"&gt;结语：应该带走的不是术语，而是一个分析模板&#10;&lt;/h2&gt;&lt;p&gt;以后看到任何 AI Infra 性能问题，可以按这个顺序问：&lt;/p&gt;&#10;&lt;ol&gt;&#10;&lt;li&gt;&lt;strong&gt;计算是什么？&lt;/strong&gt; 输入、输出、规则分别是什么？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;并行机会在哪里？&lt;/strong&gt; 哪些任务没有依赖？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;怎样分块？&lt;/strong&gt; 按数据、功能、模型层、序列还是专家？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;映射到哪里？&lt;/strong&gt; thread、warp、CTA、SM、GPU、节点分别承担什么？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;数据在哪里？&lt;/strong&gt; register、shared、HBM 还是远端 GPU？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;瓶颈是什么？&lt;/strong&gt; 计算、带宽、延迟、同步、通信还是 launch overhead？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;能否重叠？&lt;/strong&gt; 搬运与计算、通信与计算、不同请求是否可流水化？&lt;/li&gt;&#10;&lt;li&gt;&lt;strong&gt;怎样证明？&lt;/strong&gt; 正确性测试、benchmark 和 profiler 是否支持你的判断？&lt;/li&gt;&#10;&lt;/ol&gt;&#10;&lt;p&gt;当你能够沿这八个问题分析一个 Kernel 或一个分布式系统时，就已经不再只是&amp;quot;知道几个 GPU 术语&amp;quot;，而是在用 Infra 的方式思考。&lt;/p&gt;&#10;</description></item></channel></rss>