<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cuterwrite's Blog</title><link>https://cuterwrite.top/</link><description>Recent content on Cuterwrite's Blog</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><copyright>cuterwrite</copyright><lastBuildDate>Tue, 17 Feb 2026 05:00:00 +0000</lastBuildDate><atom:link href="https://cuterwrite.top/index.xml" rel="self" type="application/rss+xml"/><item><title>Triton CUDA 算子开发入门</title><link>https://cuterwrite.top/p/triton-intro/</link><pubDate>Tue, 17 Feb 2026 05:00:00 +0000</pubDate><guid>https://cuterwrite.top/p/triton-intro/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/ComfyUI_00222__hu8c4c55ba3784f678eff2b858e820a3b7_4931616_filter_10933573887768330671-20260217-1ecdj1-8n.webp" alt="Featured image of post Triton CUDA 算子开发入门" /&gt;&lt;h2 id="前言"&gt;
&lt;a href="#%e5%89%8d%e8%a8%80" class="header-anchor"&gt;#&lt;/a&gt;
前言
&lt;/h2&gt;&lt;p&gt;好久没写博客了。最近一年都在埋头搞研究，但是也在一直关注 AI infra 领域，深感这个领域卷得越来越厉害——大模型训推的性能压力逼着每个团队手写 GPU 算子 kernel，而&amp;quot;用什么工具写&amp;quot;这件事，正在经历洗牌。学习一下主流的 tile-based GPU DSL 对于理解未来几年 AI 算子开发的趋势非常有帮助，所以就有了这篇文章。&lt;/p&gt;
&lt;p&gt;当前基于 tile 的 GPU DSL 竞争激烈：OpenAI 的 Triton 社区最大、生态最全；TVM 阵营的 Tilelang 另辟蹊径；NVIDIA 自家的 CuTe/CUTLASS 则是 C++ 模板元编程的极致。三者风格迥异，但如果只能学一个，Triton 几乎一定是最佳起点，Python 写 kernel，上手门槛最低，而且 PyTorch 2.0 的 &lt;code&gt;torch.compile&lt;/code&gt; 后端就是 Triton。&lt;/p&gt;
&lt;p&gt;这是系列第一篇，从零开始走完&amp;quot;向量加法 → 矩阵乘法 → FlashAttention&amp;quot;的完整路径。&lt;/p&gt;
&lt;h2 id="一为什么是-triton"&gt;
&lt;a href="#%e4%b8%80%e4%b8%ba%e4%bb%80%e4%b9%88%e6%98%af-triton" class="header-anchor"&gt;#&lt;/a&gt;
一、为什么是 Triton？
&lt;/h2&gt;&lt;h3 id="11-gpu-编程范式的演进"&gt;
&lt;a href="#11-gpu-%e7%bc%96%e7%a8%8b%e8%8c%83%e5%bc%8f%e7%9a%84%e6%bc%94%e8%bf%9b" class="header-anchor"&gt;#&lt;/a&gt;
1.1 GPU 编程范式的演进
&lt;/h3&gt;&lt;p&gt;GPU 编程从来都不简单。传统的 CUDA C++ 要求开发者在线程级别思考：手动管理共享内存（shared memory）、手动处理 bank conflict、手动编排异步拷贝流水线。CUTLASS 在此基础上用 C++ 模板抽象了 tile 级别的操作，大幅降低了心智负担，但仍然需要深厚的 C++ 模板元编程功底。&lt;/p&gt;
&lt;p&gt;Triton 的定位很明确：&lt;strong&gt;用 Python 写出 90%+ cuBLAS 性能的 kernel&lt;/strong&gt;。它把编程粒度从线程级提升到 tile 级，让编译器去处理那些繁琐的底层细节。&lt;/p&gt;
&lt;p&gt;下面这张对比表总结了三种范式的核心差异：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;CUDA C++&lt;/th&gt;
&lt;th&gt;CUTLASS&lt;/th&gt;
&lt;th&gt;Triton&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;编程粒度&lt;/td&gt;
&lt;td&gt;线程级&lt;/td&gt;
&lt;td&gt;Tile 级（C++ 模板）&lt;/td&gt;
&lt;td&gt;Tile 级（Python）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;共享内存&lt;/td&gt;
&lt;td&gt;手动管理&lt;/td&gt;
&lt;td&gt;模板抽象&lt;/td&gt;
&lt;td&gt;编译器自动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tensor Core&lt;/td&gt;
&lt;td&gt;手写 PTX / wmma&lt;/td&gt;
&lt;td&gt;CuTe 布局&lt;/td&gt;
&lt;td&gt;&lt;code&gt;tl.dot&lt;/code&gt; 自动映射&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bank conflict&lt;/td&gt;
&lt;td&gt;手动 swizzle&lt;/td&gt;
&lt;td&gt;模板 swizzle&lt;/td&gt;
&lt;td&gt;编译器自动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;流水线&lt;/td&gt;
&lt;td&gt;手动 cp.async&lt;/td&gt;
&lt;td&gt;模板参数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;num_stages&lt;/code&gt; 一个参数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;上手难度&lt;/td&gt;
&lt;td&gt;高&lt;/td&gt;
&lt;td&gt;中高&lt;/td&gt;
&lt;td&gt;低&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;性能上限&lt;/td&gt;
&lt;td&gt;100%&lt;/td&gt;
&lt;td&gt;~98%&lt;/td&gt;
&lt;td&gt;~90-95%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;一个有意思的现象：Triton 的性能天花板确实低一些，但实际项目里，能把 Triton 写到 90% cuBLAS 的人，远比能把 CUDA C++ 写到 95% 的人多。&lt;strong&gt;开发效率本身就是性能的一部分。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="12-编译流水线"&gt;
&lt;a href="#12-%e7%bc%96%e8%af%91%e6%b5%81%e6%b0%b4%e7%ba%bf" class="header-anchor"&gt;#&lt;/a&gt;
1.2 编译流水线
&lt;/h3&gt;&lt;p&gt;Triton 的编译流程始于 Python 源码，历经多层中间表示（IR）的逐级转换，最终生成 GPU 二进制文件：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/triton-20260219-17njbs-zn.webp"
alt="Triton 编译流水线示意图" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Triton 编译流水线示意图&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;整个流水线的核心在于 Triton IR → Triton GPU IR 的转换：在此阶段，编译器会将抽象的 Tile 级操作映射为具体的线程、Warp 及 Tensor Core 指令。“开发者专注 Tile 级逻辑，编译器负责线程级实现”，这正是 Triton 降低算子开发门槛的核心设计哲学。&lt;/p&gt;
&lt;h2 id="二核心概念与指令速查"&gt;
&lt;a href="#%e4%ba%8c%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5%e4%b8%8e%e6%8c%87%e4%bb%a4%e9%80%9f%e6%9f%a5" class="header-anchor"&gt;#&lt;/a&gt;
二、核心概念与指令速查
&lt;/h2&gt;&lt;h3 id="21-执行模型"&gt;
&lt;a href="#21-%e6%89%a7%e8%a1%8c%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;#&lt;/a&gt;
2.1 执行模型
&lt;/h3&gt;&lt;p&gt;Triton 的执行模型有三个关键概念：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;程序实例&lt;/strong&gt;（program）：一个 kernel 的一次执行实例，类似 CUDA 中的 thread block。每个 program 独立运行，拥有自己的 program ID。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;网格&lt;/strong&gt;（grid）：所有 program 实例的排列方式，支持 1D、2D、3D。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;瓦片&lt;/strong&gt;（tile）：每个 program 处理的数据块。tile 的大小由编译期常量（&lt;code&gt;tl.constexpr&lt;/code&gt;）决定。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;和 CUDA 最本质的区别：CUDA 程序员想的是&amp;quot;每个线程做什么&amp;quot;，Triton 程序员想的是&amp;quot;每个 program 处理哪块 tile&amp;quot;。线程怎么协作、数据怎么在寄存器间分布，全交给编译器。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/triton-program-20260218-176vb-wq.webp"
alt="Triton 执行模型示意图" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Triton 执行模型示意图&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;核心 API：&lt;/p&gt;
&lt;h4 id="tlprogram_id"&gt;
&lt;a href="#tlprogram_id" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.program_id&lt;/code&gt;
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;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="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;返回当前 program 在该轴的索引。axis 是 program ID 的维度，取值范围是 0、1、2，分别对应 1D、2D、3D 网格的不同轴。比如在一个 2D 网格中，&lt;code&gt;tl.program_id(0)&lt;/code&gt; 返回行索引，&lt;code&gt;tl.program_id(1)&lt;/code&gt; 返回列索引。&lt;/p&gt;
&lt;h4 id="tlarange"&gt;
&lt;a href="#tlarange" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.arange&lt;/code&gt;
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;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="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;end&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;返回一个包含 &lt;code&gt;[start, end)&lt;/code&gt; 范围内连续整数的 1D 张量。常用于构造 tile 内的偏移索引。&lt;strong&gt;BLOCK_SIZE 必须是 2 的幂&lt;/strong&gt;&lt;/p&gt;
&lt;h4 id="tlconstexpr"&gt;
&lt;a href="#tlconstexpr" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.constexpr&lt;/code&gt;
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;constexpr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;编译期常量装饰器。Triton kernel 中的某些参数必须在编译期确定（如 tile 大小），用 &lt;code&gt;tl.constexpr&lt;/code&gt; 声明后，这些参数就成为编译期常量，编译器可以基于它们进行循环展开、条件分支消除等优化。&lt;/p&gt;
&lt;h3 id="22-内存指令"&gt;
&lt;a href="#22-%e5%86%85%e5%ad%98%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
2.2 内存指令
&lt;/h3&gt;&lt;p&gt;Triton 中用于数据传输的指令包括两个：&lt;code&gt;tl.load&lt;/code&gt; 和 &lt;code&gt;tl.store&lt;/code&gt;，分别负责从显存加载数据到寄存器，以及将寄存器中的数据写回显存。&lt;/p&gt;
&lt;p&gt;对于数据传输指令，其输入数据块和输出数据块的形状、数据类型必须完全相同。&lt;/p&gt;
&lt;h4 id="tlload"&gt;
&lt;a href="#tlload" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.load&lt;/code&gt;
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;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;pointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlockPtr&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&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="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cache_modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;eviction_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;将显存中的数据加载到寄存器。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pointer&lt;/code&gt; 可以是一个整数地址、一个张量（指针矩阵）或一个 block pointer。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;mask&lt;/code&gt; 是一个布尔张量，形状与 &lt;code&gt;pointer&lt;/code&gt; 相同，用于指示哪些位置是有效的内存访问。无效位置会被替换为 &lt;code&gt;other&lt;/code&gt; 的值。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;other&lt;/code&gt; 是当 &lt;code&gt;mask&lt;/code&gt; 为 False 时，用于替换无效位置的默认值。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cache_modifier&lt;/code&gt; 和 &lt;code&gt;eviction_policy&lt;/code&gt; 是高级参数，用于控制缓存行为，通常不需要修改。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="alert-blockquote alert-warning"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;警告&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;无 mask 时越界访问是未定义行为&lt;/strong&gt;——不会报错，但结果不可预测，且极难排查&lt;/p&gt;
&lt;p&gt;&lt;code&gt;other&lt;/code&gt; 参数必须配合 &lt;code&gt;mask&lt;/code&gt; 使用，否则报错&lt;/p&gt;
&lt;p&gt;&lt;code&gt;cache_modifier&lt;/code&gt; 仅对 NVIDIA GPU 有效&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;1D 示例：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;offs&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;
&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;offs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n_elements&lt;/span&gt;
&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;offs&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;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;表示每个 program 加载一个长度为 BLOCK_SIZE 的向量块。&lt;code&gt;mask&lt;/code&gt; 确保当 &lt;code&gt;n_elements&lt;/code&gt; 不是 &lt;code&gt;BLOCK_SIZE&lt;/code&gt; 的倍数时，越界位置不会被访问。&lt;/p&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;2D 示例：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="c1"&gt;# 加载矩阵的一个 (BLOCK_M, BLOCK_N) 子块&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;offs_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# shape: (BLOCK_M,)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;offs_n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&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_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# shape: (BLOCK_N,)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# [:, None] 和 [None, :] 产生广播，构造 (BLOCK_M, BLOCK_N) 的指针矩阵&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ptrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_m&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_n&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_n&lt;/span&gt;
&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_m&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&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="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_n&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tile&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;ptrs&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;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里的 &lt;code&gt;[:, None]&lt;/code&gt; 把 &lt;code&gt;(BLOCK_M,)&lt;/code&gt; 变成 &lt;code&gt;(BLOCK_M, 1)&lt;/code&gt;，&lt;code&gt;[None, :]&lt;/code&gt; 把 &lt;code&gt;(BLOCK_N,)&lt;/code&gt; 变成 &lt;code&gt;(1, BLOCK_N)&lt;/code&gt;，广播后得到 &lt;code&gt;(BLOCK_M, BLOCK_N)&lt;/code&gt; 的指针张量。这是 Triton 中最常见的 2D 索引模式。&lt;/p&gt;
&lt;h4 id="tlstore"&gt;
&lt;a href="#tlstore" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.store&lt;/code&gt;
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pointer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BlockPtr&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cache_modifier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;eviction_policy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;将寄存器中的数据写回显存。参数与 &lt;code&gt;tl.load&lt;/code&gt; 类似&lt;/p&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;1D 示例:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;offs&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;
&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;offs&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n_elements&lt;/span&gt;
&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;out_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;表示每个 program 将一个长度为 BLOCK_SIZE 的向量块写回显存。&lt;code&gt;mask&lt;/code&gt; 确保当 &lt;code&gt;n_elements&lt;/code&gt; 不是 &lt;code&gt;BLOCK_SIZE&lt;/code&gt; 的倍数时，越界位置不会被写入。&lt;/p&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;2D 示例:&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;offs_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;offs_n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&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_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ptrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;base_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_m&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_n&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_n&lt;/span&gt;
&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_m&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&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="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_n&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&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&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;ptrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tile&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;表示每个 program 将一个 &lt;code&gt;(BLOCK_M, BLOCK_N)&lt;/code&gt; 的 tile 写回显存。&lt;code&gt;mask&lt;/code&gt; 确保越界位置不会被写入。&lt;/p&gt;
&lt;h4 id="tlmake_block_ptr"&gt;
&lt;a href="#tlmake_block_ptr" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.make_block_ptr&lt;/code&gt;
&lt;/h4&gt;&lt;p&gt;Block pointer（块指针）是 Triton 提供的高层抽象，用&amp;quot;矩阵子块&amp;quot;的语义来描述内存访问，而非手动计算指针偏移：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;ptr&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Union&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;strides&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&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="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;block_shape&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;BlockPtr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;base&lt;/code&gt; 是基础指针，可以是整数地址或张量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;shape&lt;/code&gt; 是父张量的完整形状，如 &lt;code&gt;(M, K)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;strides&lt;/code&gt; 是父张量的步长，如 &lt;code&gt;(stride_m, stride_k)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;offsets&lt;/code&gt; 是起始偏移，如 &lt;code&gt;(pid_m * BM, 0)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;block_shape&lt;/code&gt; 是要加载的块形状，如 &lt;code&gt;(BM, BK)&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;order&lt;/code&gt; 是内存布局顺序，&lt;code&gt;(1, 0)&lt;/code&gt; 表示行主序，&lt;code&gt;(0, 1)&lt;/code&gt; 表示列主序。&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;示例：Block pointer 版本的 &lt;code&gt;tl.load&lt;/code&gt;：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;ptr&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;a_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;strides&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stride_am&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;block_shape&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tile&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;ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;对比手动指针算术：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;offs_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;offs_k&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_K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;a_ptrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_m&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_am&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_k&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;a&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;a_ptrs&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_m&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&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="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_k&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;K&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;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;语义更加清晰，编译器也有更多优化空间。&lt;/p&gt;
&lt;h4 id="tladvance"&gt;
&lt;a href="#tladvance" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.advance&lt;/code&gt;
&lt;/h4&gt;&lt;p&gt;Advance 是 Triton 提供的 block pointer 专用指令，用于在块指针上进行语义清晰的推进：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;ptr&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ptr&lt;/span&gt;&lt;span class="p"&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;Tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;BlockPtr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ptr&lt;/code&gt; 是一个 block pointer。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;offsets&lt;/code&gt; 是要推进的块偏移，如 &lt;code&gt;(0, BLOCK_K)&lt;/code&gt; 表示沿 K 维度推进一个块。&lt;/li&gt;
&lt;li&gt;返回一个新的 block pointer，指向推进后的新位置。&lt;/li&gt;
&lt;li&gt;语义清晰，编译器可以自动处理边界检查和优化。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对比手动指针算术：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;a_ptrs&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;为什么推荐 block pointer？三个原因：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;自动边界检查&lt;/strong&gt;：&lt;code&gt;boundary_check=(0, 1)&lt;/code&gt; 一个参数搞定，无需手写 mask 广播&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;触发 TMA&lt;/strong&gt;：在 Hopper（H100）架构上，block pointer 会自动映射到 TMA，大幅提升内存带宽利用率&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;编译器优化空间更大&lt;/strong&gt;：block pointer 携带了更丰富的语义信息，编译器可以自动做 swizzle 等优化&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="23-计算指令"&gt;
&lt;a href="#23-%e8%ae%a1%e7%ae%97%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
2.3 计算指令
&lt;/h3&gt;&lt;h4 id="tldot"&gt;
&lt;a href="#tldot" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;tl.dot&lt;/code&gt;
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;other&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;input_precision&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;max_num_imprecise_acc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Optional&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Tensor&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;计算矩阵乘法 out = input @ other，假设 &lt;code&gt;input&lt;/code&gt; 的形状是 &lt;code&gt;(M, K)&lt;/code&gt;，&lt;code&gt;other&lt;/code&gt; 的形状是 &lt;code&gt;(K, N)&lt;/code&gt;，则输出的形状是 &lt;code&gt;(M, N)&lt;/code&gt;。&lt;/p&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;示例：tl.dot 的典型用法&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;a&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;a_ptrs&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;offs_k&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;b&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;b_ptrs&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;offs_k&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;acc&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;dot&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;tl.dot&lt;/code&gt; 会自动映射到 Tensor Core 的 MMA（Matrix Multiply-Accumulate）指令。这是 Triton 中性能最关键的操作——一个 &lt;code&gt;tl.dot&lt;/code&gt; 调用，编译器会自动帮你生成 &lt;code&gt;wmma&lt;/code&gt;（Volta/Turing）或 &lt;code&gt;mma&lt;/code&gt;（Ampere）或 &lt;code&gt;wgmma&lt;/code&gt;（Hopper）指令。&lt;/p&gt;
&lt;p&gt;支持的数据类型组合：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input A&lt;/th&gt;
&lt;th&gt;Input B&lt;/th&gt;
&lt;th&gt;累加器&lt;/th&gt;
&lt;th&gt;硬件要求&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;float16&lt;/td&gt;
&lt;td&gt;float16&lt;/td&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;Volta+ (SM70)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bfloat16&lt;/td&gt;
&lt;td&gt;bfloat16&lt;/td&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;Ampere+ (SM80)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float8e4nv&lt;/td&gt;
&lt;td&gt;float8e4nv&lt;/td&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;Hopper+ (SM90)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int8&lt;/td&gt;
&lt;td&gt;int8&lt;/td&gt;
&lt;td&gt;int32&lt;/td&gt;
&lt;td&gt;Turing+ (SM75)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;默认用 TF32 (SM80+)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote class="alert-blockquote alert-important"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;重要&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;累加器永远用 float32（整型用 int32）。如果用 float16 做累加器，精度损失会非常严重。这是 Triton kernel 的铁律。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="归约操作"&gt;
&lt;a href="#%e5%bd%92%e7%ba%a6%e6%93%8d%e4%bd%9c" class="header-anchor"&gt;#&lt;/a&gt;
归约操作
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sum&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; &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; &lt;span class="c1"&gt;# 沿 axis=0 求和&lt;/span&gt;
&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;max&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; &lt;span class="n"&gt;axis&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 沿 axis=1 取最大值&lt;/span&gt;
&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;min&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; &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; &lt;span class="c1"&gt;# 沿 axis=0 取最小值&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这些归约操作在 softmax、LayerNorm 等 kernel 中频繁出现，编译器会将其映射为高效的 warp-level shuffle 归约。&lt;/p&gt;
&lt;h4 id="条件选择"&gt;
&lt;a href="#%e6%9d%a1%e4%bb%b6%e9%80%89%e6%8b%a9" class="header-anchor"&gt;#&lt;/a&gt;
条件选择
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;condition&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; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;与 NumPy 的 &lt;code&gt;np.where&lt;/code&gt; 语义一致。注意：&lt;strong&gt;两个分支都会被求值&lt;/strong&gt;，所以不能用它来避免越界访问。典型用途是实现 causal mask——把未来位置的注意力分数替换为 &lt;code&gt;-inf&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="24-其它"&gt;
&lt;a href="#24-%e5%85%b6%e5%ae%83" class="header-anchor"&gt;#&lt;/a&gt;
2.4 其它
&lt;/h3&gt;&lt;h4 id="tritonautotune"&gt;
&lt;a href="#tritonautotune" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;@triton.autotune&lt;/code&gt;
&lt;/h4&gt;&lt;p&gt;自动调优是 Triton 的一大特性。你只需要提供一组候选配置，Triton 会在第一次调用时自动 benchmark 每种配置，然后缓存最优的那个：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="nd"&gt;@triton.autotune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;configs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_M&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;BLOCK_N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_M&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;BLOCK_N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;M&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;K&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.jit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;kernel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="o"&gt;...&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;key&lt;/code&gt; 参数非常重要：当 M、N、K 的值发生变化时，最优配置往往也会变（小矩阵适合小 tile，大矩阵适合大 tile），所以 Triton 会为每组不同的 key 值分别搜索最优配置。&lt;/p&gt;
&lt;h4 id="tritonheuristics"&gt;
&lt;a href="#tritonheuristics" class="header-anchor"&gt;#&lt;/a&gt;
&lt;code&gt;@triton.heuristics&lt;/code&gt;
&lt;/h4&gt;&lt;p&gt;启发式装饰器（heuristics）用于从运行时参数派生编译期常量，避免不必要的 benchmark 开销：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="nd"&gt;@triton.heuristics&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;EVEN_K&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;K&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_K&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;典型应用：当 K 恰好是 BLOCK_K 的倍数时，可以跳过 mask 检查，省掉条件分支。&lt;/p&gt;
&lt;h2 id="三实战一向量加法"&gt;
&lt;a href="#%e4%b8%89%e5%ae%9e%e6%88%98%e4%b8%80%e5%90%91%e9%87%8f%e5%8a%a0%e6%b3%95" class="header-anchor"&gt;#&lt;/a&gt;
三、实战一：向量加法
&lt;/h2&gt;&lt;p&gt;问题：给定两个长度为 N 的向量 A 和 B，计算 &lt;code&gt;C[i] = A[i] + B[i]&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;这算是最简单的 Triton kernel，但包含了 Triton 编程的所有基本要素。&lt;/p&gt;
&lt;h3 id="31-分块思路"&gt;
&lt;a href="#31-%e5%88%86%e5%9d%97%e6%80%9d%e8%b7%af" class="header-anchor"&gt;#&lt;/a&gt;
3.1 分块思路
&lt;/h3&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/triton-vecadd-20260218-8wwmq-s0.webp"
alt="Triton 向量加法分块示意图" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Triton 向量加法分块示意图&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;每个 program 处理连续的 BLOCK_SIZE 个元素。program 的总数 = &lt;code&gt;ceil(N / BLOCK_SIZE)&lt;/code&gt;。&lt;/p&gt;
&lt;h3 id="32-完整实现"&gt;
&lt;a href="#32-%e5%ae%8c%e6%95%b4%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;#&lt;/a&gt;
3.2 完整实现
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;torch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton.language&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;tl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.jit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add_kernel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;out_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_elements&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BLOCK_SIZE&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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&gt;&lt;/span&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;block_start&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&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;block_start&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;
&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;
&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&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;output&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;
&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;out_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;output&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;add&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; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&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; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty_like&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;numel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_SIZE&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]),)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;add_kernel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;grid&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; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&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="mi"&gt;1024&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="vm"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;__main__&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;manual_seed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;98432&lt;/span&gt;
&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cuda&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cuda&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;output_triton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;add&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; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;output_torch&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Max error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output_triton&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;output_torch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="33-关键要点"&gt;
&lt;a href="#33-%e5%85%b3%e9%94%ae%e8%a6%81%e7%82%b9" class="header-anchor"&gt;#&lt;/a&gt;
3.3 关键要点
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;mask 的作用&lt;/strong&gt;：当 &lt;code&gt;n_elements&lt;/code&gt; 不是 &lt;code&gt;BLOCK_SIZE&lt;/code&gt; 的倍数时，最后一个 program 的部分 offset 会超出数组边界。mask 确保这些越界位置不会被读写。忘记 mask = 未定义行为。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;BLOCK_SIZE 为什么必须是 2 的幂&lt;/strong&gt;：这是 &lt;code&gt;tl.arange&lt;/code&gt; 的硬件约束。GPU 的 warp 大小是 32，BLOCK_SIZE 必须是 warp 大小的整数倍才能高效映射到硬件线程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;triton.cdiv(n, BLOCK_SIZE)&lt;/code&gt;&lt;/strong&gt;：向上取整除法，等价于 &lt;code&gt;ceil(n / BLOCK_SIZE)&lt;/code&gt;。保证所有元素都被覆盖。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="四实战二矩阵乘法"&gt;
&lt;a href="#%e5%9b%9b%e5%ae%9e%e6%88%98%e4%ba%8c%e7%9f%a9%e9%98%b5%e4%b9%98%e6%b3%95" class="header-anchor"&gt;#&lt;/a&gt;
四、实战二：矩阵乘法
&lt;/h2&gt;&lt;p&gt;矩阵乘法（GEMM）是 GPU 上最重要的计算 kernel，几乎所有深度学习的计算量最终都归结于此。这一节我们从分块思路开始，逐步写出一个高性能的 Triton GEMM kernel。&lt;/p&gt;
&lt;h3 id="41-分块思路"&gt;
&lt;a href="#41-%e5%88%86%e5%9d%97%e6%80%9d%e8%b7%af" class="header-anchor"&gt;#&lt;/a&gt;
4.1 分块思路
&lt;/h3&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/triton-matmul-20260218-9puma-o6.webp"
alt="Triton 矩阵乘法分块示意图" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Triton 矩阵乘法分块示意图&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;核心算法：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;每个 program 负责计算 C 的一个 &lt;code&gt;(BLOCK_M, BLOCK_N)&lt;/code&gt; 子块&lt;/li&gt;
&lt;li&gt;初始化 fp32 累加器为零&lt;/li&gt;
&lt;li&gt;沿 K 维度循环：每步加载 A 的 &lt;code&gt;(BLOCK_M, BLOCK_K)&lt;/code&gt; 和 B 的 &lt;code&gt;(BLOCK_K, BLOCK_N)&lt;/code&gt;，做一次 &lt;code&gt;tl.dot&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;循环结束后，将累加器转换为输出精度并写回 HBM 显存&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="42-基础实现"&gt;
&lt;a href="#42-%e5%9f%ba%e7%a1%80%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;#&lt;/a&gt;
4.2 基础实现
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;span class="lnt"&gt;35
&lt;/span&gt;&lt;span class="lnt"&gt;36
&lt;/span&gt;&lt;span class="lnt"&gt;37
&lt;/span&gt;&lt;span class="lnt"&gt;38
&lt;/span&gt;&lt;span class="lnt"&gt;39
&lt;/span&gt;&lt;span class="lnt"&gt;40
&lt;/span&gt;&lt;span class="lnt"&gt;41
&lt;/span&gt;&lt;span class="lnt"&gt;42
&lt;/span&gt;&lt;span class="lnt"&gt;43
&lt;/span&gt;&lt;span class="lnt"&gt;44
&lt;/span&gt;&lt;span class="lnt"&gt;45
&lt;/span&gt;&lt;span class="lnt"&gt;46
&lt;/span&gt;&lt;span class="lnt"&gt;47
&lt;/span&gt;&lt;span class="lnt"&gt;48
&lt;/span&gt;&lt;span class="lnt"&gt;49
&lt;/span&gt;&lt;span class="lnt"&gt;50
&lt;/span&gt;&lt;span class="lnt"&gt;51
&lt;/span&gt;&lt;span class="lnt"&gt;52
&lt;/span&gt;&lt;span class="lnt"&gt;53
&lt;/span&gt;&lt;span class="lnt"&gt;54
&lt;/span&gt;&lt;span class="lnt"&gt;55
&lt;/span&gt;&lt;span class="lnt"&gt;56
&lt;/span&gt;&lt;span class="lnt"&gt;57
&lt;/span&gt;&lt;span class="lnt"&gt;58
&lt;/span&gt;&lt;span class="lnt"&gt;59
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;torch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton.language&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;tl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.jit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;matmul_kernel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_am&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_bk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_bn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_cm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_cn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Row-major Mapping&lt;/span&gt;
&lt;/span&gt;&lt;/span&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_pid_n&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;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pid_m&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;num_pid_n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pid_n&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;num_pid_n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;offs_am&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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_M&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;offs_bn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&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_N&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;offs_k&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_K&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_ptrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_am&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_am&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_k&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b_ptrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;b_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_k&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_bk&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_bn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_bn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;zeros&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&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;range&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;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&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;a_ptrs&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;offs_k&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b&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;b_ptrs&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;offs_k&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;dot&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_ptrs&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b_ptrs&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_bk&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&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;float16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;offs_cm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;offs_cn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&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_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c_ptrs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c_ptr&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_cm&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; \
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_cm&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offs_cn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_cn&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c_mask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_cm&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&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="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_cn&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&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&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;c_ptrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&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;c_mask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;matmul&lt;/span&gt;&lt;span class="p"&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&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="s2"&gt;&amp;#34;Dimensions mismatch&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_contiguous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_contiguous&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Input tensors must be contiguous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_M&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]),)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;matmul_kernel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&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;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;32&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这个实现是最基础的版本，只需要 50 多行代码，以下性能测试在 A100 上进行，可以看到峰值性能约达 A100 fp16 理论算力（312 TFLOPS）的 70%&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Size (M, K, N)&lt;/th&gt;
&lt;th&gt;Time (ms)&lt;/th&gt;
&lt;th&gt;TFLOPS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;(512, 1024, 512)&lt;/td&gt;
&lt;td&gt;0.025&lt;/td&gt;
&lt;td&gt;21.34&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(1024, 1024, 1024)&lt;/td&gt;
&lt;td&gt;0.026&lt;/td&gt;
&lt;td&gt;82.78&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(2048, 2048, 2048)&lt;/td&gt;
&lt;td&gt;0.094&lt;/td&gt;
&lt;td&gt;182.18&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(4096, 4096, 4096)&lt;/td&gt;
&lt;td&gt;0.631&lt;/td&gt;
&lt;td&gt;217.91&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(8192, 8192, 8192)&lt;/td&gt;
&lt;td&gt;6.297&lt;/td&gt;
&lt;td&gt;174.62&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(16384, 16384, 16384)&lt;/td&gt;
&lt;td&gt;59.825&lt;/td&gt;
&lt;td&gt;147.03&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="43-进阶优化"&gt;
&lt;a href="#43-%e8%bf%9b%e9%98%b6%e4%bc%98%e5%8c%96" class="header-anchor"&gt;#&lt;/a&gt;
4.3 进阶优化
&lt;/h3&gt;&lt;p&gt;矩阵乘法 GEMM 是一个非常基础的算子了，常见的优化思路无非是：swizzling、pipelining、warp specialization、自动调优、WMMA 等，其中共享内存 swizzling 已经被 Triton 自动管理来解决 bank conflict 问题了，我们更关注的是 Tile Swizzling，warp specialization，流水线重叠和自动调优，下面将逐一介绍这些优化在 Triton 中的实现方式。&lt;/p&gt;
&lt;h4 id="优化-1grouped-ordering"&gt;
&lt;a href="#%e4%bc%98%e5%8c%96-1grouped-ordering" class="header-anchor"&gt;#&lt;/a&gt;
优化 1：Grouped Ordering
&lt;/h4&gt;&lt;p&gt;Grouped Ordering 是一种 tile 调度策略，主要解决的是 &lt;strong&gt;L2 缓存命中率低&lt;/strong&gt;的问题。&lt;/p&gt;
&lt;p&gt;之前 GEMM 的基础实现中，program ID 是按照行优先（Row-major）方式映射的：先按行分配 program ID，再按列分配。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;计算顺序&lt;/strong&gt;：先算完第 0 行的所有 Tile，再算第 1 行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;缓存问题&lt;/strong&gt;：在计算第 0 行时，我们需要加载矩阵 A 的第 0 行块和矩阵 B 的所有列块。如果矩阵 B 非常大，等到开始算第 1 行时，之前加载到 L2 缓存里的矩阵 B 的数据可能已经被踢出去了。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;后果&lt;/strong&gt;：每一行计算都要重新从显存（VRAM）读取一遍矩阵 B，带宽压力巨大。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Grouped Ordering 的核心思想是：让计算在 M 维度（行）和 N 维度（列）上都分成小组（group），同一组内的 program 紧挨着执行。比如设置 &lt;code&gt;GROUP_SIZE_M=4&lt;/code&gt;，每 4 行为一个 group，使得一小块矩阵 B 的数据能在 L2 缓存中被多个 Program 循环利用。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/grouped_ordering-20260219-bd7gr-sn.webp"
alt="Grouped Ordering 示意图" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Grouped Ordering 示意图&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;在朴素顺序中，program &lt;code&gt;(0,0)&lt;/code&gt; 和 &lt;code&gt;(1,0)&lt;/code&gt; 都需要 B 的第 0 列 tile，但它们之间隔了 &lt;code&gt;num_pid_n&lt;/code&gt; 个 program。当 &lt;code&gt;num_pid_n&lt;/code&gt; 很大时，B 的第 0 列 tile 早已被 L2 缓存驱逐。而 Grouped Ordering 让需要同一列 B tile 的 program 紧挨着执行，L2 命中率显著提升。&lt;/p&gt;
&lt;h4 id="优化-2block-pointer"&gt;
&lt;a href="#%e4%bc%98%e5%8c%96-2block-pointer" class="header-anchor"&gt;#&lt;/a&gt;
优化 2：Block Pointer
&lt;/h4&gt;&lt;p&gt;用 &lt;code&gt;tl.make_block_ptr&lt;/code&gt; 重写核心循环&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;a_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stride_am&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;b_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&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;&lt;span class="n"&gt;stride_bk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_bn&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;acc&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;zeros&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&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;range&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;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&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;a_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b&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;b_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;dot&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a_block&lt;/span&gt;&lt;span class="p"&gt;,&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_K&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_K&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;2.2 节已经介绍过 &lt;code&gt;tl.make_block_ptr&lt;/code&gt; 和 &lt;code&gt;tl.advance&lt;/code&gt;，这里不再赘述。总之，这个优化的好处在于：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;代码更简洁&lt;/strong&gt;：不需要手动计算指针偏移和 mask，语义更清晰&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自动边界检查&lt;/strong&gt;：&lt;code&gt;boundary_check=(0, 1)&lt;/code&gt; 参数让编译器自动处理越界访问，避免了之前版本中复杂的 mask 计算和广播&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;触发 TMA&lt;/strong&gt;：在 Hopper（H100）架构上，block pointer 会自动映射到 TMA，大幅提升内存带宽利用率&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 id="优化-3autotune"&gt;
&lt;a href="#%e4%bc%98%e5%8c%96-3autotune" class="header-anchor"&gt;#&lt;/a&gt;
优化 3：Autotune
&lt;/h4&gt;&lt;p&gt;可以使用 &lt;code&gt;@triton.autotune&lt;/code&gt; 和 &lt;code&gt;@triton.heuristics&lt;/code&gt; 加上自动调优和启发式优化，让 Triton 在不同的 M、N、K 维度下自动选择最优的 BLOCK_M、BLOCK_N、BLOCK_K 和 GROUP_SIZE_M 参数组合，从而在各种矩阵大小上都能达到较好的性能。&lt;/p&gt;
&lt;p&gt;最终版本的实现如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt; 10
&lt;/span&gt;&lt;span class="lnt"&gt; 11
&lt;/span&gt;&lt;span class="lnt"&gt; 12
&lt;/span&gt;&lt;span class="lnt"&gt; 13
&lt;/span&gt;&lt;span class="lnt"&gt; 14
&lt;/span&gt;&lt;span class="lnt"&gt; 15
&lt;/span&gt;&lt;span class="lnt"&gt; 16
&lt;/span&gt;&lt;span class="lnt"&gt; 17
&lt;/span&gt;&lt;span class="lnt"&gt; 18
&lt;/span&gt;&lt;span class="lnt"&gt; 19
&lt;/span&gt;&lt;span class="lnt"&gt; 20
&lt;/span&gt;&lt;span class="lnt"&gt; 21
&lt;/span&gt;&lt;span class="lnt"&gt; 22
&lt;/span&gt;&lt;span class="lnt"&gt; 23
&lt;/span&gt;&lt;span class="lnt"&gt; 24
&lt;/span&gt;&lt;span class="lnt"&gt; 25
&lt;/span&gt;&lt;span class="lnt"&gt; 26
&lt;/span&gt;&lt;span class="lnt"&gt; 27
&lt;/span&gt;&lt;span class="lnt"&gt; 28
&lt;/span&gt;&lt;span class="lnt"&gt; 29
&lt;/span&gt;&lt;span class="lnt"&gt; 30
&lt;/span&gt;&lt;span class="lnt"&gt; 31
&lt;/span&gt;&lt;span class="lnt"&gt; 32
&lt;/span&gt;&lt;span class="lnt"&gt; 33
&lt;/span&gt;&lt;span class="lnt"&gt; 34
&lt;/span&gt;&lt;span class="lnt"&gt; 35
&lt;/span&gt;&lt;span class="lnt"&gt; 36
&lt;/span&gt;&lt;span class="lnt"&gt; 37
&lt;/span&gt;&lt;span class="lnt"&gt; 38
&lt;/span&gt;&lt;span class="lnt"&gt; 39
&lt;/span&gt;&lt;span class="lnt"&gt; 40
&lt;/span&gt;&lt;span class="lnt"&gt; 41
&lt;/span&gt;&lt;span class="lnt"&gt; 42
&lt;/span&gt;&lt;span class="lnt"&gt; 43
&lt;/span&gt;&lt;span class="lnt"&gt; 44
&lt;/span&gt;&lt;span class="lnt"&gt; 45
&lt;/span&gt;&lt;span class="lnt"&gt; 46
&lt;/span&gt;&lt;span class="lnt"&gt; 47
&lt;/span&gt;&lt;span class="lnt"&gt; 48
&lt;/span&gt;&lt;span class="lnt"&gt; 49
&lt;/span&gt;&lt;span class="lnt"&gt; 50
&lt;/span&gt;&lt;span class="lnt"&gt; 51
&lt;/span&gt;&lt;span class="lnt"&gt; 52
&lt;/span&gt;&lt;span class="lnt"&gt; 53
&lt;/span&gt;&lt;span class="lnt"&gt; 54
&lt;/span&gt;&lt;span class="lnt"&gt; 55
&lt;/span&gt;&lt;span class="lnt"&gt; 56
&lt;/span&gt;&lt;span class="lnt"&gt; 57
&lt;/span&gt;&lt;span class="lnt"&gt; 58
&lt;/span&gt;&lt;span class="lnt"&gt; 59
&lt;/span&gt;&lt;span class="lnt"&gt; 60
&lt;/span&gt;&lt;span class="lnt"&gt; 61
&lt;/span&gt;&lt;span class="lnt"&gt; 62
&lt;/span&gt;&lt;span class="lnt"&gt; 63
&lt;/span&gt;&lt;span class="lnt"&gt; 64
&lt;/span&gt;&lt;span class="lnt"&gt; 65
&lt;/span&gt;&lt;span class="lnt"&gt; 66
&lt;/span&gt;&lt;span class="lnt"&gt; 67
&lt;/span&gt;&lt;span class="lnt"&gt; 68
&lt;/span&gt;&lt;span class="lnt"&gt; 69
&lt;/span&gt;&lt;span class="lnt"&gt; 70
&lt;/span&gt;&lt;span class="lnt"&gt; 71
&lt;/span&gt;&lt;span class="lnt"&gt; 72
&lt;/span&gt;&lt;span class="lnt"&gt; 73
&lt;/span&gt;&lt;span class="lnt"&gt; 74
&lt;/span&gt;&lt;span class="lnt"&gt; 75
&lt;/span&gt;&lt;span class="lnt"&gt; 76
&lt;/span&gt;&lt;span class="lnt"&gt; 77
&lt;/span&gt;&lt;span class="lnt"&gt; 78
&lt;/span&gt;&lt;span class="lnt"&gt; 79
&lt;/span&gt;&lt;span class="lnt"&gt; 80
&lt;/span&gt;&lt;span class="lnt"&gt; 81
&lt;/span&gt;&lt;span class="lnt"&gt; 82
&lt;/span&gt;&lt;span class="lnt"&gt; 83
&lt;/span&gt;&lt;span class="lnt"&gt; 84
&lt;/span&gt;&lt;span class="lnt"&gt; 85
&lt;/span&gt;&lt;span class="lnt"&gt; 86
&lt;/span&gt;&lt;span class="lnt"&gt; 87
&lt;/span&gt;&lt;span class="lnt"&gt; 88
&lt;/span&gt;&lt;span class="lnt"&gt; 89
&lt;/span&gt;&lt;span class="lnt"&gt; 90
&lt;/span&gt;&lt;span class="lnt"&gt; 91
&lt;/span&gt;&lt;span class="lnt"&gt; 92
&lt;/span&gt;&lt;span class="lnt"&gt; 93
&lt;/span&gt;&lt;span class="lnt"&gt; 94
&lt;/span&gt;&lt;span class="lnt"&gt; 95
&lt;/span&gt;&lt;span class="lnt"&gt; 96
&lt;/span&gt;&lt;span class="lnt"&gt; 97
&lt;/span&gt;&lt;span class="lnt"&gt; 98
&lt;/span&gt;&lt;span class="lnt"&gt; 99
&lt;/span&gt;&lt;span class="lnt"&gt;100
&lt;/span&gt;&lt;span class="lnt"&gt;101
&lt;/span&gt;&lt;span class="lnt"&gt;102
&lt;/span&gt;&lt;span class="lnt"&gt;103
&lt;/span&gt;&lt;span class="lnt"&gt;104
&lt;/span&gt;&lt;span class="lnt"&gt;105
&lt;/span&gt;&lt;span class="lnt"&gt;106
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;torch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton.language&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;tl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_autotune_config&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Good config for fp8 inputs.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.autotune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;configs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;get_autotune_config&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;K&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.heuristics&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;EVEN_K&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;K&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_K&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.jit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;matmul_kernel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_am&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_bk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_bn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_cm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_cn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;EVEN_K&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;
&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&gt;&lt;/span&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_pid_m&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;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_pid_n&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;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_pid_in_group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;num_pid_n&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;group_id&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;num_pid_in_group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;first_pid_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;group_size_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_pid_m&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;first_pid_m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_pid_m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&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;num_pid_in_group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;group_size_m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pid_n&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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;num_pid_in_group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;group_size_m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stride_am&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_ak&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&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;&lt;span class="n"&gt;stride_bk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_bn&lt;/span&gt;&lt;span class="p"&gt;),&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;pid_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;zeros&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt; &lt;span class="ow"&gt;in&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;range&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;tl&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_K&lt;/span&gt;&lt;span class="p"&gt;)):&lt;/span&gt;
&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="n"&gt;EVEN_K&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&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;a_block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b&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;b_block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&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;a_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b&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;b_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;dot&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a_block&lt;/span&gt;&lt;span class="p"&gt;,&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_K&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;b_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_K&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&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;float16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;c_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;c_ptr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&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;&lt;span class="n"&gt;stride_cm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_cn&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pid_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&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;c_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;matmul&lt;/span&gt;&lt;span class="p"&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&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="s2"&gt;&amp;#34;Dimensions mismatch&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_contiguous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_contiguous&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Input tensors must be contiguous&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
&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="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;]),&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;matmul_kernel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&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;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;a&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;b&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;代码行仅提升到约 100 行，但性能提升显著，尤其是在大矩阵上，已经十分接近 cuBLAS 的 fp16 性能了：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Size (M, K, N)&lt;/th&gt;
&lt;th&gt;Time (ms)&lt;/th&gt;
&lt;th&gt;TFLOPS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;(512, 1024, 512)&lt;/td&gt;
&lt;td&gt;0.014&lt;/td&gt;
&lt;td&gt;38.31&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(1024, 1024, 1024)&lt;/td&gt;
&lt;td&gt;0.022&lt;/td&gt;
&lt;td&gt;98.55&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(2048, 2048, 2048)&lt;/td&gt;
&lt;td&gt;0.091&lt;/td&gt;
&lt;td&gt;189.26&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(4096, 4096, 4096)&lt;/td&gt;
&lt;td&gt;0.621&lt;/td&gt;
&lt;td&gt;221.42&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(8192, 8192, 8192)&lt;/td&gt;
&lt;td&gt;4.905&lt;/td&gt;
&lt;td&gt;224.14&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(16384, 16384, 16384)&lt;/td&gt;
&lt;td&gt;38.054&lt;/td&gt;
&lt;td&gt;231.15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="五实战三flashattention"&gt;
&lt;a href="#%e4%ba%94%e5%ae%9e%e6%88%98%e4%b8%89flashattention" class="header-anchor"&gt;#&lt;/a&gt;
五、实战三：FlashAttention
&lt;/h2&gt;&lt;h3 id="51-标准-attention-的内存瓶颈"&gt;
&lt;a href="#51-%e6%a0%87%e5%87%86-attention-%e7%9a%84%e5%86%85%e5%ad%98%e7%93%b6%e9%a2%88" class="header-anchor"&gt;#&lt;/a&gt;
5.1 标准 Attention 的内存瓶颈
&lt;/h3&gt;&lt;p&gt;标准的多头注意力（Multi-Head Attention）计算流程如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;计算注意力分数（Attention Score）&lt;/strong&gt;：
将查询矩阵 $Q$ 与转置后的键矩阵 $K^T$ 相乘，生成相似度矩阵 $S$。
$$S = Q K^T, \quad S \in \mathbb{R}^{B \times H \times N \times N}$$
此步骤的时间与空间复杂度均为 $O(N^2)$，会产生巨大的中间张量。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;归一化处理（Softmax）&lt;/strong&gt;：
对 $S$ 进行缩放和 Softmax 操作，得到注意力权重概率分布 $P$。
$$P = \text{softmax}\left(\frac{S}{\sqrt{d_k}}\right), \quad P \in \mathbb{R}^{B \times H \times N \times N}$$
此处再次产生一个 $O(N^2)$ 的全量权重矩阵。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;计算加权输出（Output）&lt;/strong&gt;：
利用权重矩阵 $P$ 对值矩阵 $V$ 进行加权聚合。
$$O = P V, \quad O \in \mathbb{R}^{B \times H \times N \times d}$$&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这个过程中会产生 $S = Q K^T$ 和 $P = \text{softmax}(S)$ 两个规模为 $O(N^2)$ 的中间矩阵。当序列长度 $N$ 上升到 32K 甚至 128K 时，显存直接撑爆；同时，频繁在 HBM 与 SRAM 之间搬运这两个巨型矩阵，导致带宽被彻底锁死。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;FlashAttention 的解法：不实例化 $S$ 和 $P$ 矩阵，通过分块（Tiling）在 SRAM 中一口气算到底，将显存复杂度降为 $O(N)$。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="52-online-softmax-算法"&gt;
&lt;a href="#52-online-softmax-%e7%ae%97%e6%b3%95" class="header-anchor"&gt;#&lt;/a&gt;
5.2 Online Softmax 算法
&lt;/h3&gt;&lt;p&gt;Online Softmax 的核心思想是为每一行维护一个状态三元组 $(m_i, l_i, \mathbf{o}_i)$，通过迭代更新实现增量计算：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;$m_i$：当前已处理部分的行最大值。&lt;/li&gt;
&lt;li&gt;$l_i$：当前局部归一化常数（Softmax 分母）。&lt;/li&gt;
&lt;li&gt;$\mathbf{o}_i$：当前加权累加结果（输出向量）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于每个新的 $K/V$ 块 $j$，更新步骤如下：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;计算局部相似度&lt;/strong&gt;：
计算当前块的原始分数 $S^{(j)}$：
$$S^{(j)} = Q_{\text{block}} \times K_{\text{block}, j}^T$$&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更新行最大值&lt;/strong&gt;：
对比当前块的最大值与历史最大值，确定新的全局最大值 $m_{\text{new}}$：
$$m_{\text{new}} = \max(m_i, \text{row\_max}(S^{(j)}))$$&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;计算修正系数&lt;/strong&gt;：
为了确保数值稳定性以及不同块之间的对齐，计算旧统计量的缩放因子 $\alpha$：
$$\alpha = \exp(m_i - m_{\text{new}})$$&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更新归一化分母&lt;/strong&gt;：
利用修正系数对齐旧分母，并加入当前块的贡献：
$$l_{\text{new}} = l_i \cdot \alpha + \sum \exp(S^{(j)} - m_{\text{new}})$$&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;更新累加器&lt;/strong&gt;：
对旧的输出向量进行重缩放，并累加当前块的新贡献：
$$\mathbf{o}_{\text{new}} = \mathbf{o}_i \cdot \alpha + \exp(S^{(j)} - m_{\text{new}}) \times V_{\text{block}, j}$$&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;迭代状态&lt;/strong&gt;：
更新当前状态：
$$m_i \leftarrow m_{\text{new}}, l_i \leftarrow l_{\text{new}}, \mathbf{o}_i \leftarrow \mathbf{o}_{\text{new}}$$&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;算法正确性&lt;/strong&gt;：
修正系数 $\alpha = \exp(m_i - m_{\text{new}})$ 是算法的关键。当发现更大的局部最大值时（$m_{\text{new}} &amp;gt; m_i$），$\alpha$ 会作为一个小于 1 的缩放因子，对之前基于较小 $m_i$ 计算出的指数项进行补偿。这种机制确保了在分块遍历结束时，最终输出 $O = \mathbf{o}_i / l_i$ 与一次性全局计算的结果在数学上完全等价。&lt;/p&gt;
&lt;h3 id="53-kernel-实现"&gt;
&lt;a href="#53-kernel-%e5%ae%9e%e7%8e%b0" class="header-anchor"&gt;#&lt;/a&gt;
5.3 Kernel 实现
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt; 10
&lt;/span&gt;&lt;span class="lnt"&gt; 11
&lt;/span&gt;&lt;span class="lnt"&gt; 12
&lt;/span&gt;&lt;span class="lnt"&gt; 13
&lt;/span&gt;&lt;span class="lnt"&gt; 14
&lt;/span&gt;&lt;span class="lnt"&gt; 15
&lt;/span&gt;&lt;span class="lnt"&gt; 16
&lt;/span&gt;&lt;span class="lnt"&gt; 17
&lt;/span&gt;&lt;span class="lnt"&gt; 18
&lt;/span&gt;&lt;span class="lnt"&gt; 19
&lt;/span&gt;&lt;span class="lnt"&gt; 20
&lt;/span&gt;&lt;span class="lnt"&gt; 21
&lt;/span&gt;&lt;span class="lnt"&gt; 22
&lt;/span&gt;&lt;span class="lnt"&gt; 23
&lt;/span&gt;&lt;span class="lnt"&gt; 24
&lt;/span&gt;&lt;span class="lnt"&gt; 25
&lt;/span&gt;&lt;span class="lnt"&gt; 26
&lt;/span&gt;&lt;span class="lnt"&gt; 27
&lt;/span&gt;&lt;span class="lnt"&gt; 28
&lt;/span&gt;&lt;span class="lnt"&gt; 29
&lt;/span&gt;&lt;span class="lnt"&gt; 30
&lt;/span&gt;&lt;span class="lnt"&gt; 31
&lt;/span&gt;&lt;span class="lnt"&gt; 32
&lt;/span&gt;&lt;span class="lnt"&gt; 33
&lt;/span&gt;&lt;span class="lnt"&gt; 34
&lt;/span&gt;&lt;span class="lnt"&gt; 35
&lt;/span&gt;&lt;span class="lnt"&gt; 36
&lt;/span&gt;&lt;span class="lnt"&gt; 37
&lt;/span&gt;&lt;span class="lnt"&gt; 38
&lt;/span&gt;&lt;span class="lnt"&gt; 39
&lt;/span&gt;&lt;span class="lnt"&gt; 40
&lt;/span&gt;&lt;span class="lnt"&gt; 41
&lt;/span&gt;&lt;span class="lnt"&gt; 42
&lt;/span&gt;&lt;span class="lnt"&gt; 43
&lt;/span&gt;&lt;span class="lnt"&gt; 44
&lt;/span&gt;&lt;span class="lnt"&gt; 45
&lt;/span&gt;&lt;span class="lnt"&gt; 46
&lt;/span&gt;&lt;span class="lnt"&gt; 47
&lt;/span&gt;&lt;span class="lnt"&gt; 48
&lt;/span&gt;&lt;span class="lnt"&gt; 49
&lt;/span&gt;&lt;span class="lnt"&gt; 50
&lt;/span&gt;&lt;span class="lnt"&gt; 51
&lt;/span&gt;&lt;span class="lnt"&gt; 52
&lt;/span&gt;&lt;span class="lnt"&gt; 53
&lt;/span&gt;&lt;span class="lnt"&gt; 54
&lt;/span&gt;&lt;span class="lnt"&gt; 55
&lt;/span&gt;&lt;span class="lnt"&gt; 56
&lt;/span&gt;&lt;span class="lnt"&gt; 57
&lt;/span&gt;&lt;span class="lnt"&gt; 58
&lt;/span&gt;&lt;span class="lnt"&gt; 59
&lt;/span&gt;&lt;span class="lnt"&gt; 60
&lt;/span&gt;&lt;span class="lnt"&gt; 61
&lt;/span&gt;&lt;span class="lnt"&gt; 62
&lt;/span&gt;&lt;span class="lnt"&gt; 63
&lt;/span&gt;&lt;span class="lnt"&gt; 64
&lt;/span&gt;&lt;span class="lnt"&gt; 65
&lt;/span&gt;&lt;span class="lnt"&gt; 66
&lt;/span&gt;&lt;span class="lnt"&gt; 67
&lt;/span&gt;&lt;span class="lnt"&gt; 68
&lt;/span&gt;&lt;span class="lnt"&gt; 69
&lt;/span&gt;&lt;span class="lnt"&gt; 70
&lt;/span&gt;&lt;span class="lnt"&gt; 71
&lt;/span&gt;&lt;span class="lnt"&gt; 72
&lt;/span&gt;&lt;span class="lnt"&gt; 73
&lt;/span&gt;&lt;span class="lnt"&gt; 74
&lt;/span&gt;&lt;span class="lnt"&gt; 75
&lt;/span&gt;&lt;span class="lnt"&gt; 76
&lt;/span&gt;&lt;span class="lnt"&gt; 77
&lt;/span&gt;&lt;span class="lnt"&gt; 78
&lt;/span&gt;&lt;span class="lnt"&gt; 79
&lt;/span&gt;&lt;span class="lnt"&gt; 80
&lt;/span&gt;&lt;span class="lnt"&gt; 81
&lt;/span&gt;&lt;span class="lnt"&gt; 82
&lt;/span&gt;&lt;span class="lnt"&gt; 83
&lt;/span&gt;&lt;span class="lnt"&gt; 84
&lt;/span&gt;&lt;span class="lnt"&gt; 85
&lt;/span&gt;&lt;span class="lnt"&gt; 86
&lt;/span&gt;&lt;span class="lnt"&gt; 87
&lt;/span&gt;&lt;span class="lnt"&gt; 88
&lt;/span&gt;&lt;span class="lnt"&gt; 89
&lt;/span&gt;&lt;span class="lnt"&gt; 90
&lt;/span&gt;&lt;span class="lnt"&gt; 91
&lt;/span&gt;&lt;span class="lnt"&gt; 92
&lt;/span&gt;&lt;span class="lnt"&gt; 93
&lt;/span&gt;&lt;span class="lnt"&gt; 94
&lt;/span&gt;&lt;span class="lnt"&gt; 95
&lt;/span&gt;&lt;span class="lnt"&gt; 96
&lt;/span&gt;&lt;span class="lnt"&gt; 97
&lt;/span&gt;&lt;span class="lnt"&gt; 98
&lt;/span&gt;&lt;span class="lnt"&gt; 99
&lt;/span&gt;&lt;span class="lnt"&gt;100
&lt;/span&gt;&lt;span class="lnt"&gt;101
&lt;/span&gt;&lt;span class="lnt"&gt;102
&lt;/span&gt;&lt;span class="lnt"&gt;103
&lt;/span&gt;&lt;span class="lnt"&gt;104
&lt;/span&gt;&lt;span class="lnt"&gt;105
&lt;/span&gt;&lt;span class="lnt"&gt;106
&lt;/span&gt;&lt;span class="lnt"&gt;107
&lt;/span&gt;&lt;span class="lnt"&gt;108
&lt;/span&gt;&lt;span class="lnt"&gt;109
&lt;/span&gt;&lt;span class="lnt"&gt;110
&lt;/span&gt;&lt;span class="lnt"&gt;111
&lt;/span&gt;&lt;span class="lnt"&gt;112
&lt;/span&gt;&lt;span class="lnt"&gt;113
&lt;/span&gt;&lt;span class="lnt"&gt;114
&lt;/span&gt;&lt;span class="lnt"&gt;115
&lt;/span&gt;&lt;span class="lnt"&gt;116
&lt;/span&gt;&lt;span class="lnt"&gt;117
&lt;/span&gt;&lt;span class="lnt"&gt;118
&lt;/span&gt;&lt;span class="lnt"&gt;119
&lt;/span&gt;&lt;span class="lnt"&gt;120
&lt;/span&gt;&lt;span class="lnt"&gt;121
&lt;/span&gt;&lt;span class="lnt"&gt;122
&lt;/span&gt;&lt;span class="lnt"&gt;123
&lt;/span&gt;&lt;span class="lnt"&gt;124
&lt;/span&gt;&lt;span class="lnt"&gt;125
&lt;/span&gt;&lt;span class="lnt"&gt;126
&lt;/span&gt;&lt;span class="lnt"&gt;127
&lt;/span&gt;&lt;span class="lnt"&gt;128
&lt;/span&gt;&lt;span class="lnt"&gt;129
&lt;/span&gt;&lt;span class="lnt"&gt;130
&lt;/span&gt;&lt;span class="lnt"&gt;131
&lt;/span&gt;&lt;span class="lnt"&gt;132
&lt;/span&gt;&lt;span class="lnt"&gt;133
&lt;/span&gt;&lt;span class="lnt"&gt;134
&lt;/span&gt;&lt;span class="lnt"&gt;135
&lt;/span&gt;&lt;span class="lnt"&gt;136
&lt;/span&gt;&lt;span class="lnt"&gt;137
&lt;/span&gt;&lt;span class="lnt"&gt;138
&lt;/span&gt;&lt;span class="lnt"&gt;139
&lt;/span&gt;&lt;span class="lnt"&gt;140
&lt;/span&gt;&lt;span class="lnt"&gt;141
&lt;/span&gt;&lt;span class="lnt"&gt;142
&lt;/span&gt;&lt;span class="lnt"&gt;143
&lt;/span&gt;&lt;span class="lnt"&gt;144
&lt;/span&gt;&lt;span class="lnt"&gt;145
&lt;/span&gt;&lt;span class="lnt"&gt;146
&lt;/span&gt;&lt;span class="lnt"&gt;147
&lt;/span&gt;&lt;span class="lnt"&gt;148
&lt;/span&gt;&lt;span class="lnt"&gt;149
&lt;/span&gt;&lt;span class="lnt"&gt;150
&lt;/span&gt;&lt;span class="lnt"&gt;151
&lt;/span&gt;&lt;span class="lnt"&gt;152
&lt;/span&gt;&lt;span class="lnt"&gt;153
&lt;/span&gt;&lt;span class="lnt"&gt;154
&lt;/span&gt;&lt;span class="lnt"&gt;155
&lt;/span&gt;&lt;span class="lnt"&gt;156
&lt;/span&gt;&lt;span class="lnt"&gt;157
&lt;/span&gt;&lt;span class="lnt"&gt;158
&lt;/span&gt;&lt;span class="lnt"&gt;159
&lt;/span&gt;&lt;span class="lnt"&gt;160
&lt;/span&gt;&lt;span class="lnt"&gt;161
&lt;/span&gt;&lt;span class="lnt"&gt;162
&lt;/span&gt;&lt;span class="lnt"&gt;163
&lt;/span&gt;&lt;span class="lnt"&gt;164
&lt;/span&gt;&lt;span class="lnt"&gt;165
&lt;/span&gt;&lt;span class="lnt"&gt;166
&lt;/span&gt;&lt;span class="lnt"&gt;167
&lt;/span&gt;&lt;span class="lnt"&gt;168
&lt;/span&gt;&lt;span class="lnt"&gt;169
&lt;/span&gt;&lt;span class="lnt"&gt;170
&lt;/span&gt;&lt;span class="lnt"&gt;171
&lt;/span&gt;&lt;span class="lnt"&gt;172
&lt;/span&gt;&lt;span class="lnt"&gt;173
&lt;/span&gt;&lt;span class="lnt"&gt;174
&lt;/span&gt;&lt;span class="lnt"&gt;175
&lt;/span&gt;&lt;span class="lnt"&gt;176
&lt;/span&gt;&lt;span class="lnt"&gt;177
&lt;/span&gt;&lt;span class="lnt"&gt;178
&lt;/span&gt;&lt;span class="lnt"&gt;179
&lt;/span&gt;&lt;span class="lnt"&gt;180
&lt;/span&gt;&lt;span class="lnt"&gt;181
&lt;/span&gt;&lt;span class="lnt"&gt;182
&lt;/span&gt;&lt;span class="lnt"&gt;183
&lt;/span&gt;&lt;span class="lnt"&gt;184
&lt;/span&gt;&lt;span class="lnt"&gt;185
&lt;/span&gt;&lt;span class="lnt"&gt;186
&lt;/span&gt;&lt;span class="lnt"&gt;187
&lt;/span&gt;&lt;span class="lnt"&gt;188
&lt;/span&gt;&lt;span class="lnt"&gt;189
&lt;/span&gt;&lt;span class="lnt"&gt;190
&lt;/span&gt;&lt;span class="lnt"&gt;191
&lt;/span&gt;&lt;span class="lnt"&gt;192
&lt;/span&gt;&lt;span class="lnt"&gt;193
&lt;/span&gt;&lt;span class="lnt"&gt;194
&lt;/span&gt;&lt;span class="lnt"&gt;195
&lt;/span&gt;&lt;span class="lnt"&gt;196
&lt;/span&gt;&lt;span class="lnt"&gt;197
&lt;/span&gt;&lt;span class="lnt"&gt;198
&lt;/span&gt;&lt;span class="lnt"&gt;199
&lt;/span&gt;&lt;span class="lnt"&gt;200
&lt;/span&gt;&lt;span class="lnt"&gt;201
&lt;/span&gt;&lt;span class="lnt"&gt;202
&lt;/span&gt;&lt;span class="lnt"&gt;203
&lt;/span&gt;&lt;span class="lnt"&gt;204
&lt;/span&gt;&lt;span class="lnt"&gt;205
&lt;/span&gt;&lt;span class="lnt"&gt;206
&lt;/span&gt;&lt;span class="lnt"&gt;207
&lt;/span&gt;&lt;span class="lnt"&gt;208
&lt;/span&gt;&lt;span class="lnt"&gt;209
&lt;/span&gt;&lt;span class="lnt"&gt;210
&lt;/span&gt;&lt;span class="lnt"&gt;211
&lt;/span&gt;&lt;span class="lnt"&gt;212
&lt;/span&gt;&lt;span class="lnt"&gt;213
&lt;/span&gt;&lt;span class="lnt"&gt;214
&lt;/span&gt;&lt;span class="lnt"&gt;215
&lt;/span&gt;&lt;span class="lnt"&gt;216
&lt;/span&gt;&lt;span class="lnt"&gt;217
&lt;/span&gt;&lt;span class="lnt"&gt;218
&lt;/span&gt;&lt;span class="lnt"&gt;219
&lt;/span&gt;&lt;span class="lnt"&gt;220
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;torch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;triton.language&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;tl&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_autotune_config&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Small blocks — short sequences / small head_dim&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Medium blocks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Large blocks — long sequences&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Higher pipeline depth&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;BLOCK_N&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s1"&gt;&amp;#39;GROUP_SIZE_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;num_stages&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;num_warps&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.autotune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;configs&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;get_autotune_config&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;seq_len&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;HEAD_DIM&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.heuristics&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;EVEN_N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;seq_len&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;BLOCK_N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nd"&gt;@triton.jit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flash_attention_fwd_kernel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;V&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sm_scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_qz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_qh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_qm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_qk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_kz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_kh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_kn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_kk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_vz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_vh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_vn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_vk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;stride_oz&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_oh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_om&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_ok&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_batch_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;IS_CAUSAL&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;EVEN_N&lt;/span&gt;&lt;span class="p"&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;constexpr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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&gt;&lt;/span&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_pid_m&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;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;num_pid_in_group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n_batch_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;group_id&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;num_pid_in_group&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;first_pid_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;group_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;group_size_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;num_pid_m&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;first_pid_m&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;GROUP_SIZE_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;first_pid_m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&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;num_pid_in_group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;group_size_m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pid_bh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&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;num_pid_in_group&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;group_size_m&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;batch_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_bh&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;n_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;head_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_bh&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;n_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Base offsets for this (batch, head)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;batch_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_qz&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;head_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_qh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;batch_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_kz&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;head_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_kh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;batch_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_vz&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;head_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_vh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;o_offset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;batch_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_oz&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;head_id&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;stride_oh&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;Q&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;q_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stride_qm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_qk&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;k_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stride_kn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_kk&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="mi"&gt;0&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;V&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;v_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stride_vn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_vk&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="mi"&gt;0&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# sm_scale * log2(e)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk_scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sm_scale&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.44269504088896340736&lt;/span&gt; &lt;span class="c1"&gt;# sm_scale * log2(e)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q&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;q_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;qk_scale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;element_ty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Online softmax accumulators&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m_i&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;full&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;inf&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;l_i&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;zeros&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;zeros&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Row indices (needed for causal / boundary masks on attention scores)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;offs_m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="n"&gt;IS_CAUSAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;full_blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_blocks&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;cdiv&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;full_blocks&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;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_blocks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;full_blocks&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block_n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&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;full_blocks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&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_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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="n"&gt;EVEN_N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k&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;k_block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k&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;k_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk&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;zeros&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk&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;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&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;trans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;EVEN_N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk&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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;qk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-inf&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# Online softmax with exp2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m_ij&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;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qk&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;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m_new&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;maximum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_ij&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alpha&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;exp2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;m_new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p&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;exp2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qk&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;m_new&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;l_i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l_i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;alpha&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;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&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;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="n"&gt;EVEN_N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&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;v_block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&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;v_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m_i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m_new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_N&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_N&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;block_n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full_blocks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_blocks&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block_n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&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_N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k&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;k_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk&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;zeros&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BLOCK_N&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;dtype&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;float32&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk&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;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&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;trans&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="n"&gt;IS_CAUSAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk&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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;offs_m&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:],&lt;/span&gt; &lt;span class="n"&gt;qk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-inf&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;EVEN_N&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;qk&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;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;:]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;qk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-inf&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m_ij&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;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qk&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;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m_new&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;maximum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m_ij&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;alpha&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;exp2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;m_i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;m_new&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p&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;exp2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qk&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;m_new&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;l_i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;l_i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;alpha&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;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&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;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;alpha&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&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;v_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&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;dot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m_i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m_new&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;k_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_N&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v_block&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;advance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;v_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_N&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;l_i&lt;/span&gt;&lt;span class="p"&gt;[:,&lt;/span&gt; &lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;o_block&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;make_block_ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;O&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;o_offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;stride_om&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;stride_ok&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&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="n"&gt;pid_m&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;BLOCK_M&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;BLOCK_M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&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;o_block&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;acc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;O&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;element_ty&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;boundary_check&lt;/span&gt;&lt;span class="o"&gt;=&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;flash_attention&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;causal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tensor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Expected shape (batch, n_heads, seq_len, head_dim)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;head_dim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;head_dim&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;head_dim must be power of 2 in [16, 256]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_contiguous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_contiguous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;is_contiguous&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;empty_like&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sm_scale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;head_dim&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_batch_heads&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n_heads&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;# 1-D grid: grouped ordering delinearizes inside the kernel&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cdiv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;META&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;BLOCK_M&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;n_batch_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;flash_attention_fwd_kernel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sm_scale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;k&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&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;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;stride&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;seq_len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;n_batch_heads&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;HEAD_DIM&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;head_dim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;IS_CAUSAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;causal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;o&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;get_autotune_config&lt;/code&gt; 定义了多个配置组合，覆盖了不同的序列长度和头维度，以适应各种使用场景。&lt;/li&gt;
&lt;li&gt;Grouped Ordering 仍然适用，确保了在计算过程中对 K/V 块的高效缓存利用。&lt;/li&gt;
&lt;li&gt;Pre-scale Q + exp2 替代了传统的缩放和 Softmax 操作，利用 Online Softmax 算法实现了数值稳定且内存高效的注意力计算。&lt;/li&gt;
&lt;li&gt;Split causal loop：将内层循环拆为两阶段。Phase 1 处理完全在对角线以下的 block，可跳过 causal mask；Phase 2 仅对对角线附近的 1–2 个 block 执行 &lt;code&gt;tl.where&lt;/code&gt; causal mask。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="六benchmark如何测试你的-kernel-性能"&gt;
&lt;a href="#%e5%85%adbenchmark%e5%a6%82%e4%bd%95%e6%b5%8b%e8%af%95%e4%bd%a0%e7%9a%84-kernel-%e6%80%a7%e8%83%bd" class="header-anchor"&gt;#&lt;/a&gt;
六、Benchmark：如何测试你的 Kernel 性能
&lt;/h2&gt;&lt;p&gt;写出正确的 kernel 只是第一步。在 GPU 编程中，性能才是最终的评判标准。Triton 提供了一整套 benchmark 框架。&lt;/p&gt;
&lt;h3 id="61-torchtestingassert_close"&gt;
&lt;a href="#61-torchtestingassert_close" class="header-anchor"&gt;#&lt;/a&gt;
6.1 &lt;code&gt;torch.testing.assert_close&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;数值正确性是性能优化的前提。&lt;code&gt;torch.testing.assert_close&lt;/code&gt; 是一个功能强大的工具，可以比较两个张量是否在指定的绝对误差（atol）和相对误差（rtol）范围内近似相等：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;assert_close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;out&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;atol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rtol&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;1e-2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;不同精度下的容差参考：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;dtype&lt;/th&gt;
&lt;th&gt;atol&lt;/th&gt;
&lt;th&gt;rtol&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;float32&lt;/td&gt;
&lt;td&gt;1e-5&lt;/td&gt;
&lt;td&gt;1e-5&lt;/td&gt;
&lt;td&gt;最严格&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float16&lt;/td&gt;
&lt;td&gt;1e-2&lt;/td&gt;
&lt;td&gt;1e-2&lt;/td&gt;
&lt;td&gt;半精度累积误差较大&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bfloat16&lt;/td&gt;
&lt;td&gt;1e-2&lt;/td&gt;
&lt;td&gt;1e-2&lt;/td&gt;
&lt;td&gt;尾数更短，精度更低&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float8&lt;/td&gt;
&lt;td&gt;1e-1&lt;/td&gt;
&lt;td&gt;1e-1&lt;/td&gt;
&lt;td&gt;极低精度，容差必须宽松&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="62-tritontestingdo_bench"&gt;
&lt;a href="#62-tritontestingdo_bench" class="header-anchor"&gt;#&lt;/a&gt;
6.2 &lt;code&gt;triton.testing.do_bench&lt;/code&gt;
&lt;/h3&gt;&lt;h4 id="计时"&gt;
&lt;a href="#%e8%ae%a1%e6%97%b6" class="header-anchor"&gt;#&lt;/a&gt;
计时
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_bench&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;my_kernel&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="o"&gt;...&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;warmup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# 预热次数（排除 JIT 编译和缓存冷启动的影响）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;rep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;# 测量次数&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;quantiles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;# 返回中位数、20th、80th 分位数&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Median: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;.3f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ms [p20=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;min_ms&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;.3f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;, p80=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;max_ms&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;.3f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;]&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;示例：测量 softmax kernel 的延迟：&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_bench&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;softmax&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; &lt;span class="n"&gt;warmup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Softmax latency: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;.3f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ms&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;预热（warmup）很重要：第一次调用会触发 JIT 编译，耗时可能是实际执行时间的数百倍。&lt;code&gt;do_bench&lt;/code&gt; 会先运行 warmup 轮丢弃结果，然后才开始正式计时。&lt;/p&gt;
&lt;h4 id="flops-吞吐量"&gt;
&lt;a href="#flops-%e5%90%9e%e5%90%90%e9%87%8f" class="header-anchor"&gt;#&lt;/a&gt;
FLOPS 吞吐量
&lt;/h4&gt;&lt;p&gt;FLOPS（Floating-point Operations Per Second，每秒浮点运算次数）是衡量 compute-bound kernel 性能的关键指标。计算这个指标前需要知道整个算法总共需要多少次运算。理论运算量 (FLOPs) 是算法本身所需的浮点运算总数，与具体的硬件并行度无关。其中常见的 &lt;code&gt;add&lt;/code&gt;、&lt;code&gt;mul&lt;/code&gt;、&lt;code&gt;sub&lt;/code&gt; 都是 1 FLOP，&lt;code&gt;fma&lt;/code&gt; 是 2 FLOP。特殊的内置函数（如 &lt;code&gt;sin&lt;/code&gt;, &lt;code&gt;exp&lt;/code&gt;）属于 SFU (Special Function Unit) 处理，其算力换算在不同架构下不同，但在标准 FLOPS 计算中，通常只统计基础的乘加运算。&lt;/p&gt;
&lt;p&gt;例子：一个简单的向量加法 &lt;code&gt;C[i] = A[i] + B[i]&lt;/code&gt;，若总长度为 N，则总运算量为 N 个 FLOPs。若是一个矩阵乘法 &lt;code&gt;C = A @ B&lt;/code&gt;，其中 A 是 MxK，B 是 KxN，则总运算量为 2 * M * N * K FLOPs 。&lt;/p&gt;
&lt;p&gt;进一步地，可以计算 Kernel 的实测性能 FLOPS = FLOPs / 执行时间（秒）。例如 GEMM Kernel ：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;flops&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="n"&gt;M&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;K&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tflops&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;flops&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="带宽利用率-gbps"&gt;
&lt;a href="#%e5%b8%a6%e5%ae%bd%e5%88%a9%e7%94%a8%e7%8e%87-gbps" class="header-anchor"&gt;#&lt;/a&gt;
带宽利用率 GBPS
&lt;/h4&gt;&lt;p&gt;对于 memory-bound kernel，带宽利用率是更合适的性能指标。计算方法是：带宽 (GB/s) = 传输的数据量 (GB) / 执行时间 (秒)。数据量包括所有从内存读取和写入的字节数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;read_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;K&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;write_bytes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;M&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="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;gbps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read_bytes&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;write_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;1e9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;hw_bw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3350&lt;/span&gt; &lt;span class="c1"&gt;# H100 HBM Bandwidth in GB/s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;utilization&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gbps&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;hw_bw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="roofline-模型"&gt;
&lt;a href="#roofline-%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;#&lt;/a&gt;
Roofline 模型
&lt;/h4&gt;&lt;p&gt;Roofline 模型是判断 kernel 是 compute-bound 还是 memory-bound 的经典工具。核心概念是算术强度（Arithmetic Intensity, AI）= 计算量 / 数据传输量。对于 H100，拐点大约在 295 FLOP/Byte：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI &amp;lt; 295：memory-bound，优化方向是减少内存访问、提高带宽利用率&lt;/li&gt;
&lt;li&gt;AI &amp;gt; 295：compute-bound，优化方向是提高 Tensor Core 利用率&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;arithmetic_intensity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;flops&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;read_bytes&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;write_bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# FLOP/Byte&lt;/span&gt;
&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="n"&gt;arithmetic_intensity&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;295&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Memory-bound kernel&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Compute-bound kernel&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="63-tritontestingperf_report"&gt;
&lt;a href="#63-tritontestingperf_report" class="header-anchor"&gt;#&lt;/a&gt;
6.3 &lt;code&gt;@triton.testing.perf_report&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;@triton.testing.perf_report&lt;/code&gt; 是一个装饰器，配合 &lt;code&gt;triton.testing.Benchmark&lt;/code&gt; 使用，用于自动化多配置基准测试并生成图表。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="nd"&gt;@triton.testing.perf_report&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Benchmark&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x_names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;N&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x_vals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;128&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;line_arg&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;provider&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;line_vals&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;triton&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;torch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;line_names&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Triton&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;PyTorch&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;styles&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;blue&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;red&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;-&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ylabel&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;GB/s&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;plot_name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;softmax-performance&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;M&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bench_softmax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&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;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;randn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;cuda&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;float16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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="n"&gt;provider&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;triton&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;softmax&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;lambda&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;softmax&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; &lt;span class="n"&gt;dim&lt;/span&gt;&lt;span class="o"&gt;=-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;triton&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;do_bench&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;warmup&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;gbps&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="n"&gt;M&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;x&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;element_size&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1e-9&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1e-3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;gbps&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bench_softmax&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;show_plots&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;print_data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;bench_softmax&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;save_path&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./benchmarks/&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;triton.testing.Benchmark&lt;/code&gt; 参数说明:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;参数&lt;/th&gt;
&lt;th&gt;类型&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;x_names&lt;/td&gt;
&lt;td&gt;List[str]&lt;/td&gt;
&lt;td&gt;x 轴参数名称列表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;x_vals&lt;/td&gt;
&lt;td&gt;List[List]&lt;/td&gt;
&lt;td&gt;每个 x 轴参数的取值列表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;line_arg&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;用于区分不同曲线的参数名称&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;line_vals&lt;/td&gt;
&lt;td&gt;List[Any]&lt;/td&gt;
&lt;td&gt;不同曲线对应的参数取值列表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;line_names&lt;/td&gt;
&lt;td&gt;List[str]&lt;/td&gt;
&lt;td&gt;曲线名称列表（用于图例）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;styles&lt;/td&gt;
&lt;td&gt;List[Tuple]&lt;/td&gt;
&lt;td&gt;每条曲线的颜色和线型&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ylabel&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;y 轴标签&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;plot_name&lt;/td&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;生成的图表文件名（不含扩展名）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;args&lt;/td&gt;
&lt;td&gt;Dict[str, Any]&lt;/td&gt;
&lt;td&gt;其他固定参数&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/softmax-performance-20260218-1110z8-8m.webp"
alt="Softmax Performance" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Softmax Performance&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="七前沿fp4-与-blackwell-架构"&gt;
&lt;a href="#%e4%b8%83%e5%89%8d%e6%b2%bffp4-%e4%b8%8e-blackwell-%e6%9e%b6%e6%9e%84" class="header-anchor"&gt;#&lt;/a&gt;
七、前沿：FP4 与 Blackwell 架构
&lt;/h2&gt;&lt;h3 id="71-blackwell-架构速览"&gt;
&lt;a href="#71-blackwell-%e6%9e%b6%e6%9e%84%e9%80%9f%e8%a7%88" class="header-anchor"&gt;#&lt;/a&gt;
7.1 Blackwell 架构速览
&lt;/h3&gt;&lt;p&gt;站在 2026 年的时间点，NVIDIA Blackwell（B200/B300）架构已经规模化部署：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;特性&lt;/th&gt;
&lt;th&gt;Hopper (H100)&lt;/th&gt;
&lt;th&gt;Blackwell (B200)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;微架构&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SM90&lt;/td&gt;
&lt;td&gt;SM100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FP4 TOPS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;N/A&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~4500&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;FP8 TOPS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;~1979&lt;/td&gt;
&lt;td&gt;~2250&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;HBM 带宽&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;3.35 TB/s&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~8 TB/s&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tensor Core&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;第 4 代&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;第 5 代&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="72-nvfp4-e2m1-格式"&gt;
&lt;a href="#72-nvfp4-e2m1-%e6%a0%bc%e5%bc%8f" class="header-anchor"&gt;#&lt;/a&gt;
7.2 NVFP4 (E2M1) 格式
&lt;/h3&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/nvfp4-20260218-12v9br-hf.webp"
alt="NVFP4 E2M1 Format" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;NVFP4 E2M1 Format&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;只有 16 个可表示值意味着 FP4 的表达能力极其有限。但配合 per-block scaling，每组 16 个 FP4 值共享一个 FP8 的缩放因子，就可以覆盖更大的数值范围。这本质上和 DeepGEMM 的 per-128-element FP8 scaling 是同一个思路——用粗粒度的高精度 scale 来弥补细粒度低精度数据的表达能力不足。&lt;/p&gt;
&lt;h3 id="73-对-triton-编程的影响"&gt;
&lt;a href="#73-%e5%af%b9-triton-%e7%bc%96%e7%a8%8b%e7%9a%84%e5%bd%b1%e5%93%8d" class="header-anchor"&gt;#&lt;/a&gt;
7.3 对 Triton 编程的影响
&lt;/h3&gt;&lt;p&gt;随着 Triton 对 SM100 支持的完善：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;指令进化&lt;/strong&gt;：&lt;code&gt;tl.dot&lt;/code&gt; 将原生支持 &lt;code&gt;FP4 × FP4 -&amp;gt; FP32&lt;/code&gt;，背后映射至第五代 Tensor Core &lt;code&gt;tcgen05&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TMA 大满贯&lt;/strong&gt;：Hopper 时代 TMA 主要负责 Load，而 Blackwell 支持更强大的 Store 方向 TMA 及超大范围的 Multicast（多播）。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;更深的流水线&lt;/strong&gt;：得益于 256KB+ 的 Shared Memory，&lt;code&gt;num_stages=5&lt;/code&gt; 甚至 &lt;code&gt;6&lt;/code&gt; 成为常态，内存延迟将被完美隐藏。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="后续"&gt;
&lt;a href="#%e5%90%8e%e7%bb%ad" class="header-anchor"&gt;#&lt;/a&gt;
后续
&lt;/h2&gt;&lt;p&gt;Triton 是目前最成熟的 tile-based GPU DSL，但并非唯一选择。Tilelang 走了一条截然不同的路——更显式的内存层级控制、更灵活的布局变换抽象。接下来会将讲一下 Tilelang 的编程模型，并且与 Triton 进行对比。&lt;/p&gt;</description></item><item><title>Open WebUI 集成 MCP：MCPO 与 Claw Cloud 部署</title><link>https://cuterwrite.top/p/openwebui-mcpo/</link><pubDate>Tue, 15 Jul 2025 08:00:00 +0000</pubDate><guid>https://cuterwrite.top/p/openwebui-mcpo/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/ComfyUI_00381__hu30becd06249f386968aef4e18696b029_1596713_filter_10933573887768330671-20250715-128ivv-68.webp" alt="Featured image of post Open WebUI 集成 MCP：MCPO 与 Claw Cloud 部署" /&gt;&lt;p&gt;在 AI 应用开发领域，模型与工具的无缝集成一直是提升生产力的关键。Open WebUI 作为一款功能丰富的开源界面框架，为大模型提供了直观的交互方式。然而，要充分发挥大模型工具调用能力，我们需要将其与主流的 MCP (Model Context Protocol) 协议集成。本文将详细介绍如何通过 &lt;a class="link" href="https://github.com/open-webui/mcpo" target="_blank" rel="noopener" &gt;MCPO
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
实现这一集成，并利用 Claw Cloud Run 的免费容器资源实现零成本部署 MCPO 。&lt;/p&gt;
&lt;h2 id="架构概览"&gt;
&lt;a href="#%e6%9e%b6%e6%9e%84%e6%a6%82%e8%a7%88" class="header-anchor"&gt;#&lt;/a&gt;
架构概览
&lt;/h2&gt;&lt;p&gt;在深入实施之前，可以先大概了解一下 Open WebUI 与 MCP 的集成架构。以下是一个简化的架构图，展示了 Open WebUI、MCPO 以及 MCP 服务器之间的关系：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ Open WebUI │───▶│ MCPO │───▶│ MCP Servers │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;│ (Web Client) │ │ (Proxy Layer) │ │ (Tools &amp;amp; Data) │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;└─────────────────┘ └─────────────────┘ └─────────────────┘
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ │ │
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; User Interface Protocol Bridge External APIs
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Chat Interface - MCP &amp;lt;-&amp;gt; OpenAPI - Memory Service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Tool Management - Authentication - Time Service
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - Model Controls - Request Routing - File System
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; - API Documentation - Database
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="mcp-协议概述"&gt;
&lt;a href="#mcp-%e5%8d%8f%e8%ae%ae%e6%a6%82%e8%bf%b0" class="header-anchor"&gt;#&lt;/a&gt;
MCP 协议概述
&lt;/h2&gt;&lt;p&gt;Model Context Protocol（MCP）是由 Anthropic 在 2024 年 11 月推出的开放标准，旨在为 AI 应用程序与外部数据源、工具系统之间建立安全、双向的连接。MCP 解决了 AI 模型长期面临的数据孤岛问题，即使是最先进的模型也往往被困在信息孤岛中，无法有效访问外部系统和实时数据。&lt;/p&gt;
&lt;h3 id="核心架构"&gt;
&lt;a href="#%e6%a0%b8%e5%bf%83%e6%9e%b6%e6%9e%84" class="header-anchor"&gt;#&lt;/a&gt;
核心架构
&lt;/h3&gt;&lt;p&gt;MCP 采用客户端-服务器架构，基于 JSON-RPC 2.0 协议构建，提供了一个有状态的会话协议。整个生态系统包含三个核心组件：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MCP 客户端（MCP Clients）&lt;/strong&gt;：希望访问外部系统的 AI 应用程序或代理，如 Claude Desktop、IDE 插件等&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP 服务器（MCP Servers）&lt;/strong&gt;：作为 MCP 世界与具体外部系统之间的桥梁，将外部功能按照 MCP 规范进行封装&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MCP 主机（MCP Hosts）&lt;/strong&gt;：充当多个客户端实例的&amp;quot;容器&amp;quot;或协调器，管理生命周期和安全策略&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/MCP-20250715-12sttf-26.webp"
alt="MCP Architecture" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="三大核心原语"&gt;
&lt;a href="#%e4%b8%89%e5%a4%a7%e6%a0%b8%e5%bf%83%e5%8e%9f%e8%af%ad" class="header-anchor"&gt;#&lt;/a&gt;
三大核心原语
&lt;/h3&gt;&lt;p&gt;MCP 通过三种基本构建块为语言模型提供上下文：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;工具（Tools）&lt;/strong&gt;：LLM 可以调用的函数，用于执行特定操作，如天气查询 API&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源（Resources）&lt;/strong&gt;：LLM 可以访问的数据源，类似于 REST API 中的 GET 端点，提供数据但不执行重要计算&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;提示（Prompts）&lt;/strong&gt;：预定义的模板，用于以最优方式使用工具或资源&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="通信方式"&gt;
&lt;a href="#%e9%80%9a%e4%bf%a1%e6%96%b9%e5%bc%8f" class="header-anchor"&gt;#&lt;/a&gt;
通信方式
&lt;/h3&gt;&lt;p&gt;MCP 支持两种主要通信方式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;stdio（标准输入/输出）&lt;/strong&gt;：当客户端和服务器在同一机器上运行时使用，适合本地集成&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;HTTP via SSE（服务器发送事件）&lt;/strong&gt;：客户端通过 HTTP 连接到服务器，适合远程服务集成&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="生态系统发展"&gt;
&lt;a href="#%e7%94%9f%e6%80%81%e7%b3%bb%e7%bb%9f%e5%8f%91%e5%b1%95" class="header-anchor"&gt;#&lt;/a&gt;
生态系统发展
&lt;/h3&gt;&lt;p&gt;自发布以来，MCP 得到了广泛的行业采用：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;官方支持&lt;/strong&gt;：OpenAI、Google DeepMind 等主要 AI 提供商已采用该协议&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;企业集成&lt;/strong&gt;：Block、Apollo、Zed、Replit、Codeium、Sourcegraph 等公司已实现 MCP 支持&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开源生态&lt;/strong&gt;：到 2025 年 2 月，已有超过 1,000 个开源连接器出现&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;服务集成&lt;/strong&gt;：支持 Google Drive、Slack、GitHub、PostgreSQL 等热门企业系统&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="安全性考量"&gt;
&lt;a href="#%e5%ae%89%e5%85%a8%e6%80%a7%e8%80%83%e9%87%8f" class="header-anchor"&gt;#&lt;/a&gt;
安全性考量
&lt;/h3&gt;&lt;p&gt;MCP 在设计时充分考虑了安全性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;OAuth 2.1 认证&lt;/strong&gt;：协议要求对远程 HTTP 服务器实施 OAuth 2.1 框架进行身份验证&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源指示器&lt;/strong&gt;：MCP 客户端需要实现资源指示器（RFC 8707），明确指定访问令牌的预期接收者&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;权限控制&lt;/strong&gt;：支持基于角色的权限管理和用户授权&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MCP 的出现将原本的&amp;quot;N×M 问题&amp;quot;（每个数据源都需要自定义连接器）转换为&amp;quot;M+N 问题&amp;quot;，工具创建者构建 N 个 MCP 服务器，应用程序开发者构建 M 个 MCP 客户端，大大简化了 AI 工具集成的复杂性。&lt;/p&gt;
&lt;h2 id="第一部分mcpo-简介与本地测试"&gt;
&lt;a href="#%e7%ac%ac%e4%b8%80%e9%83%a8%e5%88%86mcpo-%e7%ae%80%e4%bb%8b%e4%b8%8e%e6%9c%ac%e5%9c%b0%e6%b5%8b%e8%af%95" class="header-anchor"&gt;#&lt;/a&gt;
第一部分：MCPO 简介与本地测试
&lt;/h2&gt;&lt;h3 id="11-mcpo-是什么"&gt;
&lt;a href="#11-mcpo-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;#&lt;/a&gt;
1.1 MCPO 是什么？
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://github.com/open-webui/mcpo" target="_blank" rel="noopener" &gt;MCPO
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
是一个轻量级代理服务器，它接收 MCP 服务器命令，并通过标准的 RESTful OpenAPI 使其可访问，因此工具可以“开箱即用”地与期望 OpenAPI 服务器的 LLM agents 和应用程序配合使用。简单来说，它充当 Open WebUI 与 MCP 工具服务器之间的翻译层。通过将 MCP 协议转换为标准的OpenAPI 规范，MCPO 使 MCP 服务能够以 RESTful API 的形式被 Open WebUI 访问。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MCPO 的核心优势在于：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;协议转换：将 MCP 通信转换为 OpenAPI 兼容的HTTP接口&lt;/li&gt;
&lt;li&gt;安全隔离：在浏览器客户端与本地服务之间建立安全边界&lt;/li&gt;
&lt;li&gt;多工具支持：可同时代理多个MCP服务器，实现工具扩展&lt;/li&gt;
&lt;li&gt;自动文档：为每个MCP工具自动生成交互式 OpenAPI 文档&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;快速使用：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;官方最推荐的方式是通过 &lt;a class="link" href="https://github.com/astral-sh/uv" target="_blank" rel="noopener" &gt;uv
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
包管理器进行安装和配置 MCPO ，可以一行启动 MCPO 服务：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;uvx mcpo --port &lt;span class="m"&gt;8000&lt;/span&gt; --api-key &lt;span class="s2"&gt;&amp;#34;top-secret&amp;#34;&lt;/span&gt; -- your_mcp_server_command
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;当然也可以使用 Python + pip 安装：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install mcpo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;mcpo --port &lt;span class="m"&gt;8000&lt;/span&gt; --api-key &lt;span class="s2"&gt;&amp;#34;top-secret&amp;#34;&lt;/span&gt; -- your_mcp_server_command
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="12-本地测试-mcpo"&gt;
&lt;a href="#12-%e6%9c%ac%e5%9c%b0%e6%b5%8b%e8%af%95-mcpo" class="header-anchor"&gt;#&lt;/a&gt;
1.2 本地测试 MCPO
&lt;/h3&gt;&lt;p&gt;在本文中，我们使用 Docker 容器来运行 MCPO 服务，并且基于 &lt;code&gt;config.json&lt;/code&gt; 文件进行 MCP Servers 的配置。&lt;/p&gt;
&lt;h4 id="步骤-1准备配置文件"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-1%e5%87%86%e5%a4%87%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6" class="header-anchor"&gt;#&lt;/a&gt;
步骤 1：准备配置文件
&lt;/h4&gt;&lt;p&gt;首先，创建 &lt;code&gt;config.json&lt;/code&gt; 文件，内容如下（后续只使用 memory 和 time 工具作为测试）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mcpServers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;memory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;npx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;-y&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;@modelcontextprotocol/server-memory&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;command&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;uvx&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;args&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;mcp-server-time&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;--local-timezone=America/New_York&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mcp_sse&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;sse&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Explicitly define type
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://127.0.0.1:8001/sse&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;headers&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;Authorization&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Bearer token&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;X-Custom-Header&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;value&amp;#34;&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;mcp_streamable_http&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;type&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;streamable_http&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;http://127.0.0.1:8002/mcp&amp;#34;&lt;/span&gt;
&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="c1"&gt;// Streamable HTTP MCP Server
&lt;/span&gt;&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中，每个具体的 MCP Server 都有几个可选的字段，最常见的是 command, args, type, url, env 这五个字段。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;command&lt;/code&gt;：指定 MCP Server 的启动命令&lt;/li&gt;
&lt;li&gt;&lt;code&gt;args&lt;/code&gt;：传递给 MCP Server 的参数列表&lt;/li&gt;
&lt;li&gt;&lt;code&gt;type&lt;/code&gt;：指定 MCP Server 的类型 (如 sse, streamable_http 等，默认是 stdio，不用填写)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;url&lt;/code&gt;：如果 MCP Server 是通过 sse 或 streamable http 协议提供服务，则需要指定其 URL&lt;/li&gt;
&lt;li&gt;&lt;code&gt;env&lt;/code&gt;：指定 MCP Server 的环境变量，一般是用户鉴权信息&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="步骤-2创建-docker-compose-文件"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-2%e5%88%9b%e5%bb%ba-docker-compose-%e6%96%87%e4%bb%b6" class="header-anchor"&gt;#&lt;/a&gt;
步骤 2：创建 Docker Compose 文件
&lt;/h4&gt;&lt;p&gt;接着编写对应的 &lt;code&gt;docker-compose.yml&lt;/code&gt; 文件：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-yaml" data-lang="yaml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;services&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;mcpo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;image&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;ghcr.io/open-webui/mcpo:main&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;container_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;mcpo&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;restart&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l"&gt;unless-stopped&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;ports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="s2"&gt;&amp;#34;127.0.0.1:8000:8000&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;volumes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;- &lt;span class="l"&gt;./config.json:/app/config.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;command&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--&lt;span class="l"&gt;config config.json --api-key &amp;#34;Your Key&amp;#34;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="步骤-3启动-mcpo-服务"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-3%e5%90%af%e5%8a%a8-mcpo-%e6%9c%8d%e5%8a%a1" class="header-anchor"&gt;#&lt;/a&gt;
步骤 3：启动 MCPO 服务
&lt;/h4&gt;&lt;p&gt;在当前目录下运行以下命令启动 MCPO 服务：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker compose up -d
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="步骤-4验证服务运行"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-4%e9%aa%8c%e8%af%81%e6%9c%8d%e5%8a%a1%e8%bf%90%e8%a1%8c" class="header-anchor"&gt;#&lt;/a&gt;
步骤 4：验证服务运行
&lt;/h4&gt;&lt;p&gt;运行 CURL 命令测试 MCPO 服务是否正常：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl -X GET &lt;span class="s2"&gt;&amp;#34;http://127.0.0.1:8000/openapi.json&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;正常情况下会返回以下内容：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;openapi&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;3.1.0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;info&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;title&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;MCP OpenAPI Proxy&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;description&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Automatically generated API from MCP Tool Schemas\n\n- **available tools**：\n - [memory](/memory/docs)\n - [time](/time/docs)\n&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;version&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;1.0&amp;#34;&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;到此，本地测试 MCPO 服务已经完成。接下来，本文将介绍如何将其部署到 Claw Cloud Run 并接入 Open WebUI。&lt;/p&gt;
&lt;h2 id="第二部分claw-cloud-run-免费部署-mcpo"&gt;
&lt;a href="#%e7%ac%ac%e4%ba%8c%e9%83%a8%e5%88%86claw-cloud-run-%e5%85%8d%e8%b4%b9%e9%83%a8%e7%bd%b2-mcpo" class="header-anchor"&gt;#&lt;/a&gt;
第二部分：Claw Cloud Run 免费部署 MCPO
&lt;/h2&gt;&lt;h3 id="21-claw-cloud-run-平台介绍"&gt;
&lt;a href="#21-claw-cloud-run-%e5%b9%b3%e5%8f%b0%e4%bb%8b%e7%bb%8d" class="header-anchor"&gt;#&lt;/a&gt;
2.1 Claw Cloud Run 平台介绍
&lt;/h3&gt;&lt;p&gt;&lt;a class="link" href="https://run.claw.cloud" target="_blank" rel="noopener" &gt;Claw Cloud Run
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
是一个专业的容器化应用部署平台，专注于为开发者提供简单、高效的云原生应用部署体验。与传统的云服务相比，Claw Cloud Run 具有以下特点：&lt;/p&gt;
&lt;h4 id="平台特色"&gt;
&lt;a href="#%e5%b9%b3%e5%8f%b0%e7%89%b9%e8%89%b2" class="header-anchor"&gt;#&lt;/a&gt;
平台特色
&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;极简部署&lt;/strong&gt;：支持从 Docker 镜像直接部署，无需复杂的配置&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;弹性扩缩容&lt;/strong&gt;：支持弹性伸缩，选择合适的资源配置&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全球加速&lt;/strong&gt;：具有多个地区节点，提供更快的访问速度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;开发者友好&lt;/strong&gt;：提供直观的 Web 控制台和完整的 API 接口&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="免费额度政策"&gt;
&lt;a href="#%e5%85%8d%e8%b4%b9%e9%a2%9d%e5%ba%a6%e6%94%bf%e7%ad%96" class="header-anchor"&gt;#&lt;/a&gt;
免费额度政策
&lt;/h4&gt;&lt;p&gt;Claw Cloud Run 为注册超过 180 天的 GitHub 用户提供慷慨的免费额度：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;计算资源&lt;/strong&gt;：每月 5 美元的免费额度&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;网络流量&lt;/strong&gt;：包含一定量的出站流量&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;存储空间&lt;/strong&gt;：提供基础的持久化存储&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;域名服务&lt;/strong&gt;：免费的 &lt;code&gt;.clawcloudrun.com&lt;/code&gt; 子域名&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;免费额度足以支撑中小型项目的开发和测试需求。对于生产环境，建议根据实际使用情况升级到付费计划。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4 id="技术架构"&gt;
&lt;a href="#%e6%8a%80%e6%9c%af%e6%9e%b6%e6%9e%84" class="header-anchor"&gt;#&lt;/a&gt;
技术架构
&lt;/h4&gt;&lt;p&gt;Claw Cloud Run 基于 Kubernetes 构建，提供：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多区域部署&lt;/strong&gt;：支持亚太、欧洲、北美等多个区域&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;负载均衡&lt;/strong&gt;：内置智能负载均衡和故障转移&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;监控告警&lt;/strong&gt;：实时监控应用状态和性能指标&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;日志管理&lt;/strong&gt;：集中化的日志收集和分析&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="22-前置准备"&gt;
&lt;a href="#22-%e5%89%8d%e7%bd%ae%e5%87%86%e5%a4%87" class="header-anchor"&gt;#&lt;/a&gt;
2.2 前置准备
&lt;/h3&gt;&lt;p&gt;在开始部署前，请确保已准备好以下账号：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;GitHub 账号&lt;/strong&gt;：注册时间需超过 180 天（用于免费额度验证）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Claw Cloud 账号&lt;/strong&gt;：通过 GitHub 账号授权登录&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;域名&lt;/strong&gt;（可选）：如需自定义域名，请准备好域名和 DNS 管理权限&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="23-创建应用部署"&gt;
&lt;a href="#23-%e5%88%9b%e5%bb%ba%e5%ba%94%e7%94%a8%e9%83%a8%e7%bd%b2" class="header-anchor"&gt;#&lt;/a&gt;
2.3 创建应用部署
&lt;/h3&gt;&lt;h4 id="步骤-1登录控制台并查看免费额度"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-1%e7%99%bb%e5%bd%95%e6%8e%a7%e5%88%b6%e5%8f%b0%e5%b9%b6%e6%9f%a5%e7%9c%8b%e5%85%8d%e8%b4%b9%e9%a2%9d%e5%ba%a6" class="header-anchor"&gt;#&lt;/a&gt;
步骤 1：登录控制台并查看免费额度
&lt;/h4&gt;&lt;p&gt;登录 &lt;a class="link" href="console.run.claw.cloud" &gt;Claw Cloud
&lt;/a&gt;
控制台，选择 Github 登录，点击右上角的 Plan，可以看到有每个月 5$ 的免费额度。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/clawcloudfree-20250715-zgmpg-b2.webp"
alt="claw-cloud-run-free-plan" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h4 id="步骤-2创建应用实例"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-2%e5%88%9b%e5%bb%ba%e5%ba%94%e7%94%a8%e5%ae%9e%e4%be%8b" class="header-anchor"&gt;#&lt;/a&gt;
步骤 2：创建应用实例
&lt;/h4&gt;&lt;p&gt;回到首页，进入 &lt;strong&gt;App Launchpad&lt;/strong&gt;，点击 &lt;strong&gt;Create App&lt;/strong&gt;，填写应用名称（如 mcpo），并完成以下设置：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;应用名称：mcpo&lt;/li&gt;
&lt;li&gt;镜像名称：ghcr.io/open-webui/mcpo:main&lt;/li&gt;
&lt;li&gt;资源大小：0.5vCPU, 1GB 内存&lt;/li&gt;
&lt;li&gt;端口：8000&lt;/li&gt;
&lt;li&gt;开启公网访问：是&lt;/li&gt;
&lt;li&gt;自定义域名：可选，需要配置 CNAME 解析到 Claw Cloud 的域名&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/app-lauchpad-1-20250715-1058p8-rc.webp"
alt="app-lauchpad-setting1" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="24-配置应用参数"&gt;
&lt;a href="#24-%e9%85%8d%e7%bd%ae%e5%ba%94%e7%94%a8%e5%8f%82%e6%95%b0" class="header-anchor"&gt;#&lt;/a&gt;
2.4 配置应用参数
&lt;/h3&gt;&lt;h4 id="步骤-3设置启动命令"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-3%e8%ae%be%e7%bd%ae%e5%90%af%e5%8a%a8%e5%91%bd%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
步骤 3：设置启动命令
&lt;/h4&gt;&lt;p&gt;启动命令设置为 &lt;code&gt;mcpo --config config.json&lt;/code&gt;，设置 API Key 用于访问控制：&lt;/p&gt;
&lt;blockquote class="alert-blockquote alert-important"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;重要&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;为了确保安全性，请使用强密码作为 API Key，并定期轮换。不要在公开代码中暴露实际的 API Key。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/app-launchpad-advance-20250715-10a4q3-uk.webp"
alt="app-lauchpad-advance" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h4 id="步骤-4配置-mcp-servers"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-4%e9%85%8d%e7%bd%ae-mcp-servers" class="header-anchor"&gt;#&lt;/a&gt;
步骤 4：配置 MCP Servers
&lt;/h4&gt;&lt;p&gt;配置 &lt;code&gt;config.json&lt;/code&gt; 文件，在 Configmaps 中新增 &lt;code&gt;/app/config.json&lt;/code&gt; 文件，内容与本地测试时的 &lt;code&gt;config.json&lt;/code&gt; 相同：&lt;/p&gt;
&lt;blockquote class="alert-blockquote alert-warning"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;警告&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;在配置远程 SSE 或 Streamable HTTP 类型的 MCP Servers 时，请确保仅添加可信任的服务器。恶意的 MCP Server 可能会执行不安全的操作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/ConfigMap-20250715-10fjmq-ch.webp"
alt="claw-cloud-run-configmap" width="85%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h4 id="步骤-5配置持久化存储"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-5%e9%85%8d%e7%bd%ae%e6%8c%81%e4%b9%85%e5%8c%96%e5%ad%98%e5%82%a8" class="header-anchor"&gt;#&lt;/a&gt;
步骤 5：配置持久化存储
&lt;/h4&gt;&lt;p&gt;新增本地存储，挂载 &lt;code&gt;/root&lt;/code&gt; 目录，一般来说 5GB 的存储空间足够使用：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/LocalStorage-20250715-10khbw-7e.webp"
alt="claw-cloud-run-local-storage" width="85%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="25-部署应用"&gt;
&lt;a href="#25-%e9%83%a8%e7%bd%b2%e5%ba%94%e7%94%a8" class="header-anchor"&gt;#&lt;/a&gt;
2.5 部署应用
&lt;/h3&gt;&lt;h4 id="步骤-6完成配置并部署"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-6%e5%ae%8c%e6%88%90%e9%85%8d%e7%bd%ae%e5%b9%b6%e9%83%a8%e7%bd%b2" class="header-anchor"&gt;#&lt;/a&gt;
步骤 6：完成配置并部署
&lt;/h4&gt;&lt;p&gt;完成上述配置后如下所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/config_res-20250715-10n0fi-iv.webp"
alt="claw-cloud-run-app" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h4 id="步骤-7部署并验证"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-7%e9%83%a8%e7%bd%b2%e5%b9%b6%e9%aa%8c%e8%af%81" class="header-anchor"&gt;#&lt;/a&gt;
步骤 7：部署并验证
&lt;/h4&gt;&lt;p&gt;接着就可以点击右上角的 &lt;strong&gt;Deploy Application&lt;/strong&gt; 按钮部署 MCPO 服务。显示如下的 running 状态并且通过域名访问 &lt;code&gt;/openapi.json&lt;/code&gt; 有正常响应即表示部署成功：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/Running-20250715-1104xx-r3.webp"
alt="claw-cloud-run-app-running" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h2 id="第三部分在-open-webui-中连接工具服务器"&gt;
&lt;a href="#%e7%ac%ac%e4%b8%89%e9%83%a8%e5%88%86%e5%9c%a8-open-webui-%e4%b8%ad%e8%bf%9e%e6%8e%a5%e5%b7%a5%e5%85%b7%e6%9c%8d%e5%8a%a1%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
第三部分：在 Open WebUI 中连接工具服务器
&lt;/h2&gt;&lt;h3 id="31-连接-mcpo-服务器"&gt;
&lt;a href="#31-%e8%bf%9e%e6%8e%a5-mcpo-%e6%9c%8d%e5%8a%a1%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
3.1 连接 MCPO 服务器
&lt;/h3&gt;&lt;h4 id="步骤-1添加工具服务器"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-1%e6%b7%bb%e5%8a%a0%e5%b7%a5%e5%85%b7%e6%9c%8d%e5%8a%a1%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
步骤 1：添加工具服务器
&lt;/h4&gt;&lt;p&gt;将运行中的 MCPO 服务器连接到 Open WebUI：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;在浏览器中打开 Open WebUI&lt;/li&gt;
&lt;li&gt;打开 ⚙️ 设置&lt;/li&gt;
&lt;li&gt;点击 ➕ 工具，添加新的工具服务器&lt;/li&gt;
&lt;li&gt;输入运行 OpenAPI 工具服务器的 URL（如 Claw Cloud Run 默认的域名: &lt;code&gt;https://xxx.ap-southeast-1.clawcloudrun.com&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;点击 &amp;ldquo;保存&amp;rdquo;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote class="alert-blockquote alert-warning"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;警告&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;在添加工具服务器时，请确保：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;使用 HTTPS 协议确保数据传输安全&lt;/li&gt;
&lt;li&gt;验证服务器 URL 的有效性，避免输入错误的地址&lt;/li&gt;
&lt;li&gt;仅连接到可信任的 MCPO 服务器&lt;/li&gt;
&lt;li&gt;如果服务器需要 API Key 认证，请在相应字段中输入&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/add-connnection-20250715-11aiir-t2.webp"
alt="Open WebUI 添加工具服务器" width="85%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="32-用户工具服务器-vs-全局工具服务器"&gt;
&lt;a href="#32-%e7%94%a8%e6%88%b7%e5%b7%a5%e5%85%b7%e6%9c%8d%e5%8a%a1%e5%99%a8-vs-%e5%85%a8%e5%b1%80%e5%b7%a5%e5%85%b7%e6%9c%8d%e5%8a%a1%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
3.2 用户工具服务器 vs 全局工具服务器
&lt;/h3&gt;&lt;p&gt;如果是管理员，则可以在后台管理员设置 → 工具 → 管理工具服务器中配置全局的工具服务器。至于这两种方式的区别，可以参考官方的说明：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;用户工具服务器和全局工具服务器的主要区别在于，API 连接和请求实际上是在哪里进行的：&lt;/p&gt;
&lt;p&gt;用户工具服务器通过浏览器（客户端）直接向工具服务器发出请求。这意味着可以安全地连接到本地主机 URL，甚至可以暴露私人端点或仅用于开发的端点，连接是私有的。&lt;/p&gt;
&lt;p&gt;全局工具服务器通过 Open WebUI 后端（服务器）进行连接。后端必须能够访问指定的工具服务器 URL，使用此方法可与部署范围内的其他用户共享工具，请求是由后台发出的，无法通过此方法访问个人本地资源，而且需要慎重考虑安全性。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;工具服务器类型&lt;/th&gt;
&lt;th&gt;请求起源&lt;/th&gt;
&lt;th&gt;使用本地主机？&lt;/th&gt;
&lt;th&gt;用例示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;用户工具服务器&lt;/td&gt;
&lt;td&gt;浏览器客户端&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;个人工具、本地开发/测试&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;全局工具服务器&lt;/td&gt;
&lt;td&gt;Open WebUI 后端&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;团队/共享工具、企业集成&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;用户工具服务器适用于个人使用和本地开发测试，可以直接连接到本地主机 URL。而全局工具服务器则适用于生产或共享环境，在这些环境中，每个人都需要访问相同的工具。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="33-使用工具服务器"&gt;
&lt;a href="#33-%e4%bd%bf%e7%94%a8%e5%b7%a5%e5%85%b7%e6%9c%8d%e5%8a%a1%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
3.3 使用工具服务器
&lt;/h3&gt;&lt;h4 id="步骤-2在聊天界面中使用工具"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-2%e5%9c%a8%e8%81%8a%e5%a4%a9%e7%95%8c%e9%9d%a2%e4%b8%ad%e4%bd%bf%e7%94%a8%e5%b7%a5%e5%85%b7" class="header-anchor"&gt;#&lt;/a&gt;
步骤 2：在聊天界面中使用工具
&lt;/h4&gt;&lt;p&gt;完成上述步骤后，将可以在聊天界面中找到工具服务器（输入框的下方）：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/tool-button-20250715-11pjjo-1r.webp"
alt="Open WebUI 工具服务器" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;单击该图标可打开一个弹出窗口，可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查看已连接的工具服务器信息&lt;/li&gt;
&lt;li&gt;查看哪些工具可用以及由哪个服务器提供&lt;/li&gt;
&lt;li&gt;必要时调试或断开任何工具&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;全局工具服务器显示外观有所不同，需要点击消息输入区的 ➕ 按钮才会显示工具信息。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/glocal-tool-button-20250715-11sptb-wn.webp"
alt="Open WebUI 工具服务器信息" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;blockquote class="alert-blockquote alert-important"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;重要&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;在通过 ➕ 菜单启用之前，它们不会显示在工具指示器弹出窗口中。&lt;/p&gt;
&lt;p&gt;每个全局工具都必须单独打开，才能在当前聊天中激活。&lt;/p&gt;
&lt;p&gt;一旦开启，其功能与用户工具相同。&lt;/p&gt;
&lt;p&gt;管理员可以通过基于角色的权限控制对全局工具的访问。&lt;/p&gt;
&lt;p&gt;这非常适合团队设置或共享环境，在这些环境中，常用工具（如文档搜索、网络查询）提供给多个用户集中访问。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="34-启用原生工具模式"&gt;
&lt;a href="#34-%e5%90%af%e7%94%a8%e5%8e%9f%e7%94%9f%e5%b7%a5%e5%85%b7%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;#&lt;/a&gt;
3.4 启用原生工具模式
&lt;/h3&gt;&lt;h4 id="步骤-3配置-react-风格的函数调用"&gt;
&lt;a href="#%e6%ad%a5%e9%aa%a4-3%e9%85%8d%e7%bd%ae-react-%e9%a3%8e%e6%a0%bc%e7%9a%84%e5%87%bd%e6%95%b0%e8%b0%83%e7%94%a8" class="header-anchor"&gt;#&lt;/a&gt;
步骤 3：配置 ReACT 风格的函数调用
&lt;/h4&gt;&lt;p&gt;想在会话中直接启用 ReACT 风格（推理 + 执行）的本地函数调用，则需要在模型设置页面启用原生工具模式：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;进入 ⚙️ Chat Controls（聊天控制）→ Advanced Params（高级参数）&lt;/li&gt;
&lt;li&gt;将函数调用参数从 &lt;code&gt;Default&lt;/code&gt; 改为 &lt;code&gt;Native&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="第四部分常见问题与排查"&gt;
&lt;a href="#%e7%ac%ac%e5%9b%9b%e9%83%a8%e5%88%86%e5%b8%b8%e8%a7%81%e9%97%ae%e9%a2%98%e4%b8%8e%e6%8e%92%e6%9f%a5" class="header-anchor"&gt;#&lt;/a&gt;
第四部分：常见问题与排查
&lt;/h2&gt;&lt;p&gt;以下是一些比较常见的问题及解决方案：&lt;/p&gt;
&lt;h3 id="41-无法连接到-mcpo-服务器"&gt;
&lt;a href="#41-%e6%97%a0%e6%b3%95%e8%bf%9e%e6%8e%a5%e5%88%b0-mcpo-%e6%9c%8d%e5%8a%a1%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
4.1 无法连接到 MCPO 服务器
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;确保 MCPO 服务正在运行，并且端口配置正确。&lt;/li&gt;
&lt;li&gt;检查防火墙设置，确保允许访问指定端口。&lt;/li&gt;
&lt;li&gt;如果使用 Claw Cloud Run，请确保已正确配置域名和端口。&lt;/li&gt;
&lt;li&gt;检查 MCPO 服务的日志，以获取更多错误信息。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="42-工具无法正常工作"&gt;
&lt;a href="#42-%e5%b7%a5%e5%85%b7%e6%97%a0%e6%b3%95%e6%ad%a3%e5%b8%b8%e5%b7%a5%e4%bd%9c" class="header-anchor"&gt;#&lt;/a&gt;
4.2 工具无法正常工作
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;确保 MCP Server 已正确配置，并且 &lt;code&gt;config.json&lt;/code&gt; 文件中的工具配置正确。&lt;/li&gt;
&lt;li&gt;检查 MCPO 的 OpenAPI 文档，确保工具的 API 路径和参数正确。&lt;/li&gt;
&lt;li&gt;如果工具需要特定的权限或 API Key，请确保已正确设置。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="43-工具服务器响应慢"&gt;
&lt;a href="#43-%e5%b7%a5%e5%85%b7%e6%9c%8d%e5%8a%a1%e5%99%a8%e5%93%8d%e5%ba%94%e6%85%a2" class="header-anchor"&gt;#&lt;/a&gt;
4.3 工具服务器响应慢
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;检查 MCPO 服务的资源配置，确保分配了足够的 CPU 和内存。&lt;/li&gt;
&lt;li&gt;如果使用 Claw Cloud Run，请检查当前的免费额度是否已用完。&lt;/li&gt;
&lt;li&gt;确保 MCP Server 的性能良好，必要时可以优化工具的实现。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="44-工具无法在-open-webui-中显示"&gt;
&lt;a href="#44-%e5%b7%a5%e5%85%b7%e6%97%a0%e6%b3%95%e5%9c%a8-open-webui-%e4%b8%ad%e6%98%be%e7%a4%ba" class="header-anchor"&gt;#&lt;/a&gt;
4.4 工具无法在 Open WebUI 中显示
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;确保已正确连接工具服务器，并且工具服务器的 URL 正确。&lt;/li&gt;
&lt;li&gt;检查 Open WebUI 的设置，确保已启用工具服务器。&lt;/li&gt;
&lt;li&gt;如果是全局工具服务器，请确保已在管理员设置中正确配置。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="总结"&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;#&lt;/a&gt;
总结
&lt;/h2&gt;&lt;p&gt;通过 MCPO 将 MCP 能力集成到 Open WebUI，不仅扩展了 AI 助手的功能性，还通过标准化接口简化了工具管理流程。借助 Claw Cloud Run 的免费额度，开发者可以零成本部署 MCPO 服务，实现云端化访问 MCP 工具。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;这种方案的优势在于：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;灵活性&lt;/strong&gt;：支持任意 MCP 兼容工具，只需改写 config.json 就能轻松扩展&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;经济性&lt;/strong&gt;：利用免费容器资源，无需额外的服务器成本&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;安全性&lt;/strong&gt;：通过代理层隔离本地服务与 Web 界面&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可扩展性&lt;/strong&gt;：随业务需求平滑升级资源配置&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote class="alert-blockquote alert-important"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;重要&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;定期关注 Claw Cloud Run 的免费额度政策和 MCPO 项目更新，以获取最新功能和最佳实践。对于生产环境，建议配置监控告警和定期备份，确保服务稳定运行。&lt;/p&gt;
&lt;/blockquote&gt;</description></item><item><title>关于</title><link>https://cuterwrite.top/about/</link><pubDate>Fri, 27 Sep 2024 00:00:00 +0000</pubDate><guid>https://cuterwrite.top/about/</guid><description>&lt;img src="https://cloud.cuterwrite.top/blog/GA11qGVXwAASzAL-2023-12-25.webp" alt="Featured image of post 关于" /&gt;
&lt;link rel="stylesheet" href="https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/aplayer/1.10.1/APlayer.min.css"&gt;
&lt;script src="https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/aplayer/1.10.1/APlayer.min.js" defer&gt;&lt;/script&gt;
&lt;script src="https://mirrors.sustech.edu.cn/cdnjs/ajax/libs/meting/2.0.1/Meting.min.js" defer&gt;&lt;/script&gt;
&lt;meting-js
server="netease"
type="album"
id="263241022"
autoplay="true" loop="true"&gt;
&lt;/meting-js&gt;
&lt;h2 id="cuterwrite-的技术博客"&gt;
&lt;a href="#cuterwrite-%e7%9a%84%e6%8a%80%e6%9c%af%e5%8d%9a%e5%ae%a2" class="header-anchor"&gt;#&lt;/a&gt;
Cuterwrite 的技术博客
&lt;/h2&gt;&lt;p&gt;👀欢迎来到 Cuterwrite 的技术博客！&lt;/p&gt;
&lt;h2 id="-关于我"&gt;
&lt;a href="#-%e5%85%b3%e4%ba%8e%e6%88%91" class="header-anchor"&gt;#&lt;/a&gt;
✋ 关于我
&lt;/h2&gt;&lt;p&gt;我是 Cuterwrite，一名在读博士生，博客专注于以下领域：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;高性能计算&lt;/strong&gt;：这是我的主业，主要研究并行计算、分布式系统和高性能计算架构。我致力于在大规模集群（超算）上进行应用优化，以提升系统的计算效率和性能。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;操作系统&lt;/strong&gt;：主要是 Linux 系统的内核机制和性能优化策略，一些底层细节对于我来说是挺有帮助的。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全栈开发&lt;/strong&gt;：对前端和后端的技术都有涉猎，主要是为了自己的博客和一些 Toy 项目，也会尝试一些新技术，像是前端的 Vue、React，后端的 Golang、Java、Rust 等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;人工智能&lt;/strong&gt;：虽然这不是我的专业研究方向，以前只是接触和上手过，但随着近年来大模型的快速发展，我也对人工智能领域产生了浓厚兴趣。我正在了解如深度学习、自然语言处理等 AI 技术，并基于开源代码和模型进行一些探索实践。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;我希望通过不断地学习，提升自己的技术水平。如果你对我的博客感兴趣，欢迎关注我的动态，也欢迎在评论区留言，我会尽快回复的。&lt;/p&gt;
&lt;h2 id="-关于网站"&gt;
&lt;a href="#-%e5%85%b3%e4%ba%8e%e7%bd%91%e7%ab%99" class="header-anchor"&gt;#&lt;/a&gt;
⌛️ 关于网站
&lt;/h2&gt;&lt;p&gt;&lt;strong&gt;Cuterwrite&amp;rsquo;s Blog&lt;/strong&gt; 搭建于 2021 年，刚开始只是本科期间的一些技术笔记和学习心得，后来逐渐发展成了一个技术博客。网站采用 &lt;a class="link" href="https://gohugo.io/" target="_blank" rel="noopener" &gt;Hugo
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
，托管于 &lt;a class="link" href="https://vercel.com/" target="_blank" rel="noopener" &gt;Vercel
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
，并绑定域名 cuterwrite.top。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;评论系统：使用的是 &lt;a class="link" href="https://twikoo.js.org/" target="_blank" rel="noopener" &gt;Twikoo
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
，数据托管在免费的 &lt;a class="link" href="https://cloud.mongodb.com/" target="_blank" rel="noopener" &gt;MongoDB Atlas
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
上。&lt;/li&gt;
&lt;li&gt;网站统计分析：使用的是 &lt;a class="link" href="https://umami.is/" target="_blank" rel="noopener" &gt;Umami
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
，数据托管在免费的 &lt;a class="link" href="https://neon.dev/" target="_blank" rel="noopener" &gt;Neon
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的 PostgreSQL 服务上。&lt;/li&gt;
&lt;li&gt;搜索功能：使用的是自建的 &lt;a class="link" href="https://www.meilisearch.com/" target="_blank" rel="noopener" &gt;MeiliSearch
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
服务。&lt;/li&gt;
&lt;li&gt;至于左边的画板和画册：分别基于开源项目 &lt;a class="link" href="https://github.com/nicokaiser/hugo-theme-gallery" target="_blank" rel="noopener" &gt;hugo-theme-gallery
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
和 &lt;a class="link" href="https://github.com/korbinzhao/excalidraw-cn" target="_blank" rel="noopener" &gt;excalidraw-cn
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
搭建的。&lt;/li&gt;
&lt;li&gt;网站 CDN：目前不使用 CDN ，使用 Vercel 优选域名加速。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Cuterwrite&amp;rsquo;s Blog&lt;/strong&gt; 也一直在努力提升用户体验。因此，我时不时就对版面进行优化，添加新功能，力求让每一位访问者都能有良好的阅读体验。&lt;/p&gt;
&lt;h2 id="-关于封面"&gt;
&lt;a href="#-%e5%85%b3%e4%ba%8e%e5%b0%81%e9%9d%a2" class="header-anchor"&gt;#&lt;/a&gt;
🎨 关于封面
&lt;/h2&gt;&lt;p&gt;我最喜欢的乐队：&lt;a class="link" href="https://www.oneokrock.com/" target="_blank" rel="noopener" &gt;One OK Rock
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
，一个来自日本的摇滚乐队，这张封面是 2023 年 12 月 8 日在香港亚洲博览馆举办的演唱会的现场照片，我也是在那天第一次去到他们的现场，感觉非常震撼，所以就用这张照片作为了个人页的封面。&lt;/p&gt;
&lt;h2 id="-如何联系"&gt;
&lt;a href="#-%e5%a6%82%e4%bd%95%e8%81%94%e7%b3%bb" class="header-anchor"&gt;#&lt;/a&gt;
🌐 如何联系
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://github.com/PKUcoldkeyboard" target="_blank" rel="noopener" &gt;Github
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
：关注我的项目和动态。（目前还没什么新项目）&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.zhihu.com/people/kong-tiao-cheng-tai-lang-30-57" target="_blank" rel="noopener" &gt;知乎主页
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
：我一般当检索引擎和收藏夹用，不怎么回答问题，私信也不怎么看，当然现在流量多了可能会看一下。&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://telegram.me/cuterwrite" target="_blank" rel="noopener" &gt;Telegram
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
：偶尔会上线看看。&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://linux.do" target="_blank" rel="noopener" &gt;Linux Do
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
：可以在论坛联系我，用户名为 cuterwrite。&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>实现本地 RAG 服务：整合 Open WebUI、Ollama 和 Qwen2.5</title><link>https://cuterwrite.top/p/integrate-open-webui-ollama-qwen25-local-rag/</link><pubDate>Fri, 20 Sep 2024 22:44:00 +0000</pubDate><guid>https://cuterwrite.top/p/integrate-open-webui-ollama-qwen25-local-rag/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/2024-06-29_116903285_p0_master1200.webp" alt="Featured image of post 实现本地 RAG 服务：整合 Open WebUI、Ollama 和 Qwen2.5" /&gt;&lt;h2 id="引言"&gt;
&lt;a href="#%e5%bc%95%e8%a8%80" class="header-anchor"&gt;#&lt;/a&gt;
引言
&lt;/h2&gt;&lt;p&gt;在构建信息检索和生成式 AI 应用时，Retrieval-Augmented Generation (RAG) 模型凭借其能够从知识库中检索相关信息并生成准确答案的强大能力，受到越来越多开发者的青睐。然而，实现端到端的本地 RAG 服务，需求的不只是合适的模型，还需要集成强大的用户界面和高效的推理框架。&lt;/p&gt;
&lt;p&gt;在构建本地 RAG 服务时，利用易于部署的 Docker 方式，可以极大简化模型管理和服务集成。这里我们依赖 Open WebUI 提供的用户界面与模型推理服务，再通过 Ollama 来引入 &lt;code&gt;bge-m3&lt;/code&gt; embedding 模型以实现文档向量化方式的检索功能，从而帮助 Qwen2.5 完成更精准的答案生成。&lt;/p&gt;
&lt;p&gt;本文我们将讨论如何通过 Docker 快速启动 Open WebUI，同步 Ollama 的 RAG 能力，并结合 Qwen2.5 模型实现高效的文档检索与生成系统。&lt;/p&gt;
&lt;h2 id="项目概览"&gt;
&lt;a href="#%e9%a1%b9%e7%9b%ae%e6%a6%82%e8%a7%88" class="header-anchor"&gt;#&lt;/a&gt;
项目概览
&lt;/h2&gt;&lt;p&gt;该项目将使用以下关键工具：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Open WebUI&lt;/strong&gt; : 提供用户与模型交互的 web 界面。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Ollama&lt;/strong&gt; : 用于管理 embedding 和大语言模型的模型推理任务。其中 Ollama 中的 &lt;code&gt;bge-m3&lt;/code&gt; 模型将用于文档检索，Qwen2.5 将负责回答生成。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Qwen2.5&lt;/strong&gt; : 模型部分使用阿里推出的 Qwen 2.5 系列，为检索增强生成服务提供自然语言生成。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;为了实现 RAG 服务，我们需要以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;部署 Open WebUI 作为用户交互界面。&lt;/li&gt;
&lt;li&gt;配置 Ollama 以高效调度 Qwen2.5 系列模型。&lt;/li&gt;
&lt;li&gt;使用 Ollama 配置的名为 &lt;code&gt;bge-m3&lt;/code&gt; 的 embedding 模型实现检索向量化处理。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="部署-open-webui"&gt;
&lt;a href="#%e9%83%a8%e7%bd%b2-open-webui" class="header-anchor"&gt;#&lt;/a&gt;
部署 Open WebUI
&lt;/h2&gt;&lt;p&gt;Open WebUI 提供了一个简洁的 Docker 化解决方案，用户无需手动配置大量依赖，直接通过 Docker 启动 Web 界面。&lt;/p&gt;
&lt;p&gt;首先，服务器上需要确保已经安装了 &lt;a class="link" href="https://docs.docker.com/get-docker/" target="_blank" rel="noopener" &gt;Docker
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
，如果没有安装，可以通过以下命令进行快速安装：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;curl https://get.docker.com &lt;span class="p"&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后创建一个目录用于保存 Open WebUI 的数据，这样数据不会在项目更新后丢失：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sudo mkdir -p /DATA/open-webui
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;接下来，我们可以通过以下命令来启动 Open WebUI ：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -d -p 3000:8080 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --add-host&lt;span class="o"&gt;=&lt;/span&gt;host.docker.internal:host-gateway &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /DATA/open-webui:/app/backend/data &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name open-webui &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --restart always &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ghcr.io/open-webui/open-webui:main
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果想要运行支持 Nvidia GPU 的 Open WebUI ，可以使用以下命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;docker run -d -p 3000:8080 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --gpus all &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --add-host&lt;span class="o"&gt;=&lt;/span&gt;host.docker.internal:host-gateway &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -v /DATA/open-webui:/app/backend/data &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --name open-webui &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --restart always &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ghcr.io/open-webui/open-webui:cuda
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里我们将 Open WebUI 的服务暴露在机器的 3000 端口，可以通过浏览器访问 &lt;code&gt;http://localhost:3000&lt;/code&gt; 即可使用（远程访问则使用公网 ip ，开放 3000 端口）。/DATA/open-webui 是数据存储目录，你可以根据需要调整这个路径。&lt;/p&gt;
&lt;p&gt;当然除了 Docker 安装方式外，你也可以通过 pip 、源码编译、Podman 等方式安装 Open WebUI 。更多安装方式请参考 &lt;a class="link" href="https://docs.openwebui.com/getting-started" target="_blank" rel="noopener" &gt;Open WebUI 官方文档
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
。&lt;/p&gt;
&lt;h3 id="基础设置"&gt;
&lt;a href="#%e5%9f%ba%e7%a1%80%e8%ae%be%e7%bd%ae" class="header-anchor"&gt;#&lt;/a&gt;
基础设置
&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;输入要注册的账号信息，&lt;strong&gt;设置强密码！！！&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote class="alert-blockquote alert-important"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v9.5A1.75 1.75 0 0 1 14.25 13H8.06l-2.573 2.573A1.458 1.458 0 0 1 3 14.543V13H1.75A1.75 1.75 0 0 1 0 11.25Zm1.75-.25a.25.25 0 0 0-.25.25v9.5c0 .138.112.25.25.25h2a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h6.5a.25.25 0 0 0 .25-.25v-9.5a.25.25 0 0 0-.25-.25Zm7 2.25v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 9a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;重要&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;第一个注册的用户将被自动设置为系统管理员，所以请确保你是第一个注册的用户。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start="2"&gt;
&lt;li&gt;点击左下角头像，选择管理员面板&lt;/li&gt;
&lt;li&gt;点击面板中的设置&lt;/li&gt;
&lt;li&gt;关闭允许新用户注册（可选）&lt;/li&gt;
&lt;li&gt;点击右下角保存&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-09-21_openwebui_admin.webp"
alt="Open WebUI" width="85%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h2 id="配置-ollama-和-qwen25"&gt;
&lt;a href="#%e9%85%8d%e7%bd%ae-ollama-%e5%92%8c-qwen25" class="header-anchor"&gt;#&lt;/a&gt;
配置 Ollama 和 Qwen2.5
&lt;/h2&gt;&lt;h3 id="部署-ollama"&gt;
&lt;a href="#%e9%83%a8%e7%bd%b2-ollama" class="header-anchor"&gt;#&lt;/a&gt;
部署 Ollama
&lt;/h3&gt;&lt;p&gt;在本地服务器上安装 Ollama。目前 Ollama 提供多种安装方式，请参考 Ollama 的&lt;a class="link" href="https://ollama.com/" target="_blank" rel="noopener" &gt;官方文档
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
下载安装最新的 &lt;code&gt;0.3.11&lt;/code&gt; 版本（Qwen2.5 在该版本才开始支持）。安装细节可以参考我之前写的一篇文章：&lt;a class="link" href="https://cuterwrite.top/p/ollama/" &gt;Ollama：从入门到进阶
&lt;/a&gt;
。&lt;/p&gt;
&lt;p&gt;启动 Ollama 服务（如果是 Docker 方式启动则不需要，但必须暴露 11434 端口）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama serve
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Ollama 服务启动后，可以通过访问地址 &lt;code&gt;http://localhost:11434&lt;/code&gt; 连接到 Ollama 服务。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://ollama.com/library" target="_blank" rel="noopener" &gt;Ollama Library
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
提供了语义向量模型 ( &lt;code&gt;bge-m3&lt;/code&gt; ) 以及各大文本生成模型（包括 Qwen2.5）。下一步我们将配置 Ollama 以适应本项目对文档检索和问答生成的需求。&lt;/p&gt;
&lt;h3 id="下载-qwen25-模型"&gt;
&lt;a href="#%e4%b8%8b%e8%bd%bd-qwen25-%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;#&lt;/a&gt;
下载 Qwen2.5 模型
&lt;/h3&gt;&lt;p&gt;通过 Ollama 安装 Qwen2.5，你可以直接在命令行中运行 &lt;code&gt;ollama pull&lt;/code&gt; 命令来下载 Qwen2.5 模型，比如要下载 Qwen2.5 的 72B 模型，可以使用以下命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama pull qwen2.5:72b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;该命令将从 Ollama 的模型仓库抓取 Qwen2.5 模型，并准备运行环境。&lt;/p&gt;
&lt;p&gt;Qwen2.5 提供了多种模型尺寸，包括 72B、32B、14B、7B、3B、1.5B、0.5B 等，你可以根据自己的需求和 GPU 显存大小选择合适的模型。我采用的是 4x V100 的服务器，所以可以直接选择 72B 模型。如果要求吐字速度快且能接收微小的性能损失的话，可以使用 &lt;code&gt;q4_0&lt;/code&gt; 量化版本 &lt;code&gt;qwen2.5:72b-instruct-q4_0&lt;/code&gt; ；如果能接受吐字速度慢一些，可以使用 &lt;code&gt;qwen2.5:72b-instruct-q5_K_M&lt;/code&gt; 。对于 4x V100 的服务器，虽然 &lt;code&gt;q5_K_M&lt;/code&gt; 模型的 token 生成明显卡顿，但是为了试验一下 Qwen2.5 的性能，我还是选择了 &lt;code&gt;q5_K_M&lt;/code&gt; 模型。&lt;/p&gt;
&lt;p&gt;对于显存较少的个人电脑，推荐使用 14B 或 7B 模型，通过以下命令下载：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama pull qwen2.5:14b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama pull qwen2.5:7b
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你同时启动好了 Open WebUI 和 Ollama 服务，那么也可以在管理员面板中下载模型。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-09-21_download_qwen2-5-7b.webp"
alt="Download Ollama Model in Open WebUI" width="85%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="下载-bge-m3-模型"&gt;
&lt;a href="#%e4%b8%8b%e8%bd%bd-bge-m3-%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;#&lt;/a&gt;
下载 bge-m3 模型
&lt;/h3&gt;&lt;p&gt;在 Ollama 中下载 &lt;code&gt;bge-m3&lt;/code&gt; 模型，该模型用于文档向量化处理。在命令行中运行以下命令下载模型（或者在 Open WebUI 界面下载）：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ollama pull bge-m3:latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;到这里，我们已经完成了 Ollama 的配置，接下来我们将在 Open WebUI 中配置 RAG 服务。&lt;/p&gt;
&lt;h2 id="rag-集成与配置"&gt;
&lt;a href="#rag-%e9%9b%86%e6%88%90%e4%b8%8e%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;#&lt;/a&gt;
RAG 集成与配置
&lt;/h2&gt;&lt;h3 id="在-open-webui-中配置-ollama-的-rag-接口"&gt;
&lt;a href="#%e5%9c%a8-open-webui-%e4%b8%ad%e9%85%8d%e7%bd%ae-ollama-%e7%9a%84-rag-%e6%8e%a5%e5%8f%a3" class="header-anchor"&gt;#&lt;/a&gt;
在 Open WebUI 中配置 Ollama 的 RAG 接口
&lt;/h3&gt;&lt;h4 id="访问-open-webui-管理界面"&gt;
&lt;a href="#%e8%ae%bf%e9%97%ae-open-webui-%e7%ae%a1%e7%90%86%e7%95%8c%e9%9d%a2" class="header-anchor"&gt;#&lt;/a&gt;
访问 Open WebUI 管理界面
&lt;/h4&gt;&lt;p&gt;启动 Open WebUI 之后，你可以直接通过 Web 浏览器访问服务地址，登录你的管理员账户，然后进入管理员面板。&lt;/p&gt;
&lt;h4 id="设置-ollama-接口"&gt;
&lt;a href="#%e8%ae%be%e7%bd%ae-ollama-%e6%8e%a5%e5%8f%a3" class="header-anchor"&gt;#&lt;/a&gt;
设置 Ollama 接口
&lt;/h4&gt;&lt;p&gt;在 Open WebUI 的管理员面板中，点击&lt;strong&gt;设置&lt;/strong&gt;，你会看到外部连接的选项，确保 Ollama API 的地址为 &lt;code&gt;host.docker.internal:11434&lt;/code&gt; ，然后点击右边的 &lt;strong&gt;verify connection&lt;/strong&gt; 按钮确认 Ollama 服务是否正常连接。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-09-21_ollama_api.webp"
alt="Open WebUI Ollama Setting" width="85%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h4 id="设置语义向量模型"&gt;
&lt;a href="#%e8%ae%be%e7%bd%ae%e8%af%ad%e4%b9%89%e5%90%91%e9%87%8f%e6%a8%a1%e5%9e%8b" class="header-anchor"&gt;#&lt;/a&gt;
设置语义向量模型
&lt;/h4&gt;&lt;p&gt;在 Open WebUI 的管理员面板中，点击&lt;strong&gt;设置&lt;/strong&gt;，接着点击&lt;strong&gt;文档&lt;/strong&gt;，依次完成以下步骤：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;设置语义向量模型引擎为 Ollama 。&lt;/li&gt;
&lt;li&gt;设置语义向量模型为 &lt;code&gt;bge-m3:latest&lt;/code&gt; 。&lt;/li&gt;
&lt;li&gt;其余设置可以保持默认，这里我设置了文件最大上传大小为 10MB，最大上传数量为 3，Top K 设置为 5，块大小和块重叠分别设置为 1500 和 100 ，并开启 PDF 图像处理。&lt;/li&gt;
&lt;li&gt;点击右下角保存。&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-09-21_openwebui_embedding.webp"
alt="Open WebUI Embedding Setting" width="85%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="测试-rag-服务"&gt;
&lt;a href="#%e6%b5%8b%e8%af%95-rag-%e6%9c%8d%e5%8a%a1" class="header-anchor"&gt;#&lt;/a&gt;
测试 RAG 服务
&lt;/h3&gt;&lt;p&gt;现在，你已经实现了完整的本地 RAG 系统。你可以在 Open WebUI 的主界面中输入任意自然语言问题，然后上传响应文档，系统会调用语义向量模型向量化文档，再使用 Qwen2.5 模型检索文档生成答案并返回给用户。&lt;/p&gt;
&lt;p&gt;在 Open WebUI 的用户聊天界面，上传你要检索的文档，然后输入你的问题，点击发送，Open WebUI 将会调用 Ollama 的 &lt;code&gt;bge-m3&lt;/code&gt; 模型进行文档向量化处理，然后调用 Qwen2.5 模型进行问答生成。&lt;/p&gt;
&lt;p&gt;这里我上传了一个简单的 &lt;code&gt;txt&lt;/code&gt; 文件（由 GPT 生成的文本），内容如下：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&lt;/span&gt;&lt;span class="lnt"&gt;31
&lt;/span&gt;&lt;span class="lnt"&gt;32
&lt;/span&gt;&lt;span class="lnt"&gt;33
&lt;/span&gt;&lt;span class="lnt"&gt;34
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-md" data-lang="md"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gh"&gt;# 奇幻森林的冒险
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## 引言
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;在一个遥远的王国边界，有一片神秘的奇幻森林，传说中栖息着许多奇异的生物和古老的魔法。很少有人敢于进入，因为进入森林的人都没有再回来过。故事的主人公是一个年轻的冒险者，他名叫艾文。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## 第一章：艾文的决定
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;艾文是一个热爱冒险和探索的年轻人，他从小就听过很多关于奇幻森林的故事。尽管家人和朋友都劝他不要去，但他坚定地认为，自己注定要揭开这片森林的秘密。一天清晨，他收拾好行囊，带着勇气和好奇心，向森林进发。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### 1.1 出发前的准备
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;在出发前，艾文去了城里最有名的图书馆，查阅了关于奇幻森林的资料。他发现，有一本古老的手稿记录了进入森林的路线，以及如何避开其中一些危险的生物。艾文将这本手稿复印在自己的笔记本上，准备在需要的时候参考。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### 1.2 第一次穿越
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;艾文刚进入森林就感觉到这里的气息与外界完全不同。空气中弥漫着浓郁的花香，还有隐隐约约的奇怪声音。穿越森林的第一天，艾文没有遇到什么危险，但他能感觉到，有什么东西在暗中观察他。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## 第二章：神秘生物
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;第二天，艾文继续深入森林。然而，他没走多远，就遇到了一只奇异的生物。这是一只会发光的小鹿，全身散发着柔和的蓝色光芒。起初，艾文感到惊讶和畏惧，但这只小鹿却没有攻击他的意思，还带着他走向一个隐秘的洞穴。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### 2.1 洞穴中的秘密
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;在洞穴中，艾文发现了一块古老的石板，石板上刻有一些奇怪的符号。小鹿似乎知道这些符号的含义，带着艾文一步一步地解读。原来，这些符号记载着一种强大的魔法，可以帮助他在森林中找到失落的宝藏。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### 2.2 获得帮助
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;艾文决定接受小鹿的帮助，解开这些符号的秘密。他们在洞穴中度过了几天，艾文学会了如何利用森林中的资源制作药剂和武器。通过这些，他在森林中的生存能力大大提高。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## 第三章：最终的试炼
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;在小鹿的指引下，艾文终于来到了森林的深处，那里有一个古老的祭坛。据说，只有最勇敢的冒险者才能通过祭坛的试炼，获得最终的宝藏。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### 3.1 面对恐惧
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;祭坛周围布满了各种陷阱和幻觉。艾文必须面对自己内心深处的恐惧，才能通过这些障碍。最终，他用智慧和勇气克服了一切，获得了进入祭坛的资格。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;### 3.2 发现宝藏
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;在祭坛的中心，艾文发现了一颗闪闪发光的宝石。据传，这颗宝石拥有改变命运的力量。艾文拿起宝石，感受到了其中的强大力量。他知道，这不仅仅是一件珍宝，还有可能是破解奇幻森林秘密的关键。
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="gu"&gt;## 结论
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;艾文成功地揭开了奇幻森林的部分秘密，成为了传说中的英雄。他的冒险故事也激励了更多年轻的冒险者，带着勇气和智慧，踏上探索未知世界的旅程。
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;然后分别提了三个问题：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;艾文在森林中遇到的奇异生物是什么？&lt;/li&gt;
&lt;li&gt;艾文在洞穴中找到的古老石板上刻的是什么？&lt;/li&gt;
&lt;li&gt;艾文在祭坛中心发现了什么宝藏？&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;下图是回答结果：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-09-21_qwen2-5-QA.webp"
alt="Open WebUI Qwen2.5 Answer" width="90%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h2 id="总结"&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;#&lt;/a&gt;
总结
&lt;/h2&gt;&lt;p&gt;借助 Open WebUI 和 Ollama，我们可以轻松搭建一个高效、直观的本地 RAG 系统。通过将 &lt;code&gt;bge-m3&lt;/code&gt; 语义向量模型用于文本向量化，再结合 Qwen2.5 生成模型，用户可以在一个统一的 Web 界面中进行文档检索与增强生成任务的高效互动。不但保护了数据隐私，还大幅提升了生成式 AI 的本地化应用能力。&lt;/p&gt;</description></item><item><title>Arm 矩阵加速：可伸缩矩阵扩展 SME</title><link>https://cuterwrite.top/p/arm-sme-for-performance/</link><pubDate>Tue, 13 Aug 2024 22:44:00 +0000</pubDate><guid>https://cuterwrite.top/p/arm-sme-for-performance/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/2024-08-14_117622407_p0_master1200.webp" alt="Featured image of post Arm 矩阵加速：可伸缩矩阵扩展 SME" /&gt;&lt;h2 id="1-sme-简介"&gt;
&lt;a href="#1-sme-%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;#&lt;/a&gt;
1. SME 简介
&lt;/h2&gt;&lt;p&gt;可伸缩矩阵扩展 SME (Scalable Matrix Extension) SME 是在可伸缩向量扩展（Scalable Vector Extensions， SVE 和 SVE2）的基础上建立的，并增加了有效处理矩阵的能力，主要功能包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;计算 SVE 向量的外积（Outer product）&lt;/li&gt;
&lt;li&gt;矩阵块（tile） 存储&lt;/li&gt;
&lt;li&gt;tile 向量的加载、存储、插入和提取（包括动态转置）&lt;/li&gt;
&lt;li&gt;Streaming SVE 模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下表总结了 SME、SVE 和 SVE2 的主要功能：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;SME&lt;/th&gt;
&lt;th&gt;SVE&lt;/th&gt;
&lt;th&gt;SVE2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Streaming SVE 模式&lt;/td&gt;
&lt;td&gt;NEON DSP++&lt;/td&gt;
&lt;td&gt;可伸缩向量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;动态矩阵转置&lt;/td&gt;
&lt;td&gt;多精度算术&lt;/td&gt;
&lt;td&gt;per-lane predication&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;向量外积&lt;/td&gt;
&lt;td&gt;匹配检测和直方图&lt;/td&gt;
&lt;td&gt;Gather-load 与 Scatter-store&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;加载、存储、插入和提取矩阵向量&lt;/td&gt;
&lt;td&gt;非时间性 scatter/gather&lt;/td&gt;
&lt;td&gt;预测向量化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;按位置换（bitwise permute）&lt;/td&gt;
&lt;td&gt;ML 扩展（FP16 + DOT）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;AE、SHA3、SM4、Crypto&lt;/td&gt;
&lt;td&gt;V8.6 BF16, FP 与 Int8 支持&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;SME 定义了以下新功能：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新的架构状态，可以用来存储二维矩阵 tile&lt;/li&gt;
&lt;li&gt;Streaming SVE 模式，支持执行向量长度与 tile 长度匹配的 SVE2 指令。&lt;/li&gt;
&lt;li&gt;将两个向量的外积累加（或累减）到一个矩阵 tile 中的新指令。&lt;/li&gt;
&lt;li&gt;新的加载、存储和移动指令：可以将向量写入到矩阵 tile 的一行或一列，也可以将矩阵 tile 的一行或一列读取到向量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;与 SVE2 类似，SME 也是一种支持可伸缩向量长度的扩展，可实现向量长度无关性 (VLA)、per-lane predication、predication 驱动的循环控制和管理功能。&lt;/p&gt;
&lt;h2 id="2-streaming-sve-模式"&gt;
&lt;a href="#2-streaming-sve-%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;#&lt;/a&gt;
2. Streaming SVE 模式
&lt;/h2&gt;&lt;p&gt;SME 引入了 Streaming SVE 模式，该模式实现了 SVE2 指令集的一个子集，并增加了新的 SME 专用指令。&lt;/p&gt;
&lt;p&gt;Streaming SVE 模式支持对大型数据集进行高吞吐量地流式数据处理，流式数据通常具有简单的循环控制流和有限的条件性。&lt;/p&gt;
&lt;p&gt;在 Non-streaming SVE 模式下，支持完整的 SVE2 指令集，通常处理复杂的数据结构和复杂的判断。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-14_3443.webp"
alt="Streaming SVE 模式与 Non-streaming SVE 模式" width="80%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Streaming SVE 模式与 Non-streaming SVE 模式&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;大多数 SME 指令仅在 Streaming SVE 模式下可用。Streaming SVE 模式下的流向量长度（SVL）可能与非流向量长度（NSVL）不同。&lt;/p&gt;
&lt;p&gt;预期是：SVL 要比 NSVL 更长或是相同，也就是 SVL &amp;gt;= NSVL。例如，NSVL 的长度可以为 128-bit , 而 SVL 的长度可以为 512-bit 。&lt;/p&gt;
&lt;p&gt;SME 的 SVL 可以是 128-bit , 256-bit , 512-bit, 1024-bit 或是 2048-bit 。SVL 需要是 2 的次幂，而 NSVL 需要是 128 的整数倍。&lt;/p&gt;
&lt;p&gt;与 SVE2 类似，软件可以控制 &lt;code&gt;SMCR_ELx.LEN&lt;/code&gt; 寄存器位来设置 EL1, EL2, EL3 想用的有效 SVL 长度（可以设置为比硬件支持的 SVL 更短）。&lt;/p&gt;
&lt;p&gt;有关 Streaming SVE 模式的更多信息，请参阅《Arm 架构参考手册》第 B1.4.6 节（A-profile 架构）。&lt;/p&gt;
&lt;h2 id="3-切换-non-streaming-和-streaming-sve-模式"&gt;
&lt;a href="#3-%e5%88%87%e6%8d%a2-non-streaming-%e5%92%8c-streaming-sve-%e6%a8%a1%e5%bc%8f" class="header-anchor"&gt;#&lt;/a&gt;
3. 切换 Non-streaming 和 Streaming SVE 模式
&lt;/h2&gt;&lt;p&gt;如果 CPU 硬件实现既支持 Streaming SVE 模式的 SME ，又支持 Non-streaming SVE 模式的 SVE2 ，应用程序可以根据自己的需求动态切换这两个操作模式。&lt;/p&gt;
&lt;p&gt;为 SME 提供一个独立的操作模式，使 CPU 硬件实现可以为同一应用提供不同的向量长度。比如 CPU 硬件实现可以选择支持一个更长的 Streaming SVE 模式向量长度，并针对适用于高吞吐量的流操作对硬件进行优化。&lt;/p&gt;
&lt;p&gt;应用程序很容易在 Streaming SVE 模式和 Non-streaming SVE 模式之间动态切换。SME 引入的 &lt;code&gt;PSTATE.{SM, ZA}&lt;/code&gt; 位可以可启用和禁用 Streaming SVE 模式和 SME ZA 存储：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SM: 启用与禁用 Streaming SVE 模式&lt;/li&gt;
&lt;li&gt;ZA：启用和禁用 ZA 存储访问&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;可以通过 &lt;code&gt;MSR/MRS&lt;/code&gt; 指令操作 Streaming Vector Control Register (SVCR) 来设置和读取 &lt;code&gt;PSTATE.{SM, ZA}&lt;/code&gt; 位，具体操作如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MSR SVCRSM, #&amp;lt;imm&amp;gt; MSR SVCRSM，#&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MSR SVCRZA, #&amp;lt;imm&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MSR SVCRSMZA, #&amp;lt;imm&amp;gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SMSTART 指令是设置 &lt;code&gt;PSTATE.SM&lt;/code&gt; 和 &lt;code&gt;PSTATE.ZA&lt;/code&gt; 的 &lt;code&gt;MSR&lt;/code&gt; 指令的别名&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SMSTART&lt;/code&gt;：同时启用 Streaming SVE 模式和 ZA 存储访问&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SMSTART SM&lt;/code&gt;：启用 Streaming SVE 模式&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SMSTART ZA&lt;/code&gt;：启用 ZA 存储访问&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SMSTOP 指令则是清除 &lt;code&gt;PSTATE.SM&lt;/code&gt; 和 &lt;code&gt;PSTATE.ZA&lt;/code&gt; 的 &lt;code&gt;MSR&lt;/code&gt; 指令的别名。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;SMSTOP&lt;/code&gt;：同时禁用 Streaming SVE 模式和 ZA 存储访问&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SMSTOP SM&lt;/code&gt;：禁用 Streaming SVE 模式&lt;/li&gt;
&lt;li&gt;&lt;code&gt;SMSTOP ZA&lt;/code&gt;：禁用 ZA 存储访问&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下图展示了应用程序是如何在 Streaming SVE 模式和 Non-streaming SVE 模式之间切换的：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_Scalable_Matrix_p1.webp"
alt="应用程序切换 Streaming SVE 模式和 Non-streaming SVE 模式" width="50%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;应用程序切换 Streaming SVE 模式和 Non-streaming SVE 模式&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;有关使用 SMSTART 和 SMSTOP 在 Streaming SVE 模式和 Non-Streaming SVE 模式之间切换的更多信息，请参阅《Arm 架构参考手册》中有关 A-profile 架构的 C6.2.327 和 C6.2.328 节。&lt;/p&gt;
&lt;h2 id="4-sme-架构状态"&gt;
&lt;a href="#4-sme-%e6%9e%b6%e6%9e%84%e7%8a%b6%e6%80%81" class="header-anchor"&gt;#&lt;/a&gt;
4. SME 架构状态
&lt;/h2&gt;&lt;p&gt;与 SVE2 类似，在 Streaming SVE 模式，它有 &lt;code&gt;Z0-Z31&lt;/code&gt; 向量寄存器，和 &lt;code&gt;P0-P15&lt;/code&gt; Predicate 寄存器。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_4130_ARM2799_3_Scalable_Matrix_p1.webp"
alt="Streaming mode registers" width="70%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;SVE 向量寄存器的最低编号位 &lt;code&gt;Zn&lt;/code&gt; 也保存着固定长度的 &lt;code&gt;Vn、Qn、Dn、Sn、Hn&lt;/code&gt; 和 &lt;code&gt;Bn&lt;/code&gt; 寄存器。&lt;/p&gt;
&lt;p&gt;进入 Streaming SVE 模式（ &lt;code&gt;PSTATE.SM&lt;/code&gt; 由 0 变为 1）或退出 Streaming SVE 模式（ &lt;code&gt;PSTATE.SM&lt;/code&gt; 由 1 变为 0）时，所有这些寄存器都将置零。&lt;/p&gt;
&lt;p&gt;大多数 Non-streaming SVE2 指令可用于 Streaming SVE 模式，但&lt;strong&gt;可能使用不同的向量长度&lt;/strong&gt;（流模式使用 VSL 长度，非流模式使用 NVSL 长度）。可以使用 &lt;code&gt;RDSVL&lt;/code&gt; 指令读取当前的有效向量长度 VL。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;//Read multiple of Streaming SVE vector register size to Xd
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;RDSVL&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Xd&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;imm&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote class="alert-blockquote alert-note"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;注释&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;因为 SME 支持 Vector Length Agnostic (VLA) ，在 Streaming SVE 模式下，软件很少需要明确读 SVL 向量长度。在 Non-streaming SVE 模式下，通常使用 RDSVL 指令来确定 SVL 的值。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="5-za-array"&gt;
&lt;a href="#5-za-array" class="header-anchor"&gt;#&lt;/a&gt;
5. ZA array
&lt;/h2&gt;&lt;p&gt;SME 新引入的 ZA (Z Array, ZA Storage) 是一个二维（2D）正方形数组，大小是 SVL x SVL。之所以叫 Z Array，也是因为它行与列的长度与 Streaming SVE 模式下的 Zn 寄存器一致。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_4314_ARM2799_4_Scalable_Matrix_p1.webp"
alt="ZA array" width="50%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;ZA array&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;例如：如果 Streaming SVE 模式下的向量长度为 256-bit，即 Zn 寄存器的长度为 256-bit，那么 ZA 的大小为 (256/8 bytes) x (256/8 bytes) 。&lt;/p&gt;
&lt;p&gt;ZA array 可以通过以下方式访问：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ZA array vector 访问&lt;/li&gt;
&lt;li&gt;ZA tiles&lt;/li&gt;
&lt;li&gt;ZA tile slices&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="51-za-array-vector-访问"&gt;
&lt;a href="#51-za-array-vector-%e8%ae%bf%e9%97%ae" class="header-anchor"&gt;#&lt;/a&gt;
5.1 ZA array vector 访问
&lt;/h3&gt;&lt;p&gt;ZA array 的一行可以当成一个 SVL 长度的向量来访问，这个向量可以放数据类型长度为 8-bit, 16-bit, 32-bit, 64-bit 或 128-bit 的元素，比如 32-bit 的 fp32 浮点数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;ZA&lt;/span&gt;&lt;span class="p"&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;N&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ZA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;H&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ZA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;S&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ZA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;D&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;ZA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;N&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中 &lt;code&gt;B，H，S，D，Q&lt;/code&gt; 分别表示 8-bit , 16-bit , 32-bit , 64-bit , 128-bit。&lt;/p&gt;
&lt;p&gt;ZA array vector 的数量与 SVL 中的字节数相同，例如，如果 SLV 是 256-bit ，那么 ZA array vector 的数量是 32 个，N 的范围是 0 到 31。&lt;/p&gt;
&lt;p&gt;为了支持上下文切换，SME 引入了新的 &lt;code&gt;LDR&lt;/code&gt; 和 &lt;code&gt;STR&lt;/code&gt; 指令，用于从内存加载和存储一个 ZA array vector。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;LDR&lt;/span&gt; &lt;span class="no"&gt;ZA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Wv&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;imm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Xn&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="no"&gt;SP&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;{&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;imm&amp;gt;, MUL VL}]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;STR&lt;/span&gt; &lt;span class="no"&gt;ZA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Wv&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;imm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Xn&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="no"&gt;SP&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;{&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;imm&amp;gt;, MUL VL}]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="52-za-tiles"&gt;
&lt;a href="#52-za-tiles" class="header-anchor"&gt;#&lt;/a&gt;
5.2 ZA tiles
&lt;/h3&gt;&lt;p&gt;ZA tile 是在 ZA 中的正方形的二维子矩阵。ZA tile 的宽度始终是 SVL，与 ZA array 的宽度相同。&lt;/p&gt;
&lt;p&gt;ZA 可以分成多少个可用的 ZA tile 是由元素的数据类型大小决定的：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;元素数据类型大小&lt;/th&gt;
&lt;th&gt;tile 数量&lt;/th&gt;
&lt;th&gt;tile 名称&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;8-bit&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;ZA0.B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;16-bit&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;ZA0.H-ZA1.H&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;32-bit&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;ZA0.S-ZA3.S&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;64-bit&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;ZA0.D-ZA7.D&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;128-bit&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;ZA0.Q-ZA15.Q&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;当元素数据类型为 8-bit 时，ZA 只能作为一个 ZA tile (ZA0.B) 被访问。&lt;/li&gt;
&lt;li&gt;当元素数据类型为 16-bit 时，ZA 可以作为 2 个 ZA tile (ZA0.H 和 ZA1.H) 被访问。&lt;/li&gt;
&lt;li&gt;当元素数据类型为 32-bit 时，ZA 可以作为 4 个 ZA tile (ZA0.S 到 ZA3.S) 被访问。&lt;/li&gt;
&lt;li&gt;当元素数据类型为 64-bit 时，ZA 可以作为 8 个 ZA tile (ZA0.D 到 ZA7.D) 被访问。&lt;/li&gt;
&lt;li&gt;当元素数据类型为 128-bit 时，ZA 可以作为 16 个 ZA tile (ZA0.Q 到 ZA15.Q) 被访问。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，如果 SVL 为 256-bit，元素数据类型大小为 8-bit，则 ZA 可以视为 ZA0.B，也可视为 32 个向量（32 行，每行大小为 32 x 8-bit，即每行 32 个元素）。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_ZA0B.webp"
alt="ZA0.B" width="50%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;如果 SVL 为 256-bit，元素数据类型大小为 16-bit，则 ZA 可以视为 2 个 ZA tile (ZA0.H 和 ZA1.H)，每个 tile 视为 16 个向量（16 行，每行大小为 16 x 16-bit，即每行 16 个元素）。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_ZA0H_ZA1H.webp"
alt="ZA0.H 和 ZA1.H" width="40%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;这样做的好处是充分利用了 ZA storage，在实际应用中，比如说当 SVL 为 256-bit，元素数据类型大小为 32-bit，ZA 的大小为 256-bit x 256-bit 时，&lt;strong&gt;要对两个 Z 寄存器里的向量做外积运算&lt;/strong&gt;，计算得到的外积结果是 8 x 8 的二维浮点数数组，这个外积只需要 ZA 的 1/4 的存储空间。将 ZA 分成 4 个 ZA tile，这样就可以充分利用 ZA storage。&lt;/p&gt;
&lt;h3 id="53-za-tile-slices"&gt;
&lt;a href="#53-za-tile-slices" class="header-anchor"&gt;#&lt;/a&gt;
5.3 ZA tile slices
&lt;/h3&gt;&lt;p&gt;一个 ZA tile 可以作为一个整体来访问，也可以以一个个 ZA tile slice 的方式访问。&lt;/p&gt;
&lt;p&gt;当作为一个整体访问时，指令可以使用 tile 的名字访问：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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;ZA0.B, ZA0.H-ZA1.H, ZA0.S-ZA3.S, ZA0.D-ZA7.D or ZA0.Q-ZA15.Q
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;一个 ZA tile slice 是由其 ZA tile 中&lt;strong&gt;水平方向或是垂直方向的连续元素组成的一维数组&lt;/strong&gt;，即在 ZA tile 中的一行或是一列。&lt;/p&gt;
&lt;p&gt;对一个 ZA tile 的向量访问即是读写一个 ZA tile slice ：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;水平或垂直方向的 ZA tile slice 访问，由 ZA tile 名字后的 &lt;code&gt;H&lt;/code&gt; 或 &lt;code&gt;V&lt;/code&gt; 后缀来表示。&lt;/li&gt;
&lt;li&gt;具体的 ZA tile slice 由一个索引来表示，由 ZA tile 名字后的切片索引 &lt;code&gt;[N]&lt;/code&gt; 来表示。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，如果 SVL 为 128 位，元素数据类型大小为 8-bit，那么其水平的和垂直的 ZA tile slice 可由下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_6724_ARM2799_7_Scalable_Matrix_p1.webp"
alt="ZA tile slices" width="50%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;再例如，如果 SVL 为 128 位，元素数据类型大小为 16-bit，那么其水平的和垂直的 ZA tile slice 可由下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_6888_ARM2799_8_Scalable_Matrix_p1.webp"
alt="ZA tile slices" width="50%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;为了提高硬件访问 ZA tile 和 ZA tile slices 的效率，ZA tile 的 ZA tile slices 是交错排列的。&lt;/p&gt;
&lt;p&gt;下图显示了这种交错排列的示例。在此示例中，SVL 为 256 位，元素数据类型大小为 16 位。这意味着，ZA 可被视为两个 ZA tile（ZA0H 和 ZA1H），并具有交错的水平 tile slices ：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_4885_SME_interleave.webp"
alt="ZA tile slices" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;下图展示了不同的元素数据类型大小的水平和垂直方向 ZA tile slice 的混合视图:&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-15_7673_SME_V_H.webp"
alt="ZA tile slices" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;左侧各栏显示了 ZA 存储器每一行的不同处理方式。&lt;/p&gt;
&lt;p&gt;设 SIZE 为向量元素的大小，其中 SIZE 为 1、2、4、8、16，分别代表数据类型 B、H、S、D 或 Q。&lt;/p&gt;
&lt;p&gt;设 NUM_OF_ELEMENTS 为向量中的元素个数，即 bytes_of(SVL)/SIZE。&lt;/p&gt;
&lt;p&gt;水平 tile slice， &lt;code&gt;ZAnH.&amp;lt;B|H|S|D|Q&amp;gt;[m]&lt;/code&gt; 访问一个向量，该向量包含 ZA storage 中的整行（m x SIZE + n）。该向量包含数据类型为 B、H、S、D 或 Q 的元素。&lt;/p&gt;
&lt;p&gt;垂直 tile slice，&lt;code&gt;ZAnV.&amp;lt;B|H|S|D|Q&amp;gt;[m] &lt;/code&gt; 访问一个向量，该向量包含 ZA storage 中的整列（m x SIZE）。该向量包含数据类型为 B、H、S、D 或 Q 的元素。&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ZAnV.[m] &lt;/code&gt; 访问一个包含列（m x SIZE）和行元素（i x SIZE + n）的向量，其中 i 为 0 ~ NUM_OF_ELEMENTS-1。该向量包含数据类型为 B、H、S、D 或 Q 的元素。&lt;/p&gt;
&lt;p&gt;使用混合元素数据类型大小以及水平和垂直 tile slice 的应用应小心处理重叠。&lt;/p&gt;
&lt;p&gt;有关 ZA Array、ZA array vectors、tile 和 tile slices 的更多信息，请参阅《Arm 架构参考手册》中有关 A-profile 架构的 B1.4.8 至 B1.4.12 节。&lt;/p&gt;
&lt;h2 id="6-steaming-sve-模式下支持的指令"&gt;
&lt;a href="#6-steaming-sve-%e6%a8%a1%e5%bc%8f%e4%b8%8b%e6%94%af%e6%8c%81%e7%9a%84%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
6. Steaming SVE 模式下支持的指令
&lt;/h2&gt;&lt;p&gt;某些指令在 Streaming SVE 模式下有限制：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;一些 SVE/SVE2 指令变为非法执行
&lt;ul&gt;
&lt;li&gt;Gathed-load 和 Scatter-store 指令&lt;/li&gt;
&lt;li&gt;使用 First Fault 寄存器的 SVE2 指令&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;大多的 NEON 指令变为 UNDEFINED&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;有关受 Streaming SVE 模式影响的指令的更多信息，请参阅文档 《Arm 架构参考手册》。&lt;/p&gt;
&lt;p&gt;SME 增加了几条新指令，其中包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;矩阵外积和累加或减法指令，包括 FMOPA、UMOPA 和 BFMOPA。
&lt;ul&gt;
&lt;li&gt;SVE2 向量寄存器（Z0-Z31）作为外积运算的行和列输入。&lt;/li&gt;
&lt;li&gt;ZA storage 保存二维矩阵 tile 的输出结果。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;将 SVE2 Z 向量与 ZA 的行或列做加法运算的指令&lt;/li&gt;
&lt;li&gt;对 ZA tiles 的清零操作指令&lt;/li&gt;
&lt;li&gt;增加了一些在 Streaming 和 Non-streaming 模式下都能使用的指令&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="7-sme-指令"&gt;
&lt;a href="#7-sme-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7. SME 指令
&lt;/h2&gt;&lt;p&gt;操作 ZA storage 的 SME 指令主要包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;计算两个向量的外积，并累加或累减，然后将结果放入一个 ZA tile 的指令&lt;/li&gt;
&lt;li&gt;将 SVE 向量（Z 寄存器）存入或取出 ZA tile 的行或列的指令&lt;/li&gt;
&lt;li&gt;水平或垂直方向上，一个 SVE 向量与 ZA tile 的加法指令&lt;/li&gt;
&lt;li&gt;给一个标量寄存器加上 Streaming SVE 模式下向量长度的倍数的指令&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="71-外积并累加或累减指令"&gt;
&lt;a href="#71-%e5%a4%96%e7%a7%af%e5%b9%b6%e7%b4%af%e5%8a%a0%e6%88%96%e7%b4%af%e5%87%8f%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.1 外积并累加或累减指令
&lt;/h3&gt;&lt;p&gt;为了帮助理解外积并累加或累减指令，让我们看看如何使用外积操作来做矩阵乘法。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_2313_Picture1_png-1280x960.webp"
alt="Outer product" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;计算两个向量 a 和 b 的外积会得到一个包含外积的结果矩阵 C：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_1665_Picture2_png-1280x960.webp"
alt="Outer product" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;现在考虑两个矩阵 a 和 b 的矩阵乘运算：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_8117_Picture3_png-1280x960.webp"
alt="Matrix multiplication" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;这个矩阵乘可以通过计算两次外积操作和两个结果矩阵的累加来实现（就是常用的手写计算的方法），如下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_3731_Picture4_png-1280x960.webp"
alt="Matrix multiplication with outer product" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;SME 为以下数据类型引入了高效的外积并累加或减法指令：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;8-bit, 16-bit 整数&lt;/li&gt;
&lt;li&gt;FP16, BF16, FP32 和 FP64 浮点数&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些指令计算两个 Z 向量寄存器（Zn 和 Zm）中两个向量的外积，将结果数组与一个 ZA tile（ZAda）中已有数据进行累加或累减，并将结果存入同一 ZA tile（ZAda）中。每个源向量由相应的控制 predicate 寄存器（Pn 和 Pm）独立地 predicate。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;输出数组&lt;/th&gt;
&lt;th&gt;输入向量&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;INT32&lt;/td&gt;
&lt;td&gt;INT8, INT8&lt;/td&gt;
&lt;td&gt;将四个 INT8 外积之和存入每个 INT32 元素&lt;/td&gt;
&lt;td&gt;SMOPA 或 SMOPS 或 UMOPA 或 UMOPS：带符号或无符号整数外积和，并累加或累减。例如： &lt;code&gt;UMOPS &amp;lt;ZAda&amp;gt;.S, &amp;lt;Pn&amp;gt;/M, &amp;lt;Pm&amp;gt;/M, &amp;lt;Zn&amp;gt;.B, &amp;lt;Zm&amp;gt;.B&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INT32&lt;/td&gt;
&lt;td&gt;INT16, INT16&lt;/td&gt;
&lt;td&gt;将两个 INT16 外积之和存入每个 INT32 元素&lt;/td&gt;
&lt;td&gt;SMOPA 或 SMOPS 或 UMOPA 或 UMOPS：带符号或无符号整数外积和，并累加或累减。例如： &lt;code&gt;UMOPS &amp;lt;ZAda&amp;gt;.S, &amp;lt;Pn&amp;gt;/M, &amp;lt;Pm&amp;gt;/M, &amp;lt;Zn&amp;gt;.H, &amp;lt;Zm&amp;gt;.H&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INT64&lt;/td&gt;
&lt;td&gt;INT16, INT16&lt;/td&gt;
&lt;td&gt;如果实现了 FEAT_SME_I16I64，则将四个 INT16 外积之和存入每个 INT64 元素&lt;/td&gt;
&lt;td&gt;SMOPA 或 SMOPS 或 UMOPA 或 UMOPS：带符号或无符号整数外积和，并累加或累减。例如： &lt;code&gt;UMOPS &amp;lt;ZAda&amp;gt;.D, &amp;lt;Pn&amp;gt;/M, &amp;lt;Pm&amp;gt;/M, &amp;lt;Zn&amp;gt;.H, &amp;lt;Zm&amp;gt;.H&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FP32&lt;/td&gt;
&lt;td&gt;BF16, BF16&lt;/td&gt;
&lt;td&gt;将两个 BF16 外积之和存入每个 FP32 元素&lt;/td&gt;
&lt;td&gt;BFMOPA 或 BFMOPS：BFloat16 外积和，并累加或累减。例如： &lt;code&gt;BFMOPS &amp;lt;ZAda&amp;gt;.S, &amp;lt;Pn&amp;gt;/M, &amp;lt;Pm&amp;gt;/M, &amp;lt;Zn&amp;gt;.H, &amp;lt;Zm&amp;gt;.H&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FP32&lt;/td&gt;
&lt;td&gt;FP16, FP16&lt;/td&gt;
&lt;td&gt;将两个 FP16 外积之和存入每个 FP32 元素&lt;/td&gt;
&lt;td&gt;FMOPA 或 FMOPS：半精度浮点外积和，并累加或累减。例如： &lt;code&gt;FMOPS &amp;lt;ZAda&amp;gt;.S, &amp;lt;Pn&amp;gt;/M, &amp;lt;Pm&amp;gt;/M, &amp;lt;Zn&amp;gt;.H, &amp;lt;Zm&amp;gt;.H&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FP32&lt;/td&gt;
&lt;td&gt;FP32, FP32&lt;/td&gt;
&lt;td&gt;简单的 FP32 外积&lt;/td&gt;
&lt;td&gt;FMOPA 或 FMOPS：浮点外积和，并累加或累减。例如： &lt;code&gt;FMOPS &amp;lt;ZAda&amp;gt;.S, &amp;lt;Pn&amp;gt;/M, &amp;lt;Pm&amp;gt;/M, &amp;lt;Zn&amp;gt;.S, &amp;lt;Zm&amp;gt;.S&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FP64&lt;/td&gt;
&lt;td&gt;FP64, FP64&lt;/td&gt;
&lt;td&gt;如果实现了 FEAT_SME_F64F64，则进行简单的 FP64 外积&lt;/td&gt;
&lt;td&gt;FMOPA 或 FMOPS：浮点外积和，并累加或累减。例如： &lt;code&gt;FMOPS &amp;lt;ZAda&amp;gt;.D, &amp;lt;Pn&amp;gt;/M, &amp;lt;Pm&amp;gt;/M, &amp;lt;Zn&amp;gt;.D, &amp;lt;Zm&amp;gt;.D&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 id="711-fp32-fp64-外积并累加或累减指令"&gt;
&lt;a href="#711-fp32-fp64-%e5%a4%96%e7%a7%af%e5%b9%b6%e7%b4%af%e5%8a%a0%e6%88%96%e7%b4%af%e5%87%8f%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.1.1 FP32, FP64 外积并累加或累减指令
&lt;/h4&gt;&lt;p&gt;那些输入向量和输出数组有同样数据类型（FP32， FP64）的指令相对简单。&lt;/p&gt;
&lt;p&gt;下例展示了 FP32 类型的外积并累加或累减指令。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;FMOPA&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ZAda&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;FMOPS&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ZAda&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_3613751670-667e5f923c64.webp"
alt="FMOPA and FMOPS" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;这个例子中，假设 SVL 向量长度为 128，&lt;code&gt;Zn.S&lt;/code&gt; 和 &lt;code&gt;Zm.S&lt;/code&gt; 中存放了 4 个 FP32 数组成的向量，此指令计算 &lt;code&gt;Zn.S&lt;/code&gt; 和 &lt;code&gt;Zm.S&lt;/code&gt; 的外积，外积结果为图中灰色的矩阵，然后将此外积结果累加或累减 &lt;code&gt;ZAda.S&lt;/code&gt; 这个 ZA tile 中原有的值，将结果存入同一 ZA tile。&lt;/p&gt;
&lt;h4 id="712-fp16-bf16-int16-int8-i16i64-类型的外积并累加或累减指令"&gt;
&lt;a href="#712-fp16-bf16-int16-int8-i16i64-%e7%b1%bb%e5%9e%8b%e7%9a%84%e5%a4%96%e7%a7%af%e5%b9%b6%e7%b4%af%e5%8a%a0%e6%88%96%e7%b4%af%e5%87%8f%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.1.2 FP16, BF16, INT16, INT8, I16I64 类型的外积并累加或累减指令
&lt;/h4&gt;&lt;p&gt;由于这些指令会扩大计算结果数据类型，因此这些操作不像前面 FP32，FP64 类型指令那么简单明了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;BF16 指令计算两个 BF16 的外积的和，扩大结果类型为 FP32, 然后将结果与目标 tile 进行破坏性相加或相减。&lt;/li&gt;
&lt;li&gt;INT8 指令计算四个 INT8 的外积的和，扩大结果类型为 INT32，然后将结果与目标 tile 进行破坏性相加或相减。&lt;/li&gt;
&lt;li&gt;INT16 指令计算两个 INT16 的外积的和，扩大结果类型为 INT32，然后将结果与目标 tile 进行破坏性相加或相减。&lt;/li&gt;
&lt;li&gt;FP16 指令计算两个 FP16 的外积的和，扩大结果类型为 FP32，然后将结果与目标 tile 进行破坏性相加或相减。&lt;/li&gt;
&lt;li&gt;如果实现了 FEAT_SME_I16I64，I16I64 指令计算四个 INT16 的外积的和，扩大结果类型为 INT64, 然后将结果与目标 tile 进行破坏性相加或相减。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;以下例子展示了 SVL 向量长度为 128 的 INT8 UMOPA 指令进行的操作：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;UMOPA&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ZAda&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.B&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_1030_Picture6_png-1280x960.webp"
alt="INT8 UMOPA" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;每个输入寄存器（&lt;code&gt;Zn.B&lt;/code&gt;、&lt;code&gt;Zm.B&lt;/code&gt;）都被视为一个包含 4x4 元素的矩阵，可以看作是 4 个连续元素组成的块（如图中红线所标）被转置了。&lt;/p&gt;
&lt;p&gt;在这个例子中，因为 SVL 向量长度为 128-bit：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一源向量 &lt;code&gt;Zn.B&lt;/code&gt; ，包含一个无符号 8-bit 整数的 4x4 子矩阵。&lt;/li&gt;
&lt;li&gt;第二源向量 &lt;code&gt;Zm.B&lt;/code&gt; ，包含一个无符号 8-bit 整数的 4x4 子矩阵。&lt;/li&gt;
&lt;li&gt;UMOPA 指令计算出 4x4 扩大了的 32-bit 整数外积的和，然后破坏性地累加上目标 tile（ZAda）中的整数。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更笼统地说，UMOPA 指令是将第一个源向量中的子矩阵与第二个源向量中的子矩阵相乘。每个源向量包含一个(SVL/32) x 4 的无符号 8-bit 整数的子矩阵。然后将得到的 (SVL/32) x (SVL/32)扩大了的 32-bit 整数外积和破坏性地加上一个 32-bit 整数目标 tile。&lt;/p&gt;
&lt;p&gt;下面的例子展示了 SVL 为 128-bit 的 BF16 BFMOPA 进行的操作：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;BFMOPA&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;ZAda&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.H&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.H&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_6545_Picture7_png-1280x960.webp"
alt="BF16 BFMOPA" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;在这个例子中，因为 SVL 向量长度为 128-bit：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;第一源向量 &lt;code&gt;Zn.H&lt;/code&gt; ，包含一个 BF16 整数的 4x2 子矩阵，它被扩大成单精度浮点数。&lt;/li&gt;
&lt;li&gt;第二源向量 &lt;code&gt;Zm.H&lt;/code&gt; ，包含一个 BF16 整数的 2x4 子矩阵，它被扩大成单精度浮点数。&lt;/li&gt;
&lt;li&gt;BMOPA 指令计算出 4x4 单精度外积的和，然后破坏性地累加上目标 tile（ZAda）中的单精度浮点数。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更笼统地说，BFMOPA 指令扩大了存放在第一源向量里的(SVL/32) x2 BF16 子矩阵的类型为单精度，扩大了存放在第二源向量里的 2x (SVL/32) BF16 子矩阵的类型为单精度，将这两个子矩阵相乘。然后将得到的 (SVL/32) x (SVL/32)单精度外积和破坏性地加上一个单精度目标 tile。&lt;/p&gt;
&lt;p&gt;以下表格显示了几种数据类型和 SVL 长度的一条外积并累加或累减指令所做的对应数据类型的 MAC(乘累加)数量：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;128-bit&lt;/th&gt;
&lt;th&gt;256-bit&lt;/th&gt;
&lt;th&gt;512-bit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;FP32&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FP64&lt;/td&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INT8&lt;/td&gt;
&lt;td&gt;64&lt;/td&gt;
&lt;td&gt;256&lt;/td&gt;
&lt;td&gt;1024&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;INT16&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BF16&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FP16&lt;/td&gt;
&lt;td&gt;32&lt;/td&gt;
&lt;td&gt;128&lt;/td&gt;
&lt;td&gt;512&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id="72-带-predication-的-sme-指令"&gt;
&lt;a href="#72-%e5%b8%a6-predication-%e7%9a%84-sme-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.2 带 Predication 的 SME 指令
&lt;/h3&gt;&lt;p&gt;每个源向量都可以被其相应的控制 predicate 寄存器独立地 predicate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;外积并累加或累减指令使用 Pn/M 和 Pn/M (没有/Z 形式)：Inactive 的源元素被当成具有 0 值。&lt;/li&gt;
&lt;li&gt;Slice move 指令使用 Pg/M: 目标 slice 中 Inactive 的元素保持不变。&lt;/li&gt;
&lt;li&gt;Tile slice load 指令使用 Pg/Z: 目标 tile slice 中的 Inactive 元素被设置为 0。&lt;/li&gt;
&lt;li&gt;Tile slice store 指令使用 Pg: Inactive 的元素不会写入内存。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Predication 让矩阵的维数不是 SVL 的倍数的情况更容易处理。&lt;/p&gt;
&lt;p&gt;例如下图的指令：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_2656_Picture12_png-600x0.webp"
alt="SME predication" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;输入向量 &lt;code&gt;Z0&lt;/code&gt; 被 &lt;code&gt;P0&lt;/code&gt; predicate，&lt;code&gt;Z1&lt;/code&gt; 被 &lt;code&gt;P1&lt;/code&gt; predicate。&lt;/p&gt;
&lt;p&gt;在这个例子中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SVL 向量长度为 512-bit。&lt;/li&gt;
&lt;li&gt;Z 寄存器中包含 16 个 FP32 数组成的向量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;P0&lt;/code&gt; 中最后两个元素是 inactive 的。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;P1&lt;/code&gt; 中最后一个元素是 inactive 的。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这条指令更新 &lt;code&gt;ZA0.S&lt;/code&gt; 中 (16-2) x (16-1) 个 FP32 元素，因为使用了 &lt;code&gt;Pn/M&lt;/code&gt; , &lt;code&gt;ZA0.S&lt;/code&gt; 中剩下的元素保持不变。&lt;/p&gt;
&lt;p&gt;下图展示了更多的 predicated 外积并累加或累减的例子。图中被划线的文字表示被 inactive predicate 元素影响的计算部分。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_2072_Picture14_png-1280x960.webp"
alt="SME predication FMOPA" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_3513_Picture16_png-1280x960.webp"
alt="SME predication UMOPA" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="73-za-tile-与一个-z-向量的加运算"&gt;
&lt;a href="#73-za-tile-%e4%b8%8e%e4%b8%80%e4%b8%aa-z-%e5%90%91%e9%87%8f%e7%9a%84%e5%8a%a0%e8%bf%90%e7%ae%97" class="header-anchor"&gt;#&lt;/a&gt;
7.3 ZA tile 与一个 Z 向量的加运算
&lt;/h3&gt;&lt;p&gt;SME 包括 ZA tile 的行或列都加上一个向量的指令，这些指令也有 predication 的支持。&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;指令&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ADDHA&lt;/td&gt;
&lt;td&gt;将源向量添加到 ZA tile 的每个水平 slice 上&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ADDVA&lt;/td&gt;
&lt;td&gt;将源向量添加到 ZA tile 的每个垂直 slice 上&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;ADDHA&lt;/span&gt; &lt;span class="no"&gt;ZA0.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P1&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Z1.S&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;将执行以下操作：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_ARM2799_9_Scalable_Matrix_p2_png-1200x0.webp"
alt="SME ADDHA" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;这个 ADDHA 指令将源向量 Z1 中的每个元素加上 ZA0.S tile 每一水平 slice 的相应 active 元素。&lt;/p&gt;
&lt;p&gt;Tile 中元素被一对 governing predicate 进行 predicate。 一个水平 slice 中的一个元素在下面情况下可以认为是 active：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;它在第二 governing predicate 对应的元素是 TRUE, 并且&lt;/li&gt;
&lt;li&gt;它在第一 governing predicate 对应的水平 slice 行号也为 TRUE,目标 tile 中 inactive 元素保持不变。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="74-tile-load-store-move-指令"&gt;
&lt;a href="#74-tile-load-store-move-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.4 Tile load, store, move 指令
&lt;/h3&gt;&lt;p&gt;SME tile load, store, move 指令可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;从内存读取数据，放入 ZA tile 的行或列&lt;/li&gt;
&lt;li&gt;将 ZA tile 的行或列写入内存&lt;/li&gt;
&lt;li&gt;将 ZA tile 的行移动到 SVE Z 向量寄存器&lt;/li&gt;
&lt;li&gt;将 SVE Z 向量寄存器移动到 ZA tile 行或列&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="741-tile-slice-load-和-store-指令"&gt;
&lt;a href="#741-tile-slice-load-%e5%92%8c-store-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.4.1 Tile slice load 和 store 指令
&lt;/h4&gt;&lt;p&gt;LD1B、LD1H、LD1S、LD1D 和 LD1Q 指令分别将连续内存值加载到具有 8-bit、16-bit、32-bit、64-bit 或 128-bit 元素的 ZA tile slice 中。&lt;/p&gt;
&lt;p&gt;ST1B、ST1H、ST1S、ST1D 和 ST1Q 指令分别将包含 8-bit、16-bit、32-bit、64-bit 或 128-bit 元素的 ZA tile slice 存储到连续内存中。&lt;/p&gt;
&lt;p&gt;这些指令也支持 predication ，例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;LD1B&lt;/span&gt; &lt;span class="no"&gt;ZA0H.B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;W0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#imm], P0/Z, [X1, X2]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此 LD1B 指令执行 predicated 的连续 byte 读取，它从地址为(X1+X2)的内存读取数据到 ZA0 中行号为（W0+imm）的这个水平 tile slice 中。目标 tile slice 中 Inactive 的元素被设置为 0。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;ST1H&lt;/span&gt; &lt;span class="no"&gt;ZA1V.H&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;W0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#imm], P2, [X1, X2, LSL #1]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此 ST1H 指令执行 predicated 连续 halfword 的存操作，它将 ZA1 中列号为（W0+imm）的垂直 tile slice 存到地址为（X1+X2*2）的内存， tile slice 中 Inactive 的元素不写入内存。&lt;/p&gt;
&lt;h4 id="742-tile-slice-move-指令"&gt;
&lt;a href="#742-tile-slice-move-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.4.2 Tile slice move 指令
&lt;/h4&gt;&lt;p&gt;MOV 指令（MOVA 指令的别名）将一个 Z 向量寄存器的值移动到一个 ZA tile slice，或将一个 ZA tile slice 中的值移动到一个 Z 向量寄存器。这条指令操作带指定元素大小的 ZA tile 的单个水平或垂直 tile slice。 Slice 的行号/列号由 slice 的检索寄存器加上立即数偏移指定。目标 slice 中 Inactive 的元素保持不变。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;MOV&lt;/span&gt; &lt;span class="no"&gt;ZA0H.B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;W0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#imm], P0/M, Z0.B
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;MOVA&lt;/span&gt; &lt;span class="no"&gt;ZA0H.B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;W0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#imm], P0/M, Z0.B
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此指令将向量寄存器 &lt;code&gt;Z0.B&lt;/code&gt; 中的值移动到 &lt;code&gt;ZA0H.B[W0,#imm]&lt;/code&gt; 这个水平 ZA tile slice 中，使用 &lt;code&gt;P0&lt;/code&gt; 作为 predication 寄存器。目标 tile slice 中 Inactive 的元素保持不变。&lt;/p&gt;
&lt;h3 id="75-za-array-vector-loadstore-指令"&gt;
&lt;a href="#75-za-array-vector-loadstore-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.5 ZA array vector load/store 指令
&lt;/h3&gt;&lt;p&gt;SME LDR 指令从内存读取数据到一个 ZA array 向量，SME STR 指令将一个 ZA array 向量中的值存入内存。
这些指令是不带 predication 功能的。它们主要是为了软件的 context switching 时对 ZA storage 进行 save/restore。SME LDR/STR 指令也可以在 Non-streaming SVE 模式下，当 PSTATE.ZA 使能的情况下使用。
例如，下面的 STR 指令的 ZA array 向量是由一个向量选择寄存器 Wv（标量寄存器 W）加上可选的立即数（Wv+Imm）指定。访问内存的地址为：一个标量寄存器作为 base，加上相同的可选立即数偏移乘以当前向量长度 byte 数。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;STR&lt;/span&gt; &lt;span class="no"&gt;ZA&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Wv&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;imm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Xn&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="no"&gt;SP&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;{&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;imm&amp;gt;, MUL VL}]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="76-za-tile-清零指令"&gt;
&lt;a href="#76-za-tile-%e6%b8%85%e9%9b%b6%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.6 ZA tile 清零指令
&lt;/h3&gt;&lt;p&gt;SME ZERO 指令可以清零一组 64-bit ZA tile:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;ZERO&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;mask&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;ZERO 指令可以清零多到 8 个名为 &lt;code&gt;ZA0.D&lt;/code&gt; 到 &lt;code&gt;ZA8.D&lt;/code&gt; 的 ZA tile，那些 tile 要清零由指令中的 mask 指定，剩下的其他 tile 保持不变。&lt;/p&gt;
&lt;p&gt;这条指令也可以在 Non-streaming SVE 模式，当 &lt;code&gt;PSTATE.ZA&lt;/code&gt; 开启的情况下使用。&lt;/p&gt;
&lt;p&gt;如果要清零整个 ZA array, 可以使用一个指令别名，&lt;code&gt;ZERO {ZA}&lt;/code&gt; 。&lt;/p&gt;
&lt;h3 id="77-新的-sve2-指令"&gt;
&lt;a href="#77-%e6%96%b0%e7%9a%84-sve2-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.7 新的 SVE2 指令
&lt;/h3&gt;&lt;p&gt;SME 构架扩展加入了一些新的 SVE2 指令，这些指令也可以在 PE 实现了 SVE2, 处于 Non-streaming SVE 模式时使用。这些指令包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;选择一个 predicate 寄存器或是 all-false 的 Predicate select 指令&lt;/li&gt;
&lt;li&gt;翻转（Reverse）64-bit double word 元素的指令&lt;/li&gt;
&lt;li&gt;有符号/无符号钳位为更小/更大值向量的指令&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;下面介绍以下 Predicate select 指令。&lt;/p&gt;
&lt;h4 id="771-psel-指令"&gt;
&lt;a href="#771-psel-%e6%8c%87%e4%bb%a4" class="header-anchor"&gt;#&lt;/a&gt;
7.7.1 PSEL 指令
&lt;/h4&gt;&lt;p&gt;PSEL 指令选择一个 predicate 寄存器复制到到目标 predicate 寄存器或者将目标 predicate 寄存器设置为全零（all-false），如下所示：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;PSEL&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pd&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Wv&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;imm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果指令中 Pm 寄存器中对应索引位置的元素为 True, 这条指令将 Pn 寄存器的内容放到目标寄存器 Pd 中, 否则设置 Pd 寄存器的值全部为 False。
例如以下指令，假设 W12 为 0：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;PSEL&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P2.B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;W12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#0]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;P2.B[W12 + 0]&lt;/code&gt; ，即 &lt;code&gt;P2.B[0]&lt;/code&gt; 为 False, 因此目标寄存器 P0 被全部设置为 0（all-false），如下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_4401_Picture10_png-1280x960.webp"
alt="SME PSEL" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;现在看看如下指令，仍然假设 W12 为 0 ，但这次立即数偏移量（就是硬编码的偏移量）为 1：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;PSEL&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P2.B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;W12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#1]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;P2.B[W12 + 1]&lt;/code&gt; ，即 &lt;code&gt;P2.B[1]&lt;/code&gt; 为 True, 因此选择将 P1 寄存器的值复制到目标寄存器 P0，如下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-16_0116_Picture11_png-1280x960.webp"
alt="SME PSEL" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h2 id="参考文献"&gt;
&lt;a href="#%e5%8f%82%e8%80%83%e6%96%87%e7%8c%ae" class="header-anchor"&gt;#&lt;/a&gt;
参考文献
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/arm-scalable-matrix-extension-introduction" target="_blank" rel="noopener" &gt;Arm Scalable Matrix Extension (SME) Introduction
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/arm-scalable-matrix-extension-introduction-p2" target="_blank" rel="noopener" &gt;Arm Scalable Matrix Extension (SME) Instructions
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Arm 性能优化：可伸缩向量扩展 SVE</title><link>https://cuterwrite.top/p/arm-sve-for-performance/</link><pubDate>Sun, 11 Aug 2024 02:13:00 +0000</pubDate><guid>https://cuterwrite.top/p/arm-sve-for-performance/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/2024-06-29_117622464_p0_master1200.webp" alt="Featured image of post Arm 性能优化：可伸缩向量扩展 SVE" /&gt;&lt;h2 id="1-sve-介绍"&gt;
&lt;a href="#1-sve-%e4%bb%8b%e7%bb%8d" class="header-anchor"&gt;#&lt;/a&gt;
1. SVE 介绍
&lt;/h2&gt;&lt;p&gt;继固定 128 位向量长度指令集的 Neon 架构扩展之后，Arm 设计了可伸缩向量扩展 (SVE) 作为 AArch64 的下一代 SIMD 扩展。SVE 引入可伸缩概念，允许灵活的向量长度实现，并在 CPU 实现中提供一系列可能的值。向量长度可以从最小 128 位到最大 2048 位不等，以 128 位为增量。&lt;strong&gt;SVE 设计保证相同的应用程序可以在支持 SVE 的不同实现上运行，而无需重新编译代码&lt;/strong&gt;。SVE 提高了该架构对高性能计算 (HPC) 和机器学习 (ML) 应用程序的适用性，这些应用程序需要非常大量的数据处理。SVE2 是 SVE 和 Neon 的超集。SVE2 允许在数据级并行中使用更多功能域。SVE2 继承了 SVE 的概念、向量寄存器和操作原理。SVE 和 SVE2 定义了 32 个可伸缩向量寄存器。芯片合作伙伴可以选择合适的向量长度设计实现，硬件可在 128 位到 2048 位之间（以 128 位为增量）变化。SVE 和 SVE2 的优势在于，只有一个向量指令集使用可伸缩变量。&lt;/p&gt;
&lt;p&gt;SVE 设计理念使开发人员能够编写和构建一次软件，然后在具有各种 SVE 向量长度实现的不同 AArch64 硬件上运行相同的二进制文件。二进制文件的可移植性意味着开发人员不必知道其系统的向量长度实现。消除了重建二进制文件的需求，使软件更容易移植。除了可伸缩向量之外，SVE 和 SVE2 还包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;per-lane predication&lt;/li&gt;
&lt;li&gt;Gather Load/Scatter Store&lt;/li&gt;
&lt;li&gt;推测性向量化&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这些特性有助于在处理大型数据集时对循环进行向量化和优化。&lt;/p&gt;
&lt;p&gt;SVE2 和 SVE 的主要区别在于指令集的功能覆盖范围。SVE 专为 HPC 和 ML 应用而设计。SVE2 扩展了 SVE 指令集，使其能够加速 HPC 和 ML 以外领域的数据处理。SVE2 指令集还可以加速以下应用中使用的常见算法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;计算机视觉&lt;/li&gt;
&lt;li&gt;多媒体&lt;/li&gt;
&lt;li&gt;LTE 基处理&lt;/li&gt;
&lt;li&gt;基因组学&lt;/li&gt;
&lt;li&gt;内存数据库&lt;/li&gt;
&lt;li&gt;Web 服务&lt;/li&gt;
&lt;li&gt;通用软件&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SVE 和 SVE2 都支持收集和处理大量数据。SVE 和 SVE2 不是 Neon 指令集的扩展。相反，SVE 和 SVE2 经过重新设计，以提供比 Neon 更好的数据并行性。但是，SVE 和 SVE2 的硬件逻辑覆盖了 Neon 硬件的实现。当微架构支持 SVE 或 SVE2 时，它也支持 Neon。要使用 SVE 和 SVE2，在该微架构上运行的软件必须首先支持 Neon。&lt;/p&gt;
&lt;h2 id="2-sve-架构基础"&gt;
&lt;a href="#2-sve-%e6%9e%b6%e6%9e%84%e5%9f%ba%e7%a1%80" class="header-anchor"&gt;#&lt;/a&gt;
2. SVE 架构基础
&lt;/h2&gt;&lt;p&gt;本节介绍 SVE 和 SVE2 共享的基本架构特性。与 SVE 一样，SVE2 也基于可扩展向量。除了 Neon 提供的现有寄存器库之外，SVE 和 SVE2 还添加了以下寄存器：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;32 个可伸缩向量寄存器，&lt;code&gt;Z0-Z31&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;16 个可伸缩 Predicate 寄存器，&lt;code&gt;P0-P15&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;1 个 首故障 Predicate 寄存器，&lt;code&gt;FFR&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;可伸缩向量系统控制寄存器, &lt;code&gt;ZCR_ELx&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="21-可伸缩向量寄存器"&gt;
&lt;a href="#21-%e5%8f%af%e4%bc%b8%e7%bc%a9%e5%90%91%e9%87%8f%e5%af%84%e5%ad%98%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
2.1 可伸缩向量寄存器
&lt;/h3&gt;&lt;p&gt;可伸缩向量寄存器 &lt;code&gt;Z0-Z31&lt;/code&gt; 可以在微架构中实现为 128-2048 位。最低的 128 位与 Neon 的固定 128 位向量 &lt;code&gt;V0-V31&lt;/code&gt; 共享。&lt;/p&gt;
&lt;p&gt;下图显示了可伸缩向量寄存器 &lt;code&gt;Z0-Z31&lt;/code&gt;：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_Z-register.webp"
alt="Z 寄存器-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;可伸缩向量寄存器 Z0-Z31&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;可伸缩向量：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可以容纳 64、32、16 和 8 位元素&lt;/li&gt;
&lt;li&gt;支持整数、双精度、单精度和半精度浮点元素&lt;/li&gt;
&lt;li&gt;可以针对每个异常级别（EL）配置向量长度&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="22-可伸缩-predicate-寄存器"&gt;
&lt;a href="#22-%e5%8f%af%e4%bc%b8%e7%bc%a9-predicate-%e5%af%84%e5%ad%98%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
2.2 可伸缩 Predicate 寄存器
&lt;/h3&gt;&lt;p&gt;为了控制哪些活动元素参与运算，Predicate 寄存器（简称为 P 寄存器）在许多 SVE 指令中用作掩码，这也为向量运算提供了灵活性。下图显示了可伸缩 Predicate 寄存器 &lt;code&gt;P0-P15&lt;/code&gt; ：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_Predicate-register.webp"
alt="P 寄存器-2024-08-12" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;可伸缩 Predicate 寄存器 P0-P15&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;P 寄存器通常用作数据操作的位掩码：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;每个 P 寄存器是 Z 寄存器长度的 1/8&lt;/li&gt;
&lt;li&gt;&lt;code&gt;P0-P7&lt;/code&gt; 用于加载、存储和算术运算&lt;/li&gt;
&lt;li&gt;&lt;code&gt;P8-P15&lt;/code&gt; 用于循环管理&lt;/li&gt;
&lt;li&gt;FFR 是一个特殊的 P 寄存器，由 first-fault vector load 指令和 store 指令设置，用于指示每个元素的加载和存储操作的成功情况。FFR 旨在支持推测性内存访问，这使得在许多情况下向量化更容易和更安全。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="23-可伸缩向量系统控制寄存器"&gt;
&lt;a href="#23-%e5%8f%af%e4%bc%b8%e7%bc%a9%e5%90%91%e9%87%8f%e7%b3%bb%e7%bb%9f%e6%8e%a7%e5%88%b6%e5%af%84%e5%ad%98%e5%99%a8" class="header-anchor"&gt;#&lt;/a&gt;
2.3 可伸缩向量系统控制寄存器
&lt;/h3&gt;&lt;p&gt;下图展示了可伸缩向量系统控制寄存器 &lt;code&gt;ZCR_ELx&lt;/code&gt; ：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_ZCR_Elx.webp"
alt="ZCR_Elx-2024-08-12" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;可伸缩向量系统控制寄存器 ZCR_Elx&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;可伸缩向量系统控制寄存器指示 SVE 实现特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ZCR_Elx.LEN&lt;/code&gt; 字段用于当前和较低异常级别的向量长度。&lt;/li&gt;
&lt;li&gt;大多数位当前保留供将来使用。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="24-sve-汇编语法"&gt;
&lt;a href="#24-sve-%e6%b1%87%e7%bc%96%e8%af%ad%e6%b3%95" class="header-anchor"&gt;#&lt;/a&gt;
2.4 SVE 汇编语法
&lt;/h3&gt;&lt;p&gt;SVE 汇编语法格式由操作码、目标寄存器、P 寄存器（如果指令支持 Predicate 掩码）和输入操作数组成。以下指令示例将详细说明此格式。&lt;/p&gt;
&lt;p&gt;示例 1:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;LDFF1D&lt;/span&gt; &lt;span class="err"&gt;{&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zt&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.D&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Xn&lt;/span&gt;&lt;span class="err"&gt;|&lt;/span&gt;&lt;span class="no"&gt;SP&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;LSL&lt;/span&gt; &lt;span class="c1"&gt;#3]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Zt&amp;gt;&lt;/code&gt; 是 Z 寄存器, &lt;code&gt;Z0-Z31&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Zt&amp;gt;&lt;/code&gt;.D 和 &lt;code&gt;&amp;lt;Zm&amp;gt;.D&lt;/code&gt; 指定目标和操作数向量的元素类型，不需要指定元素的数量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Pg&amp;gt;&lt;/code&gt; 是 P 寄存器, &lt;code&gt;P0-P15&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Pg&amp;gt;/Z&lt;/code&gt; 是对 P 寄存器归零。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Zm&amp;gt;&lt;/code&gt; 指定 Gather Load 地址模式的偏移量。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例 2:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;ADD&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zdn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zdn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Zm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;T&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其中：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Pg&amp;gt;/M&lt;/code&gt; 是合并 P 寄存器。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Zdn&amp;gt;&lt;/code&gt; 既是目标寄存器，也是输入操作数之一。指令语法在两个位置都显示 &lt;code&gt;&amp;lt;Zdn&amp;gt;&lt;/code&gt; ，是为了方便起见。在汇编编码中，为了简化，它们只被编码一次。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;示例 3:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;ORRS&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pd&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pg&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pn&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;Pm&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="no"&gt;.B&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;S&lt;/code&gt; 是 P 寄存器条件标志 &lt;code&gt;NZCV&lt;/code&gt; 的新解释。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;lt;Pg&amp;gt;&lt;/code&gt; 控制 P 寄存器在示例操作中充当位掩码。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="25-sve-架构特性"&gt;
&lt;a href="#25-sve-%e6%9e%b6%e6%9e%84%e7%89%b9%e6%80%a7" class="header-anchor"&gt;#&lt;/a&gt;
2.5 SVE 架构特性
&lt;/h3&gt;&lt;p&gt;SVE 包括以下关键架构特性：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;per-lane predication&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了允许对所选元素进行灵活的操作，SVE 引入了 16 个 P 寄存器， &lt;code&gt;P0-P15&lt;/code&gt; ，用于指示对向量活动通道的有效操作。例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;ADD&lt;/span&gt; &lt;span class="no"&gt;Z0.D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Z0.D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Z1.D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;活动元素 &lt;code&gt;Z0&lt;/code&gt; 和 &lt;code&gt;Z1&lt;/code&gt; 相加并将结果放入 &lt;code&gt;Z0&lt;/code&gt; 中，&lt;code&gt;P0&lt;/code&gt; 指示操作数的哪些元素是活动的和非活动的。&lt;code&gt;P0&lt;/code&gt; 后面的 &lt;strong&gt;M&lt;/strong&gt; 表示 Merging ，表示将非活动元素合并，因此 &lt;code&gt;Z0&lt;/code&gt; 的非活动元素在 &lt;code&gt;ADD&lt;/code&gt; 操作后将保持其初始值。如果 &lt;code&gt;P0&lt;/code&gt; 后面是 &lt;strong&gt;Z&lt;/strong&gt; ，则非活动元素将被清零，目标寄存器的非活动元素将在操作后归零。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_Per-lane_Predication.webp"
alt="Per-lane_Predication-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Per-lane predication merging&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;如果使用的是 &lt;strong&gt;\Z&lt;/strong&gt; ，则非活动元素将被清零，目标寄存器的非活动元素将在操作后归零。例如&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;CPY&lt;/span&gt; &lt;span class="no"&gt;Z0.B&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#0xFF
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;表示将有符号整数 0xFF 复制到 &lt;code&gt;Z0&lt;/code&gt; 的活动通道中，而非活动通道将被清零。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_Per-lane_Predicate_Zeroing.webp"
alt="Per-lane_Predicate_Zeroing-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Per-lane predication zeroing&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;blockquote class="alert-blockquote alert-note"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;注释&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;并非所有指令都具有 Predicate 选项。此外，并非所有 Predicate 操作都同时具有合并和清零选项。您必须参考 &lt;a class="link" href="https://developer.arm.com/documentation/ddi0487/latest/t" target="_blank" rel="noopener" &gt;AArch64 SVE Supplement
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
以了解每个指令的规范细节。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Gather Load 和 Scatter Store&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SVE 中的寻址模式允许将向量用作 Gather Load 和 Scatter Store 指令中的基地址和偏移量，这使得能够访问非连续的内存位置。例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;LD1SB&lt;/span&gt; &lt;span class="no"&gt;Z0.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Z1.S&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// 将有符号字节从由 32 位向量基地址 Z1 生成的内存地址 Gather Load 到 Z0 的活动 32 位元素中。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;LD1SB&lt;/span&gt; &lt;span class="no"&gt;Z0.D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;X0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Z1.D&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="c1"&gt;// 将有符号字节从由 64 位标量基地址 X0 加上 Z1.D 中的向量索引生成的内存地址 Gather Load 到 Z0 的活动元素中。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;以下示例显示了加载操作 &lt;code&gt;LD1SB Z0.S, P0/Z, [Z1.S]&lt;/code&gt; ，其中 &lt;code&gt;P0&lt;/code&gt; 包含所有真元素，&lt;code&gt;Z1&lt;/code&gt; 包含分散的地址。加载后，&lt;code&gt;Z0.S&lt;/code&gt; 的每个元素的低位字节将用从分散内存位置获取的数据更新。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_gather-load_and_scatter_store_example.webp"
alt="gather-load_and_scatter_store_example-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Gather-load 与 Scatter-store 示例&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;P 寄存器驱动的循环控制和管理&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;作为 SVE 的一项关键特性，P 寄存器不仅可以灵活地控制向量运算的各个元素，还可以实现 P 寄存器驱动的循环控制。P 寄存器驱动的循环控制和管理使循环控制高效且灵活。此功能通过在 P 寄存器中注册活动和非活动元素索引，消除了处理部分向量的额外循环头和尾的开销。P 寄存器驱动的循环控制和管理意味着，在接下来的循环迭代中，只有活动元素才会执行预期的操作。例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;WHILEL0&lt;/span&gt; &lt;span class="no"&gt;P0.S&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x9&lt;/span&gt; &lt;span class="c1"&gt;// 在 P0 中生成一个谓词，从最低编号的元素开始，当第一个无符号标量操作数 X8 的递增值小于第二个标量操作数 X9 时为真，之后为假，直到最高编号的元素。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;B.FIRST&lt;/span&gt; &lt;span class="no"&gt;Loop_start&lt;/span&gt; &lt;span class="c1"&gt;// B.FIRST（等效于 B.MI）或 B.NFRST（等效于 B.PL）通常用于根据上述指令测试结果进行分支，判断 P0 的第一个元素是真还是假，作为循环的结束或继续条件。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_Predicate-driver_loop_control_and_management_example.webp"
alt="Predicate-driver_loop_control_and_management_example-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;P 寄存器驱动的循环控制和管理示例&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;用于软件管理推测的向量分区&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;推测性加载可能会给传统向量的内存读取带来挑战，&lt;strong&gt;如果在读取过程中某些元素发生错误，则难以逆转加载操作并跟踪哪些元素加载失败&lt;/strong&gt;。Neon 不允许推测性加载。为了允许对向量进行推测性加载（例如 LDRFF），SVE 引入了 first-fault vector load 指令。为了允许向量访问跨越无效页面，SVE 还引入了 FFR 寄存器。&lt;strong&gt;使用 first-fault vector load 指令加载到 SVE 向量时，FFR 寄存器会更新每个元素的加载成功或失败结果&lt;/strong&gt;。当发生加载错误时，FFR 会立即注册相应的元素，将其余元素注册为 0 或 false，并且不会触发异常。通常，RDFFR 指令用于读取 FFR 状态。当第一个元素为假时，RDFFR 指令结束迭代。如果第一个元素为真，RDFFR 指令继续迭代。FFR 的长度与 P 向量相同。可以使用 SETFFR 指令初始化该值。以下示例使用 LDFF1D 从内存中读取数据，FFR 会相应地更新：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;LDFF1D&lt;/span&gt; &lt;span class="no"&gt;Z0.D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;Z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;Z1.D&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#0] // 使用首个故障行为将双字从由向量基地址 Z1 加 0 生成的内存地址收集加载到 Z0 的活动元素中。非活动元素不会读取设备内存或发出故障信号，并在目标向量中设置为零。从有效内存成功加载将 FFR 中的对应元素设置为真。首个故障加载将 FFR 中的对应元素和其余元素设置为假或 0。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_Vector-partioning-for-software-managed-speculation-example.webp"
alt="Vector-partioning-for-software-managed-speculation-example-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;用于软件管理推测的向量分区示例&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;扩展的浮点和水平规约&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了允许在向量中进行高效的归约操作，并满足对精度的不同要求，SVE 增强了浮点和水平归约操作。这些指令可能具有顺序（从低到高）或基于树（成对）的浮点归约顺序，其中操作顺序可能会导致不同的舍入结果。这些操作需要在可重复性和性能之间进行权衡。例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nf"&gt;FADDA&lt;/span&gt; &lt;span class="no"&gt;D0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;P0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;D1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Z2.D&lt;/span&gt; &lt;span class="c1"&gt;// 从源头向量的低位到高位元素进行浮点加严格顺序归约，将结果累积到 SIMD&amp;amp;FP 标量寄存器中。该示例指令将 D1 与 Z2.D 的所有活动元素相加，并将结果存储到标量寄存器 D0 中。向量元素按从低到高的顺序严格处理，标量源 D1 提供初始值。源向量中的非活动元素将被忽略。而 FADDV 将执行递归成对归约，并将结果存储到标量寄存器中。
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_Extended_Floating-poing-and-horizontal-reductions-example.webp"
alt="Extended_Floating-poing-and-horizontal-reductions-example-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;扩展的浮点和水平规约示例&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="3-sve2-新增特性"&gt;
&lt;a href="#3-sve2-%e6%96%b0%e5%a2%9e%e7%89%b9%e6%80%a7" class="header-anchor"&gt;#&lt;/a&gt;
3. SVE2 新增特性
&lt;/h2&gt;&lt;p&gt;本节介绍 SVE2 为 Arm AArch64 架构新增的特性。为了实现可伸缩的性能，SVE2 基于 SVE 构建，允许向量实现高达 2048 位。&lt;/p&gt;
&lt;p&gt;在 SVE2 中，添加了许多复制 Neon 中现有指令的指令，包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;转换后的 Neon 整数运算，例如，带符号绝对差累加 (SAB) 和带符号减半加法 (SHADD)。&lt;/li&gt;
&lt;li&gt;转换后的 Neon 扩展、缩小和成对运算，例如，无符号长加法 - 底部 (UADDLB) 和无符号长加法 - 顶部 (UADDLT)。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;元素处理顺序发生了变化。SVE2 对交错的偶数和奇数元素进行处理，而 Neon 对窄或宽操作的低半部分和高半部分元素进行处理。下图说明了 Neon 和 SVE2 处理之间的区别：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_transformed_neon_widen_narraow_pairwise_operations.webp"
alt="transformed_neon_widen_narraow_pairwise_operations-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;转换后的 Neon 窄或宽操作对比&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;复数操作，例如带旋转的复整数乘加 (CMLA)。&lt;/li&gt;
&lt;li&gt;多精度运算，用于大整数运算和密码学，例如，带进位长加法 - 底部 (ADCLB)、带进位长加法 - 顶部 (ADCLT) 以及 SM4 加密和解密 (SM4E)。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;为了向后兼容，最新架构中需要 Neon 和 VFP。虽然 SVE2 包含 SVE 和 Neon 的一些功能，但 SVE2 并不排除 Neon 在芯片上的存在。&lt;/p&gt;
&lt;p&gt;SVE2 支持针对 HPC 市场以外的新兴应用进行优化，例如，在机器学习 (ML)（UDOT 指令）、计算机视觉（TBL 和 TBX 指令）、基带网络（CADD 和 CMLA 指令）、基因组学（BDEP 和 BEXT 指令）和服务器（MATCH 和 NMATCH 指令）中。&lt;/p&gt;
&lt;p&gt;SVE2 增强了通用处理器大量数据操作的整体性能，而无需其他片外加速器。&lt;/p&gt;
&lt;h2 id="4-使用-sve-编程"&gt;
&lt;a href="#4-%e4%bd%bf%e7%94%a8-sve-%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;#&lt;/a&gt;
4. 使用 SVE 编程
&lt;/h2&gt;&lt;p&gt;本节介绍支持 SVE2 应用程序开发的软件工具和库。本节还介绍了如何为支持 SVE2 的目标开发应用程序，在支持 SVE2 的硬件上运行该应用程序，以及在任何 Armv8-A 硬件上模拟该应用程序。&lt;/p&gt;
&lt;h3 id="41-软件和库支持"&gt;
&lt;a href="#41-%e8%bd%af%e4%bb%b6%e5%92%8c%e5%ba%93%e6%94%af%e6%8c%81" class="header-anchor"&gt;#&lt;/a&gt;
4.1 软件和库支持
&lt;/h3&gt;&lt;p&gt;要构建 SVE 或 SVE2 应用程序，你必须选择支持 SVE 和 SVE2 功能的编译器。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GNU 工具 8.0+ 版本支持 SVE。&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.arm.com/tools-and-software/server-and-hpc/compile/arm-compiler-for-linux" target="_blank" rel="noopener" &gt;Arm Compiler for Linux
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
18.0+ 版本支持 SVE，20.0+ 版本支持 SVE 和 SVE2。&lt;/li&gt;
&lt;li&gt;GNU 和 Arm Compiler for Linux 编译器都支持优化 C/C++/Fortran 代码。&lt;/li&gt;
&lt;li&gt;LLVM（开源 Clang）5 及更高版本包括对 SVE 的支持，9 及更高版本包括对 SVE2 的支持。要了解 LLVM 工具的每个版本支持哪些 SVE 或 SVE2 功能，请参阅 &lt;a class="link" href="https://developer.arm.com/tools-and-software/open-source-software/developer-tools/llvm-toolchain/sve-support" target="_blank" rel="noopener" &gt;LLVM 工具链 SVE 支持页面
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a class="link" href="https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Libraries" target="_blank" rel="noopener" &gt;Arm Performance Libraries
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
针对数学例程进行了高度优化，可以链接到你的应用程序。Arm Performance Libraries 19.3+ 版本支持 SVE 的数学库。&lt;/p&gt;
&lt;p&gt;Arm Compiler for Linux 是 Arm Allinea Studio 的一部分，包含 Arm C/C++ 编译器、Arm Fortran 编译器和 Arm Performance Libraries。&lt;/p&gt;
&lt;h3 id="42-如何使用-sve2-编程"&gt;
&lt;a href="#42-%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8-sve2-%e7%bc%96%e7%a8%8b" class="header-anchor"&gt;#&lt;/a&gt;
4.2 如何使用 SVE2 编程
&lt;/h3&gt;&lt;p&gt;编写或生成 SVE 和 SVE2 代码的方法有多种。在本小节中，我们将探讨其中的一些方法。&lt;/p&gt;
&lt;p&gt;要编写或生成 SVE 和 SVE2 代码，你可以：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;编写 SVE 汇编代码&lt;/li&gt;
&lt;li&gt;使用 SVE 内部函数编程&lt;/li&gt;
&lt;li&gt;自动向量化&lt;/li&gt;
&lt;li&gt;使用 SVE 优化库&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;让我们更详细地了解这四种选择。&lt;/p&gt;
&lt;h4 id="421-编写-sve-汇编代码"&gt;
&lt;a href="#421-%e7%bc%96%e5%86%99-sve-%e6%b1%87%e7%bc%96%e4%bb%a3%e7%a0%81" class="header-anchor"&gt;#&lt;/a&gt;
4.2.1 编写 SVE 汇编代码
&lt;/h4&gt;&lt;p&gt;你可以将 SVE 指令作为内联汇编编写到 C/C++ 代码中，或者作为完整的函数编写到汇编源代码中。例如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;.globl&lt;/span&gt; &lt;span class="no"&gt;subtract_arrays&lt;/span&gt; &lt;span class="c1"&gt;// -- Begin function
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;.p2align&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;.type&lt;/span&gt; &lt;span class="no"&gt;subtract_arrays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;@function&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nl"&gt;subtract_arrays:&lt;/span&gt; &lt;span class="c1"&gt;// @subtract_arrays
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;.cfi_startproc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// %bb.0:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;orr&lt;/span&gt; &lt;span class="no"&gt;w9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;wzr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;#0x400
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;mov&lt;/span&gt; &lt;span class="no"&gt;x8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;xzr&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;whilelo&lt;/span&gt; &lt;span class="no"&gt;p0.s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;xzr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;.LBB0_1:&lt;/span&gt; &lt;span class="c1"&gt;// =&amp;gt;This Inner Loop Header: Depth=1
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;ld1w&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="no"&gt;z0.s&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;p0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;lsl&lt;/span&gt; &lt;span class="c1"&gt;#2]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;ld1w&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="no"&gt;z1.s&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;p0&lt;/span&gt;&lt;span class="err"&gt;/&lt;/span&gt;&lt;span class="no"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;lsl&lt;/span&gt; &lt;span class="c1"&gt;#2]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;sub&lt;/span&gt; &lt;span class="no"&gt;z0.s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;z0.s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;z1.s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;st1w&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="no"&gt;z0.s&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;p0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;x0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;lsl&lt;/span&gt; &lt;span class="c1"&gt;#2]
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;incw&lt;/span&gt; &lt;span class="no"&gt;x8&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;whilelo&lt;/span&gt; &lt;span class="no"&gt;p0.s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;x9&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;b.mi&lt;/span&gt; &lt;span class="no"&gt;.LBB0_1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// %bb.2:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;ret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;.Lfunc_end0:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;.size&lt;/span&gt; &lt;span class="no"&gt;subtract_arrays&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;.Lfunc_end0-subtract_arrays&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;.cfi_endproc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果你混合使用高级语言和汇编语言编写的函数，则必须熟悉针对 SVE 更新的&lt;a class="link" href="https://developer.arm.com/documentation/ihi0036/latest/" target="_blank" rel="noopener" &gt;应用程序二进制接口 (ABI)
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
标准。&lt;a class="link" href="https://developer.arm.com/documentation/ihi0055/latest" target="_blank" rel="noopener" &gt;Arm 架构过程调用标准 (AAPCS)
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
指定了数据类型和寄存器分配，并且与汇编编程最相关。AAPCS 要求：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Z0-Z7&lt;/code&gt; 和 &lt;code&gt;P0-P3 &lt;/code&gt;用于传递可伸缩向量参数和结果。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Z8-Z15&lt;/code&gt; 和 &lt;code&gt;P4-P15&lt;/code&gt; 是被调用者保存的。&lt;/li&gt;
&lt;li&gt;所有其他向量寄存器（&lt;code&gt;Z16-Z31&lt;/code&gt;）都可能被被调用函数破坏，调用函数负责在需要时备份和恢复它们。&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="422-使用-sve-instruction-函数intrinsics"&gt;
&lt;a href="#422-%e4%bd%bf%e7%94%a8-sve-instruction-%e5%87%bd%e6%95%b0intrinsics" class="header-anchor"&gt;#&lt;/a&gt;
4.2.2 使用 SVE instruction 函数（Intrinsics）
&lt;/h4&gt;&lt;p&gt;SVE 内部函数是由编译器支持的函数，可以替换为相应的指令。程序员可以直接在 C 和 C++ 等高级语言中调用指令函数。SVE 的 ACLE（Arm C 语言扩展）定义了哪些 SVE 指令函数可用、它们的参数以及它们的功能。支持 ACLE 的编译器可以在编译期间将内部函数替换为映射的 SVE 指令。要使用 ACLE 内部函数，你必须包含头文件 &lt;code&gt;arm_sve.h&lt;/code&gt;，其中包含可在 C/C++ 中使用的向量类型和指令函数（针对 SVE）列表。每种数据类型都描述了向量中元素的大小和数据类型：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svint8_t svuint8_t&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svint16_t svuint16_t svfloat16_t&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svint32_t svuint32_t svfloat32_t&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svint64_t svuint64_t svfloat64_t&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;例如，&lt;code&gt;svint64_t&lt;/code&gt; 表示 64 位有符号整数向量，&lt;code&gt;svfloat16_t&lt;/code&gt; 表示半精度浮点数向量。&lt;/p&gt;
&lt;p&gt;以下示例 C 代码已使用 SVE 内部函数进行了手动优化：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// intrinsic_example.c
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;arm_sve.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;svuint64_t&lt;/span&gt; &lt;span class="nf"&gt;uaddlb_array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;svuint32_t&lt;/span&gt; &lt;span class="n"&gt;Zs1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;svuint32_t&lt;/span&gt; &lt;span class="n"&gt;Zs2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// widening add of even elements
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svuint64_t&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svaddlb&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Zs1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Zs2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;包含 &lt;code&gt;arm_sve.h&lt;/code&gt; 头文件的源代码可以使用 SVE 向量类型，就像数据类型可以用于变量声明和函数参数一样。要使用 Arm C/C++ 编译器编译代码并以支持 SVE 的 Armv8-A 架构为目标，请使用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;armclang -O3 -S -march&lt;span class="o"&gt;=&lt;/span&gt;armv8-a+sve2 -o intrinsic_example.s intrinsic_example.c
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;此命令生成以下汇编代码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-asm" data-lang="asm"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// instrinsic_example.s
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;uaddlb_array:&lt;/span&gt; &lt;span class="c1"&gt;// @uaddlb_array
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="na"&gt;.cfi_startproc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// %bb.0:
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;uaddlb&lt;/span&gt; &lt;span class="no"&gt;z0.d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;z0.s&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;z1.s&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;ret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="423-自动向量化"&gt;
&lt;a href="#423-%e8%87%aa%e5%8a%a8%e5%90%91%e9%87%8f%e5%8c%96" class="header-anchor"&gt;#&lt;/a&gt;
4.2.3 自动向量化
&lt;/h4&gt;&lt;p&gt;C/C++/Fortran 编译器（例如，适用于 Arm 平台的原生 &lt;a class="link" href="https://developer.arm.com/tools-and-software/server-and-hpc/compile/arm-compiler-for-linux" target="_blank" rel="noopener" &gt;Arm Compiler for Linux
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
和 GNU 编译器）支持使用 SVE 或 SVE2 指令对 C、C++ 和 Fortran 循环进行向量化。要生成 SVE 或 SVE2 代码，请选择适当的编译器选项。例如，使用 armclang 启用 SVE2 优化的一个选项是 &lt;code&gt;-march=armv8-a+sve2&lt;/code&gt; 。如果要使用 SVE 版本的库，请将 &lt;code&gt;-march=armv8-a+sve2&lt;/code&gt; 与 &lt;code&gt;-armpl=sve&lt;/code&gt; 结合使用。&lt;/p&gt;
&lt;h4 id="424-使用-svesve2-优化库"&gt;
&lt;a href="#424-%e4%bd%bf%e7%94%a8-svesve2-%e4%bc%98%e5%8c%96%e5%ba%93" class="header-anchor"&gt;#&lt;/a&gt;
4.2.4 使用 SVE/SVE2 优化库
&lt;/h4&gt;&lt;p&gt;使用针对 SVE/SVE2 高度优化的库，例如 &lt;a class="link" href="https://developer.arm.com/Tools%20and%20Software/Arm%20Performance%20Libraries" target="_blank" rel="noopener" &gt;Arm Performance Libraries
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
和 Arm Compute Libraries。Arm Performance Libraries 包含针对 BLAS、LAPACK、FFT、稀疏线性代数和 libamath 优化的数学函数的高度优化实现。要能够链接任何 Arm Performance Libraries 函数，您必须安装 Arm Allinea Studio 并在代码中包含 armpl.h。要使用 Arm Compiler for Linux 和 Arm Performance Libraries 构建应用程序，您必须在命令行中指定 &lt;code&gt;-armpl=&amp;lt;arg&amp;gt;&lt;/code&gt; 。如果您使用 GNU 工具，则必须使用 &lt;code&gt;-L&amp;lt;armpl_install_dir&amp;gt;/lib&lt;/code&gt; 将 Arm Performance Libraries 安装路径包含在链接器命令行中，并指定与 Arm Compiler for Linux &lt;code&gt;-armpl=&amp;lt;arg&amp;gt;&lt;/code&gt; 选项等效的 GNU 选项，即 &lt;code&gt;-larmpl_lp64&lt;/code&gt; 。有关更多信息，请参阅 Arm Performance Libraries 入门指南。&lt;/p&gt;
&lt;h3 id="43-如何运行-svesve2-程序"&gt;
&lt;a href="#43-%e5%a6%82%e4%bd%95%e8%bf%90%e8%a1%8c-svesve2-%e7%a8%8b%e5%ba%8f" class="header-anchor"&gt;#&lt;/a&gt;
4.3 如何运行 SVE/SVE2 程序
&lt;/h3&gt;&lt;p&gt;如果您无法访问 SVE 硬件，则可以使用模型或仿真器来运行代码。你可以选择以下几种模型和仿真器：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;QEMU&lt;/strong&gt;： 交叉编译和原生模型，支持在具有 SVE 的 Arm AArch64 平台上进行建模。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Fast Models&lt;/strong&gt;： 跨平台模型，支持在基于 x86 的主机上运行的具有 SVE 的 Arm AArch64 平台进行建模。支持 SVE2 的 架构包络模型 AEM 只对主要合作伙伴可用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Arm Instruction Emulator (ArmIE)&lt;/strong&gt;： 直接在 Arm 平台上运行。支持 SVE，并从 19.2+ 版本开始支持 SVE2。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="5-acle-intrinsics"&gt;
&lt;a href="#5-acle-intrinsics" class="header-anchor"&gt;#&lt;/a&gt;
5. ACLE Intrinsics
&lt;/h2&gt;&lt;h3 id="51-acle-简介"&gt;
&lt;a href="#51-acle-%e7%ae%80%e4%bb%8b" class="header-anchor"&gt;#&lt;/a&gt;
5.1 ACLE 简介
&lt;/h3&gt;&lt;p&gt;ACLE (Arm C 语言扩展) 是在 C 和 C++ 代码中利用内部函数和其他特性来支持 Arm 的功能。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;ACLE (ARM C 语言扩展) 通过特定于 Arm 的特性扩展了 C/C++ 语言。
&lt;ul&gt;
&lt;li&gt;预定义宏：&lt;code&gt;__ARM_ARCH_ISA_A64&lt;/code&gt; 、 &lt;code&gt;__ARM_BIG_ENDIAN&lt;/code&gt; 等。&lt;/li&gt;
&lt;li&gt;内部函数：&lt;code&gt;__clz(uint32_t x)&lt;/code&gt; 、 &lt;code&gt;__cls(uint32_t x)&lt;/code&gt; 等。&lt;/li&gt;
&lt;li&gt;数据类型：SVE、NEON 和 FP16 数据类型。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;用于 SVE 的 ACLE 支持使用 ACLE 进行可变长度向量 (VLA) 编程。
&lt;ul&gt;
&lt;li&gt;几乎每个 SVE 指令都有一个对应的内部函数。&lt;/li&gt;
&lt;li&gt;数据类型用于表示 SVE 内部函数所使用的无大小向量。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;适用于以下用户的场景：
&lt;ul&gt;
&lt;li&gt;希望手动调整 SVE 代码的用户。&lt;/li&gt;
&lt;li&gt;希望适配或手动优化应用程序和库的用户。&lt;/li&gt;
&lt;li&gt;需要对 Arm 目标进行底层访问的用户。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="52-如何使用-acle"&gt;
&lt;a href="#52-%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8-acle" class="header-anchor"&gt;#&lt;/a&gt;
5.2 如何使用 ACLE
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;引入头文件
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;arm_acle.h&lt;/code&gt; ：核心 ACLE&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arm_fp16.h&lt;/code&gt; ：添加 FP16 数据类型。
&lt;ul&gt;
&lt;li&gt;目标平台需支持 FP16，即 &lt;code&gt;march=armv8-a+fp16&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arm_neon.h&lt;/code&gt; ：添加 NEON Intrinsics 和数据类型。
&lt;ul&gt;
&lt;li&gt;目标平台需支持 NEON，即 &lt;code&gt;march=armv8-a+simd&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;code&gt;arm_sve.h&lt;/code&gt; ：添加 SVE Intrinsics 和数据类型。
&lt;ul&gt;
&lt;li&gt;目标平台需支持 SVE，即 &lt;code&gt;march=armv8-a+sve&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="53-sve-acle"&gt;
&lt;a href="#53-sve-acle" class="header-anchor"&gt;#&lt;/a&gt;
5.3 SVE ACLE
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;首先需要做的是引入头文件&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;arm_sve.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;VLA 数据类型
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svfloat64_t&lt;/code&gt;, &lt;code&gt;svfloat16_t&lt;/code&gt;, &lt;code&gt;svuint32_t&lt;/code&gt; 等。&lt;/li&gt;
&lt;li&gt;命名规则：&lt;code&gt;sv&amp;lt;datatype&amp;gt;&amp;lt;datasize&amp;gt;_t&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Predication
&lt;ul&gt;
&lt;li&gt;合并：&lt;code&gt;_m&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;置零：&lt;code&gt;_z&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;不确定：&lt;code&gt;_x&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;P 寄存器的数据类型：&lt;code&gt;svbool_t&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;使用泛型做函数重载，比如函数 &lt;code&gt;svadd&lt;/code&gt; 会根据参数类型自动选择对应的函数。&lt;/li&gt;
&lt;li&gt;函数命名规则：&lt;code&gt;svbase[disambiguator][type0][type1]...[predication]&lt;/code&gt;
&lt;ul&gt;
&lt;li&gt;base 指的是基本操作，比如 &lt;code&gt;add&lt;/code&gt;、&lt;code&gt;mul&lt;/code&gt;、&lt;code&gt;sub&lt;/code&gt; 等。&lt;/li&gt;
&lt;li&gt;disambiguator 用于区分相同基本操作的不同变体。&lt;/li&gt;
&lt;li&gt;typeN 指定了向量和 P 寄存器的类型。&lt;/li&gt;
&lt;li&gt;predication 指定了非活动元素的处理方式。&lt;/li&gt;
&lt;li&gt;例如： &lt;code&gt;svfloat64_t svld1_f64&lt;/code&gt;, &lt;code&gt;svbool_t svwhilelt_b8&lt;/code&gt;, &lt;code&gt;svuint32_t svmla_u32_z&lt;/code&gt;, &lt;code&gt;svuint32_t svmla_u32_m&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="54-sve-常用-intrinsics"&gt;
&lt;a href="#54-sve-%e5%b8%b8%e7%94%a8-intrinsics" class="header-anchor"&gt;#&lt;/a&gt;
5.4 SVE 常用 Intrinsics
&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;Predicate
&lt;ul&gt;
&lt;li&gt;Predicate 是一个 bool 类型的向量，用于控制计算过程中向量中对应位置是否参与运算&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svbool_t pg = svwhilelt_b32(i, num)&lt;/code&gt; 产生 (i, i + 1, i + 2, &amp;hellip;, i + vl - 1) &amp;lt; num 的 predicate&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svbool_t pg = svptrue_b32()&lt;/code&gt; 产生一个全为 true 的 predicate&lt;/li&gt;
&lt;li&gt;其中，b32 对应处理 32 位数据（int/float），此外还有 b8, b16, b64 对应的 intrinsic&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;内存数据存取
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svld1(pg, *base)&lt;/code&gt;： 从地址 base 中加载连续向量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svst1(pg, *base, vec)&lt;/code&gt;： 将向量 vec 存储到地址 base 中。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svld1_gather_index(pg, *base, vec_index)&lt;/code&gt;： 从地址 base 中加载向量索引对应的数据。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svst1_scatter_index(pg, *base, vec_index, vec)&lt;/code&gt;： 将向量 vec 中数据存储到向量索引对应的位置。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;基础计算
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svadd_z(pg, sv_vec1, sv_vec2)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svadd_m(pg, sv_vec1, sv_vec2)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svadd_x(pg, sv_vec1, sv_vec2)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svadd_x(pg, sv_vec1, x)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;其中，&lt;code&gt;_z&lt;/code&gt; 表示将 pg 为 false 的位置置零，&lt;code&gt;_m&lt;/code&gt; 表示保留原值，&lt;code&gt;_x&lt;/code&gt; 表示不确定（什么值都有可能）。&lt;/li&gt;
&lt;li&gt;第二个操作数可以为标量数据。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svmul&lt;/code&gt;, &lt;code&gt;svsub&lt;/code&gt;, &lt;code&gt;svsubr&lt;/code&gt;, &lt;code&gt;svdiv&lt;/code&gt;, &lt;code&gt;svdivr&lt;/code&gt;：其中，&lt;code&gt;svsubr&lt;/code&gt; 相比 &lt;code&gt;svsub&lt;/code&gt; 交换了减数与被减数的位置。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;其它
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svdup_f64(double x)&lt;/code&gt;： 生成一个所有元素都为 x 的向量。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svcntd()&lt;/code&gt;：返回 64-bit 数据的向量长度：&lt;code&gt;svcntb&lt;/code&gt; 对应 8 位， &lt;code&gt;svcnth&lt;/code&gt; 对应 16 位，&lt;code&gt;svcntw&lt;/code&gt; 对应 32 位。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="55-sve-结构体-intrinsics"&gt;
&lt;a href="#55-sve-%e7%bb%93%e6%9e%84%e4%bd%93-intrinsics" class="header-anchor"&gt;#&lt;/a&gt;
5.5 SVE 结构体 Intrinsics
&lt;/h3&gt;&lt;p&gt;对应结构体数据，SVE 提供了一些特殊的 Intrinsics，比如：&lt;code&gt;svld3&lt;/code&gt;, &lt;code&gt;svget3&lt;/code&gt;, &lt;code&gt;svset3&lt;/code&gt;, &lt;code&gt;svst3&lt;/code&gt; 等。这些 Intrinsics 用于处理结构体数据。&lt;/p&gt;
&lt;p&gt;例如，对于粒子结构体：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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="n"&gt;Particle&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;可以使用 &lt;code&gt;svld3&lt;/code&gt; 加载结构体中全部的数据为 3 个向量的组，然后使用 &lt;code&gt;svget3&lt;/code&gt; 从 3 个向量的组中提取一个向量, index 的值为 0, 1, 2 分别对应 x, y, z。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;Particle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;ps&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;2.2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// 初始化部分省略
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&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="mi"&gt;0&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;num&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;+=&lt;/span&gt; &lt;span class="nf"&gt;svcntw&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svbool_t&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svwhilelt_b32&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="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat32x3_t&lt;/span&gt; &lt;span class="n"&gt;sv_ps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svld3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ps&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat32_t&lt;/span&gt; &lt;span class="n"&gt;sv_ps_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svget3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sv_ps&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat32_t&lt;/span&gt; &lt;span class="n"&gt;sv_ps_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svget3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sv_ps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;// 执行计算
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sv_ps_x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svmul_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sv_ps_x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sv_ps_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svmul_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sv_ps_y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;factor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//保存结果
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sv_ps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svset3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sv_ps&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;sv_ps_x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sv_ps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svset3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sv_ps&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sv_ps_y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;svst3&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;float32_t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;ps&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="n"&gt;sv_ps&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svld3(pg, *base)&lt;/code&gt;： 加载结构体中全部的数据为 3 个向量的组；其中，base 是 3 个元素结构体数组的地址。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svget3(tuple, index)&lt;/code&gt;： 从 3 个向量的组中提取一个向量；index 的值为 0、1 或 2。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svset3(tuple, index, vec)&lt;/code&gt;： 设置 3 个向量的组中的一个向量；index 的值为 0、1 或 2。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svst3(pg, *base, vec)&lt;/code&gt;： 将 3 个向量的组存储到结构体中；其中，base 是 3 个元素结构体数组的地址。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="56-sve-条件选择"&gt;
&lt;a href="#56-sve-%e6%9d%a1%e4%bb%b6%e9%80%89%e6%8b%a9" class="header-anchor"&gt;#&lt;/a&gt;
5.6 SVE 条件选择
&lt;/h3&gt;&lt;p&gt;SVE 中提供了 &lt;code&gt;svcmplt&lt;/code&gt;、&lt;code&gt;svcompact&lt;/code&gt;、&lt;code&gt;svcntp_b32&lt;/code&gt; 等方法，可以根据条件选择保留向量中的元素。&lt;/p&gt;
&lt;p&gt;例如，对于无向量化的代码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&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="mi"&gt;0&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;num&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;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;provided&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&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;tmp&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;maxSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;该代码的作用是从 provided 数组中选择小于 mark 的元素，存储到 selected 数组中，直到 selected 数组满。&lt;/p&gt;
&lt;p&gt;用 SVE Intrinsic 改写：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&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="mi"&gt;0&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;num&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;+=&lt;/span&gt; &lt;span class="nf"&gt;svcntw&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svbool_t&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svwhilelt_b32&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="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat32_t&lt;/span&gt; &lt;span class="n"&gt;sv_tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svld1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;provided&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svbool_t&lt;/span&gt; &lt;span class="n"&gt;pg_sel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svcmplt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sv_tmp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mark&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;sv_tmp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svcompact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg_sel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sv_tmp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;svst1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;selected&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;count&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;sv_tmp&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;svcntp_b32&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pg_sel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&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;count&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;maxSize&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svcmplt(pg, vec1, vec2)&lt;/code&gt; ：比较两个向量的大小，返回一个 predicate，表示 vec1 中小于 vec2 的位置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svcompact(pg, sv_tmp)&lt;/code&gt; ：压缩向量，将 pg 为 active 的数据按序移动到向量低位，其余位置置零。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;svcntp_b32(pg, pg2)&lt;/code&gt; ：返回 pg2 中 active 的元素个数&lt;/li&gt;
&lt;li&gt;这段代码先将 provided 数组中的数据加载到 sv_tmp 中，然后使用 &lt;code&gt;svcmplt&lt;/code&gt; 生成一个 predicate，表示小于 mark 的位置。接着使用 &lt;code&gt;svcompact&lt;/code&gt; 压缩 sv_tmp，得到小于 mark 的数据，再通过 &lt;code&gt;svst1&lt;/code&gt; 存储到 selected 数组中。最后，使用 &lt;code&gt;svcntp_b32&lt;/code&gt; 统计 active 的元素个数，更新 count。&lt;/li&gt;
&lt;/ul&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_compact.webp"
alt="compact-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;svcompact 示意图（256-bit 向量）&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;由于进行了 compact 操作，所以 selected 数组从 count 位置连续存储新的小于 mark 的数据，剩下的位置被置零。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-08-13_svst1.webp"
alt="svst1-2024-08-13" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;svst1 示意图（256-bit 向量）&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3 id="57-sve-向量化循环交织"&gt;
&lt;a href="#57-sve-%e5%90%91%e9%87%8f%e5%8c%96%e5%be%aa%e7%8e%af%e4%ba%a4%e7%bb%87" class="header-anchor"&gt;#&lt;/a&gt;
5.7 SVE 向量化循环交织
&lt;/h3&gt;&lt;p&gt;SVE Intrinsic 实现的向量化循环交织，相比编译器自动向量化能大大减少读取向量的次数。&lt;/p&gt;
&lt;p&gt;例如，对于无向量化的代码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;outerLen&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&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;m2index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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;m1index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m2index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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;m0index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m1index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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;p1index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m0index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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;p2index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;p1index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&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="mi"&gt;0&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;innerLen&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;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m0index&lt;/span&gt; &lt;span class="o"&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;m2factor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m2index&lt;/span&gt; &lt;span class="o"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m1factor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m1index&lt;/span&gt; &lt;span class="o"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;m0factor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m0index&lt;/span&gt; &lt;span class="o"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p1factor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p1index&lt;/span&gt; &lt;span class="o"&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;p2factor&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;p2index&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;编译器对该代码进行自动向量化后，每次迭代需读取五次不同向量的数据，效率较低。&lt;/p&gt;
&lt;p&gt;用 SVE Intrinsic 改写：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-c" data-lang="c"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&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="mi"&gt;0&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;innerLen&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;+=&lt;/span&gt; &lt;span class="nf"&gt;svcntd&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svbool_t&lt;/span&gt; &lt;span class="n"&gt;pg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svwhilelt_b32&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="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&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;dataIndex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat64_t&lt;/span&gt; &lt;span class="n"&gt;jm2Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svld1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dataIndex&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dataIndex&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat64_t&lt;/span&gt; &lt;span class="n"&gt;jm1Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svld1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dataIndex&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dataIndex&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat64_t&lt;/span&gt; &lt;span class="n"&gt;jm0Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svld1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dataIndex&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dataIndex&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat64_t&lt;/span&gt; &lt;span class="n"&gt;jp1Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svld1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dataIndex&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;outerLen&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat64_t&lt;/span&gt; &lt;span class="n"&gt;jp2Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svld1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;field&lt;/span&gt;&lt;span class="p"&gt;[(&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kt"&gt;svfloat64_t&lt;/span&gt; &lt;span class="n"&gt;svRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svmul_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jm2Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m2factor&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;svRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svmad_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jm1Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m1factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;svRes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;svRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svmad_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jm0Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;m0factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;svRes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;svRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svmad_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jp1Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p1factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;svRes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;svRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;svmad_x&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;jp2Field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;p2factor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;svRes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nf"&gt;svst1&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;innerLen&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;svRes&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jm2Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jm1Field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jm1Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jm0Field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jm0Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jp1Field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;jp1Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;jp2Field&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&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&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;svmad_x(pg, vec1, vec2, vec3)&lt;/code&gt; ：计算 vec1 * vec2 + vec3，返回一个向量。&lt;/li&gt;
&lt;li&gt;这段代码每次迭代只需读取一个向量，大大减少向量读取的次数。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考文献"&gt;
&lt;a href="#%e5%8f%82%e8%80%83%e6%96%87%e7%8c%ae" class="header-anchor"&gt;#&lt;/a&gt;
参考文献
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;a class="link" href="https://developer.arm.com/-/media/Arm%20Developer%20Community/PDF/102340_0001_02_en_introduction-to-sve2.pdf?revision=b208e56b-6569-4ae2-b6f3-cd7d5d1ecac3" target="_blank" rel="noopener" &gt;Introduction to SVE2
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://www.stonybrook.edu/commcms/ookami/support/_docs/5%20-%20Advanced%20SVE.pdf" target="_blank" rel="noopener" &gt;SVE Deep Dive
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://arm-software.github.io/acle/main/acle.html" target="_blank" rel="noopener" &gt;Arm C Language Extensions
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;</description></item><item><title>LLM 生态介绍：从模型微调到应用落地</title><link>https://cuterwrite.top/p/llm-ecosystem/</link><pubDate>Fri, 05 Jul 2024 22:46:00 +0000</pubDate><guid>https://cuterwrite.top/p/llm-ecosystem/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/2024-06-29_119269220_p0_master1200.webp" alt="Featured image of post LLM 生态介绍：从模型微调到应用落地" /&gt;&lt;h2 id="模型微调"&gt;
&lt;a href="#%e6%a8%a1%e5%9e%8b%e5%be%ae%e8%b0%83" class="header-anchor"&gt;#&lt;/a&gt;
模型微调
&lt;/h2&gt;&lt;p&gt;预训练的 LLM 通常具备广泛的知识，但要使其在特定任务上表现出色，微调是必不可少的。以下是一些常用的 LLM 微调工具：&lt;/p&gt;
&lt;h3 id="axolotl"&gt;
&lt;a href="#axolotl" class="header-anchor"&gt;#&lt;/a&gt;
Axolotl
&lt;/h3&gt;
&lt;a href="https://github.com/OpenAccess-AI-Collective/axolotl" target="_blank" class="card-github fetch-waiting no-styling"
repo="OpenAccess-AI-Collective/axolotl" id="repo-bxBm0hvkmYI0kHkB-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-bxBm0hvkmYI0kHkB-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;OpenAccess-AI-Collective&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;axolotl&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-bxBm0hvkmYI0kHkB-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-bxBm0hvkmYI0kHkB-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-bxBm0hvkmYI0kHkB-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-bxBm0hvkmYI0kHkB-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-bxBm0hvkmYI0kHkB-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-bxBm0hvkmYI0kHkB-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/OpenAccess-AI-Collective\/axolotl', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-bxBm0hvkmYI0kHkB-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-bxBm0hvkmYI0kHkB-language').innerText = data.language;
document.getElementById('repo-bxBm0hvkmYI0kHkB-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-bxBm0hvkmYI0kHkB-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-bxBm0hvkmYI0kHkB-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-bxBm0hvkmYI0kHkB-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-bxBm0hvkmYI0kHkB-license').classList.add = "no-license"
};
document.getElementById('repo-bxBm0hvkmYI0kHkB-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for OpenAccess-AI-Collective\/axolotl.")
}).catch(err =&gt; {
const c = document.getElementById('repo-bxBm0hvkmYI0kHkB-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for OpenAccess-AI-Collective\/axolotl.")
})
&lt;/script&gt;
&lt;p&gt;Axolotl 是一款旨在简化各种人工智能模型微调的工具，支持多种配置和架构。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;训练各种 Huggingface 模型，如 llama、pythia、falcon、mpt&lt;/li&gt;
&lt;li&gt;支持 fullfinetune、lora、qlora、relora 和 gptq&lt;/li&gt;
&lt;li&gt;使用简单的 yaml 文件或 CLI 重写功能自定义配置&lt;/li&gt;
&lt;li&gt;加载不同的数据集格式，使用自定义格式，或自带标记化数据集&lt;/li&gt;
&lt;li&gt;与 xformer、闪存关注、绳索缩放和多重包装集成&lt;/li&gt;
&lt;li&gt;可通过 FSDP 或 Deepspeed 与单 GPU 或多 GPU 协同工作&lt;/li&gt;
&lt;li&gt;使用 Docker 在本地或云端轻松运行&lt;/li&gt;
&lt;li&gt;将结果和可选的检查点记录到 wandb 或 mlflow 中&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;快速入门：&lt;/strong&gt;
要求： Python &amp;gt;=3.10 和 Pytorch &amp;gt;=2.1.1&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/OpenAccess-AI-Collective/axolotl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; axolotl
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip3 install packaging ninja
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip3 install -e &lt;span class="s1"&gt;&amp;#39;.[flash-attn,deepspeed]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;strong&gt;使用方法：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# preprocess datasets - optional but recommended&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;CUDA_VISIBLE_DEVICES&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt; python -m axolotl.cli.preprocess examples/openllama-3b/lora.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# finetune lora&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;accelerate launch -m axolotl.cli.train examples/openllama-3b/lora.yml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# inference&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;accelerate launch -m axolotl.cli.inference examples/openllama-3b/lora.yml &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --lora_model_dir&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./outputs/lora-out&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# gradio&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;accelerate launch -m axolotl.cli.inference examples/openllama-3b/lora.yml &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --lora_model_dir&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;./outputs/lora-out&amp;#34;&lt;/span&gt; --gradio
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# remote yaml files - the yaml config can be hosted on a public URL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# Note: the yaml config must directly link to the **raw** yaml&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;accelerate launch -m axolotl.cli.train https://raw.githubusercontent.com/OpenAccess-AI-Collective/axolotl/main/examples/openllama-3b/lora.yml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;其它详细信息，请访问 &lt;a class="link" href="https://github.com/OpenAccess-AI-Collective/axolotl" target="_blank" rel="noopener" &gt;Axolotl
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
项目主页。&lt;/p&gt;
&lt;h3 id="llama-factory"&gt;
&lt;a href="#llama-factory" class="header-anchor"&gt;#&lt;/a&gt;
Llama-Factory
&lt;/h3&gt;&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-07-07_llama-factory-logo.webp"
alt="Llama Factory Logo" width="80%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;a href="https://github.com/hiyouga/LLaMA-Factory" target="_blank" class="card-github fetch-waiting no-styling"
repo="hiyouga/LLaMA-Factory" id="repo-y7xyTbdCs9JQ5InD-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-y7xyTbdCs9JQ5InD-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;hiyouga&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;LLaMA-Factory&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-y7xyTbdCs9JQ5InD-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-y7xyTbdCs9JQ5InD-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-y7xyTbdCs9JQ5InD-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-y7xyTbdCs9JQ5InD-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-y7xyTbdCs9JQ5InD-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-y7xyTbdCs9JQ5InD-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/hiyouga\/LLaMA-Factory', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-y7xyTbdCs9JQ5InD-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-y7xyTbdCs9JQ5InD-language').innerText = data.language;
document.getElementById('repo-y7xyTbdCs9JQ5InD-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-y7xyTbdCs9JQ5InD-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-y7xyTbdCs9JQ5InD-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-y7xyTbdCs9JQ5InD-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-y7xyTbdCs9JQ5InD-license').classList.add = "no-license"
};
document.getElementById('repo-y7xyTbdCs9JQ5InD-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for hiyouga\/LLaMA-Factory.")
}).catch(err =&gt; {
const c = document.getElementById('repo-y7xyTbdCs9JQ5InD-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for hiyouga\/LLaMA-Factory.")
})
&lt;/script&gt;
&lt;p&gt;Llama-Factory 是 Meta 推出的，专注于 Llama 模型微调的框架。它构建于 PyTorch 生态之上，并提供高效的训练和评估工具。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多种模型&lt;/strong&gt;：LLaMA、LLaVA、Mistral、Mixtral-MoE、Qwen、Yi、Gemma、Baichuan、ChatGLM、Phi 等等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;集成方法&lt;/strong&gt;：（增量）预训练、（多模态）指令监督微调、奖励模型训练、PPO 训练、DPO 训练、KTO 训练、ORPO 训练等等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多种精度&lt;/strong&gt;：16 比特全参数微调、冻结微调、LoRA 微调和基于 AQLM/AWQ/GPTQ/LLM.int8/HQQ/EETQ 的 2/3/4/5/6/8 比特 QLoRA 微调。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;先进算法&lt;/strong&gt;：GaLore、BAdam、DoRA、LongLoRA、LLaMA Pro、Mixture-of-Depths、LoRA+、LoftQ、PiSSA 和 Agent 微调。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实用技巧&lt;/strong&gt;：FlashAttention-2、Unsloth、RoPE scaling、NEFTune 和 rsLoRA。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;实验监控&lt;/strong&gt;：LlamaBoard、TensorBoard、Wandb、MLflow 等等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;极速推理&lt;/strong&gt;：基于 vLLM 的 OpenAI 风格 API、浏览器界面和命令行接口。&lt;/li&gt;
&lt;/ul&gt;
&lt;link href="https://web.sdk.qcloud.com/player/tcplayer/release/v4.2.1/tcplayer.min.css" rel="stylesheet"&gt;
&lt;script src="https://web.sdk.qcloud.com/player/tcplayer/release/v4.2.1/libs/hls.min.0.13.2m.js"&gt;&lt;/script&gt;
&lt;script src="https://web.sdk.qcloud.com/player/tcplayer/release/v4.2.1/tcplayer.v4.2.1.min.js"&gt;&lt;/script&gt;
&lt;style&gt;
.tcplayer {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
border: 0;
}
&lt;/style&gt;
&lt;div class="video-wrapper"&gt;
&lt;video
id="player-container-id"
preload="auto"
width="100%"
height="100%"
playsinline
webkit-playsinline&gt;
&lt;/video&gt;
&lt;/div&gt;
&lt;script&gt;
var tcplayer = TCPlayer("player-container-id", {
reportable: false,
poster: "",
});
tcplayer.src('https:\/\/cloud.cuterwrite.top\/img\/2024-07-07_309488092-ec36a9dd-37f4-4f72-81bd-d76c6d0a6594_output.mp4');
&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;性能指标&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;与 ChatGLM 官方的 &lt;a class="link" href="https://github.com/THUDM/ChatGLM2-6B/tree/main/ptuning" target="_blank" rel="noopener" &gt;P-Tuning
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
微调相比，LLaMA Factory 的 LoRA 微调提供了 &lt;strong&gt;3.7 倍&lt;/strong&gt;的加速比，同时在广告文案生成任务上取得了更高的 Rouge 分数。结合 4 比特量化技术，LLaMA Factory 的 QLoRA 微调进一步降低了 GPU 显存消耗。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-07-07_benchmark.webp"
alt="Performance" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;details&gt;
&lt;summary&gt;变量定义&lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Training Speed&lt;/strong&gt;: 训练阶段每秒处理的样本数量。（批处理大小=4，截断长度=1024）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rouge Score&lt;/strong&gt;: &lt;a class="link" href="https://aclanthology.org/D19-1321.pdf" target="_blank" rel="noopener" &gt;广告文案生成
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
任务验证集上的 Rouge-2 分数。（批处理大小=4，截断长度=1024）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GPU Memory&lt;/strong&gt;: 4 比特量化训练的 GPU 显存峰值。（批处理大小=1，截断长度=1024）&lt;/li&gt;
&lt;li&gt;我们在 ChatGLM 的 P-Tuning 中采用 &lt;code&gt;pre_seq_len=128&lt;/code&gt;，在 LLaMA Factory 的 LoRA 微调中采用 &lt;code&gt;lora_rank=32&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;p&gt;&lt;strong&gt;快速入门&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone --depth &lt;span class="m"&gt;1&lt;/span&gt; https://github.com/hiyouga/LLaMA-Factory.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; LLaMA-Factory
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install -e &lt;span class="s2"&gt;&amp;#34;.[torch,metrics]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;可选的额外依赖项：torch、torch-npu、metrics、deepspeed、bitsandbytes、hqq、eetq、gptq、awq、aqlm、vllm、galore、badam、qwen、modelscope、quality&lt;/p&gt;
&lt;blockquote class="alert-blockquote alert-tip"&gt;
&lt;p class="alert-heading"&gt;
&lt;svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16"&gt;
&lt;path d="M8 1.5c-2.363 0-4 1.69-4 3.75 0 .984.424 1.625.984 2.304l.214.253c.223.264.47.556.673.848.284.411.537.896.621 1.49a.75.75 0 0 1-1.484.211c-.04-.282-.163-.547-.37-.847a8.456 8.456 0 0 0-.542-.68c-.084-.1-.173-.205-.268-.32C3.201 7.75 2.5 6.766 2.5 5.25 2.5 2.31 4.863 0 8 0s5.5 2.31 5.5 5.25c0 1.516-.701 2.5-1.328 3.259-.095.115-.184.22-.268.319-.207.245-.383.453-.541.681-.208.3-.33.565-.37.847a.751.751 0 0 1-1.485-.212c.084-.593.337-1.078.621-1.489.203-.292.45-.584.673-.848.075-.088.147-.173.213-.253.561-.679.985-1.32.985-2.304 0-2.06-1.637-3.75-4-3.75ZM5.75 12h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1 0-1.5ZM6 15.25a.75.75 0 0 1 .75-.75h2.5a.75.75 0 0 1 0 1.5h-2.5a.75.75 0 0 1-.75-.75Z"&gt;&lt;/path&gt;
&lt;/svg&gt;
&lt;span&gt;提示&lt;/span&gt;
&lt;/p&gt;
&lt;p&gt;遇到包冲突时，可使用 pip install &amp;ndash;no-deps -e . 解决。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;details&gt;
&lt;summary&gt;Windows 用户指南&lt;/summary&gt;
&lt;p&gt;如果要在 Windows 平台上开启量化 LoRA（QLoRA），需要安装预编译的 &lt;code&gt;bitsandbytes&lt;/code&gt; 库, 支持 CUDA 11.1 到 12.2, 请根据您的 CUDA 版本情况选择适合的&lt;a class="link" href="https://github.com/jllllll/bitsandbytes-windows-webui/releases/tag/wheels" target="_blank" rel="noopener" &gt;发布版本
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install https://github.com/jllllll/bitsandbytes-windows-webui/releases/download/wheels/bitsandbytes-0.41.2.post2-py3-none-win_amd64.whl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;如果要在 Windows 平台上开启 FlashAttention-2，需要安装预编译的 &lt;code&gt;flash-attn&lt;/code&gt; 库，支持 CUDA 12.1 到 12.2，请根据需求到 &lt;a class="link" href="https://github.com/bdashore3/flash-attention/releases" target="_blank" rel="noopener" &gt;flash-attention
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
下载对应版本安装。&lt;/p&gt;
&lt;/details&gt;
&lt;details&gt;
&lt;summary&gt;昇腾 NPU 用户指南&lt;/summary&gt;
&lt;p&gt;在昇腾 NPU 设备上安装 LLaMA Factory 时，需要指定额外依赖项，使用 &lt;code&gt;pip install -e &amp;quot;.[torch-npu,metrics]&amp;quot;&lt;/code&gt; 命令安装。此外，还需要安装 &lt;strong&gt;&lt;a class="link" href="https://www.hiascend.com/developer/download/community/result?module=cann" target="_blank" rel="noopener" &gt;Ascend CANN Toolkit 与 Kernels
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/strong&gt;，安装方法请参考&lt;a class="link" href="https://www.hiascend.com/document/detail/zh/CANNCommunityEdition/80RC2alpha002/quickstart/quickstart/quickstart_18_0004.html" target="_blank" rel="noopener" &gt;安装教程
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
或使用以下命令：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 请替换 URL 为 CANN 版本和设备型号对应的 URL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 安装 CANN Toolkit&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://ascend-repo.obs.cn-east-2.myhuaweicloud.com/Milan-ASL/Milan-ASL%20V100R001C17SPC701/Ascend-cann-toolkit_8.0.RC1.alpha001_linux-&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;uname -i&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;.run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash Ascend-cann-toolkit_8.0.RC1.alpha001_linux-&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;uname -i&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;.run --install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 安装 CANN Kernels&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wget https://ascend-repo.obs.cn-east-2.myhuaweicloud.com/Milan-ASL/Milan-ASL%20V100R001C17SPC701/Ascend-cann-kernels-910b_8.0.RC1.alpha001_linux.run
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;bash Ascend-cann-kernels-910b_8.0.RC1.alpha001_linux.run --install
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 设置环境变量&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;source&lt;/span&gt; /usr/local/Ascend/ascend-toolkit/set_env.sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;依赖项&lt;/th&gt;
&lt;th&gt;至少&lt;/th&gt;
&lt;th&gt;推荐&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;CANN&lt;/td&gt;
&lt;td&gt;8.0.RC1&lt;/td&gt;
&lt;td&gt;8.0.RC1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;torch&lt;/td&gt;
&lt;td&gt;2.1.0&lt;/td&gt;
&lt;td&gt;2.1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;torch-npu&lt;/td&gt;
&lt;td&gt;2.1.0&lt;/td&gt;
&lt;td&gt;2.1.0.post3&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;deepspeed&lt;/td&gt;
&lt;td&gt;0.13.2&lt;/td&gt;
&lt;td&gt;0.13.2&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;请使用 &lt;code&gt;ASCEND_RT_VISIBLE_DEVICES&lt;/code&gt; 而非 &lt;code&gt;CUDA_VISIBLE_DEVICES&lt;/code&gt; 来指定运算设备。&lt;/p&gt;
&lt;p&gt;如果遇到无法正常推理的情况，请尝试设置 &lt;code&gt;do_sample: false&lt;/code&gt;。&lt;/p&gt;
&lt;p&gt;下载预构建 Docker 镜像：&lt;a class="link" href="http://mirrors.cn-central-221.ovaijisuan.com/detail/130.html" target="_blank" rel="noopener" &gt;32GB
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
| &lt;a class="link" href="http://mirrors.cn-central-221.ovaijisuan.com/detail/131.html" target="_blank" rel="noopener" &gt;64GB
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;/details&gt;
&lt;p&gt;下面三行命令分别对 Llama3-8B-Instruct 模型进行 LoRA 微调、推理和合并。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;llamafactory-cli train examples/train_lora/llama3_lora_sft.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;llamafactory-cli chat examples/inference/llama3_lora_sft.yaml
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;llamafactory-cli &lt;span class="nb"&gt;export&lt;/span&gt; examples/merge_lora/llama3_lora_sft.yaml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更多详细信息，请访问 &lt;a class="link" href="https://github.com/hiyouga/LLaMA-Factory" target="_blank" rel="noopener" &gt;Llama-Factory
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
项目主页。&lt;/p&gt;
&lt;h3 id="firefly"&gt;
&lt;a href="#firefly" class="header-anchor"&gt;#&lt;/a&gt;
Firefly
&lt;/h3&gt;
&lt;a href="https://github.com/yangjianxin1/Firefly" target="_blank" class="card-github fetch-waiting no-styling"
repo="yangjianxin1/Firefly" id="repo-0DhEe0F03MoFitRq-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-0DhEe0F03MoFitRq-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;yangjianxin1&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;Firefly&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-0DhEe0F03MoFitRq-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-0DhEe0F03MoFitRq-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-0DhEe0F03MoFitRq-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-0DhEe0F03MoFitRq-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-0DhEe0F03MoFitRq-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-0DhEe0F03MoFitRq-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/yangjianxin1\/Firefly', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-0DhEe0F03MoFitRq-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-0DhEe0F03MoFitRq-language').innerText = data.language;
document.getElementById('repo-0DhEe0F03MoFitRq-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-0DhEe0F03MoFitRq-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-0DhEe0F03MoFitRq-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-0DhEe0F03MoFitRq-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-0DhEe0F03MoFitRq-license').classList.add = "no-license"
};
document.getElementById('repo-0DhEe0F03MoFitRq-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for yangjianxin1\/Firefly.")
}).catch(err =&gt; {
const c = document.getElementById('repo-0DhEe0F03MoFitRq-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for yangjianxin1\/Firefly.")
})
&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;Firefly&lt;/strong&gt; 是一个开源的大模型训练项目，支持对主流的大模型进行预训练、指令微调和 DPO，包括但不限于 Qwen2、Yi-1.5、Llama3、Gemma、Qwen1.5、MiniCPM、Llama、InternLM、Baichuan、ChatGLM、Yi、Deepseek、Qwen、Orion、Ziya、Xverse、Mistral、Mixtral-8x7B、Zephyr、Vicuna、Bloom 等。
本项目支持&lt;strong&gt;全量参数训练、LoRA、QLoRA 高效训练&lt;/strong&gt;，支持&lt;strong&gt;预训练、SFT、DPO&lt;/strong&gt;。 如果你的训练资源有限，我们极力推荐使用 QLoRA 进行指令微调，因为我们在 Open LLM Leaderboard 上验证了该方法的有效性，并且取得了非常不错的成绩。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;📗 支持预训练、指令微调、DPO，支持全量参数训练、LoRA、QLoRA 高效训练。通过配置文件的方式训练不同的模型，小白亦可快速上手训练模型。&lt;/li&gt;
&lt;li&gt;📗 支持使用&lt;a class="link" href="https://github.com/yangjianxin1/unsloth" target="_blank" rel="noopener" &gt;Unsloth
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
加速训练，并且节省显存。&lt;/li&gt;
&lt;li&gt;📗 支持绝大部分主流的开源大模型，如 Llama3、Gemma、MiniCPM、Llama、InternLM、Baichuan、ChatGLM、Yi、Deepseek、Qwen、Orion、Ziya、Xverse、Mistral、Mixtral-8x7B、Zephyr、Vicuna、Bloom，训练时与各个官方的 chat 模型的 template 对齐。&lt;/li&gt;
&lt;li&gt;📗 整理并开源指令微调数据集：firefly-train-1.1M 、moss-003-sft-data、ultrachat、 WizardLM_evol_instruct_V2_143k、school_math_0.25M。&lt;/li&gt;
&lt;li&gt;📗 开源&lt;a class="link" href="https://huggingface.co/YeungNLP" target="_blank" rel="noopener" &gt;Firefly 系列指令微调模型权重
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
。&lt;/li&gt;
&lt;li&gt;📗 在 Open LLM Leaderboard 上验证了 QLoRA 训练流程的有效性。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;该项目的 README 中包含了详细的使用说明，包括如何安装、如何训练、如何微调、如何评估等。请访问 &lt;a class="link" href="https://github.com/yangjianxin1/Firefly" target="_blank" rel="noopener" &gt;Firefly
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
项目主页。&lt;/p&gt;
&lt;h3 id="xtuner"&gt;
&lt;a href="#xtuner" class="header-anchor"&gt;#&lt;/a&gt;
XTuner
&lt;/h3&gt;
&lt;a href="https://github.com/InternLM/xtuner" target="_blank" class="card-github fetch-waiting no-styling"
repo="InternLM/xtuner" id="repo-NaaVYbbYvVJCn1vF-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-NaaVYbbYvVJCn1vF-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;InternLM&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;xtuner&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-NaaVYbbYvVJCn1vF-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-NaaVYbbYvVJCn1vF-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-NaaVYbbYvVJCn1vF-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-NaaVYbbYvVJCn1vF-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-NaaVYbbYvVJCn1vF-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-NaaVYbbYvVJCn1vF-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/InternLM\/xtuner', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-NaaVYbbYvVJCn1vF-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-NaaVYbbYvVJCn1vF-language').innerText = data.language;
document.getElementById('repo-NaaVYbbYvVJCn1vF-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-NaaVYbbYvVJCn1vF-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-NaaVYbbYvVJCn1vF-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-NaaVYbbYvVJCn1vF-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-NaaVYbbYvVJCn1vF-license').classList.add = "no-license"
};
document.getElementById('repo-NaaVYbbYvVJCn1vF-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for InternLM\/xtuner.")
}).catch(err =&gt; {
const c = document.getElementById('repo-NaaVYbbYvVJCn1vF-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for InternLM\/xtuner.")
})
&lt;/script&gt;
&lt;p&gt;XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;高效&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;支持大语言模型 LLM、多模态图文模型 VLM 的预训练及轻量级微调。XTuner 支持在 8GB 显存下微调 7B 模型，同时也支持多节点跨设备微调更大尺度模型（70B+）。&lt;/li&gt;
&lt;li&gt;自动分发高性能算子（如 FlashAttention、Triton kernels 等）以加速训练吞吐。&lt;/li&gt;
&lt;li&gt;兼容 &lt;a class="link" href="https://github.com/microsoft/DeepSpeed" target="_blank" rel="noopener" &gt;DeepSpeed
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
🚀，轻松应用各种 ZeRO 训练优化策略。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;灵活&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;支持多种大语言模型，包括但不限于 &lt;a class="link" href="https://huggingface.co/internlm" target="_blank" rel="noopener" &gt;InternLM
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、&lt;a class="link" href="https://huggingface.co/mistralai" target="_blank" rel="noopener" &gt;Mixtral-8x7B
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、&lt;a class="link" href="https://huggingface.co/meta-llama" target="_blank" rel="noopener" &gt;Llama 2
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、&lt;a class="link" href="https://huggingface.co/THUDM" target="_blank" rel="noopener" &gt;ChatGLM
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、&lt;a class="link" href="https://huggingface.co/Qwen" target="_blank" rel="noopener" &gt;Qwen
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、&lt;a class="link" href="https://huggingface.co/baichuan-inc" target="_blank" rel="noopener" &gt;Baichuan
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
。&lt;/li&gt;
&lt;li&gt;支持多模态图文模型 LLaVA 的预训练与微调。利用 XTuner 训得模型 &lt;a class="link" href="https://huggingface.co/xtuner/llava-internlm2-20b" target="_blank" rel="noopener" &gt;LLaVA-InternLM2-20B
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
表现优异。&lt;/li&gt;
&lt;li&gt;精心设计的数据管道，兼容任意数据格式，开源数据或自定义数据皆可快速上手。&lt;/li&gt;
&lt;li&gt;支持 &lt;a class="link" href="http://arxiv.org/abs/2305.14314" target="_blank" rel="noopener" &gt;QLoRA
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、&lt;a class="link" href="http://arxiv.org/abs/2106.09685" target="_blank" rel="noopener" &gt;LoRA
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、全量参数微调等多种微调算法，支撑用户根据具体需求作出最优选择。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;全能&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;支持增量预训练、指令微调与 Agent 微调。&lt;/li&gt;
&lt;li&gt;预定义众多开源对话模版，支持与开源或训练所得模型进行对话。&lt;/li&gt;
&lt;li&gt;训练所得模型可无缝接入部署工具库 &lt;a class="link" href="https://github.com/InternLM/lmdeploy" target="_blank" rel="noopener" &gt;LMDeploy
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
、大规模评测工具库 &lt;a class="link" href="https://github.com/open-compass/opencompass" target="_blank" rel="noopener" &gt;OpenCompass
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
及 &lt;a class="link" href="https://github.com/open-compass/VLMEvalKit" target="_blank" rel="noopener" &gt;VLMEvalKit
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;快速上手：&lt;/strong&gt;
&lt;details&gt;
&lt;summary&gt;安装&lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;推荐使用 conda 先构建一个 Python-3.10 的虚拟环境&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda create --name xtuner-env &lt;span class="nv"&gt;python&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3.10 -y
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;conda activate xtuner-env
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 pip 安装 XTuner：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install -U xtuner
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;亦可集成 DeepSpeed 安装：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install -U &lt;span class="s1"&gt;&amp;#39;xtuner[deepspeed]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;从源码安装 XTuner：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;git clone https://github.com/InternLM/xtuner.git
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; xtuner
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install -e &lt;span class="s1"&gt;&amp;#39;.[all]&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;微调&lt;/summary&gt;
&lt;p&gt;XTuner 支持微调大语言模型。数据集预处理指南请查阅&lt;a class="link" href="./docs/zh_cn/user_guides/dataset_prepare.md" &gt;文档
&lt;/a&gt;
。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;步骤 0&lt;/strong&gt;，准备配置文件。XTuner 提供多个开箱即用的配置文件，用户可以通过下列命令查看：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xtuner list-cfg
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;或者，如果所提供的配置文件不能满足使用需求，请导出所提供的配置文件并进行相应更改：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xtuner copy-cfg &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFIG_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SAVE_PATH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vi &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SAVE_PATH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;/&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFIG_NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;_copy.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;步骤 1&lt;/strong&gt;，开始微调。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xtuner train &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFIG_NAME_OR_PATH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;例如，我们可以利用 QLoRA 算法在 oasst1 数据集上微调 InternLM2.5-Chat-7B：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 单卡&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xtuner train internlm2_5_chat_7b_qlora_oasst1_e3 --deepspeed deepspeed_zero2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# 多卡&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;DIST&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;NPROC_PER_NODE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GPU_NUM&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; xtuner train internlm2_5_chat_7b_qlora_oasst1_e3 --deepspeed deepspeed_zero2
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="o"&gt;(&lt;/span&gt;SLURM&lt;span class="o"&gt;)&lt;/span&gt; srun &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SRUN_ARGS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; xtuner train internlm2_5_chat_7b_qlora_oasst1_e3 --launcher slurm --deepspeed deepspeed_zero2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;--deepspeed&lt;/code&gt; 表示使用 &lt;a class="link" href="https://github.com/microsoft/DeepSpeed" target="_blank" rel="noopener" &gt;DeepSpeed
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
🚀 来优化训练过程。XTuner 内置了多种策略，包括 ZeRO-1、ZeRO-2、ZeRO-3 等。如果用户期望关闭此功能，请直接移除此参数。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;更多示例，请查阅&lt;a class="link" href="./docs/zh_cn/user_guides/finetune.md" &gt;文档
&lt;/a&gt;
。&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;步骤 2&lt;/strong&gt;，将保存的 PTH 模型（如果使用的 DeepSpeed，则将会是一个文件夹）转换为 HuggingFace 模型：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-shell" data-lang="shell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xtuner convert pth_to_hf &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONFIG_NAME_OR_PATH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PTH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;SAVE_PATH&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;p&gt;其它详细信息，请访问 &lt;a class="link" href="https://github.com/InternLM/xtuner" target="_blank" rel="noopener" &gt;XTuner
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h2 id="模型量化"&gt;
&lt;a href="#%e6%a8%a1%e5%9e%8b%e9%87%8f%e5%8c%96" class="header-anchor"&gt;#&lt;/a&gt;
模型量化
&lt;/h2&gt;&lt;p&gt;LLM 通常体积庞大，对计算资源要求高。模型量化技术可以压缩模型大小，提高运行效率，使其更易于部署：&lt;/p&gt;
&lt;h3 id="autogptq"&gt;
&lt;a href="#autogptq" class="header-anchor"&gt;#&lt;/a&gt;
AutoGPTQ
&lt;/h3&gt;
&lt;a href="https://github.com/PanQiWei/AutoGPTQ" target="_blank" class="card-github fetch-waiting no-styling"
repo="PanQiWei/AutoGPTQ" id="repo-aWChEmJdL3Hm2Aa7-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-aWChEmJdL3Hm2Aa7-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;PanQiWei&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;AutoGPTQ&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-aWChEmJdL3Hm2Aa7-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-aWChEmJdL3Hm2Aa7-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-aWChEmJdL3Hm2Aa7-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-aWChEmJdL3Hm2Aa7-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-aWChEmJdL3Hm2Aa7-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-aWChEmJdL3Hm2Aa7-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/PanQiWei\/AutoGPTQ', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-aWChEmJdL3Hm2Aa7-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-aWChEmJdL3Hm2Aa7-language').innerText = data.language;
document.getElementById('repo-aWChEmJdL3Hm2Aa7-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-aWChEmJdL3Hm2Aa7-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-aWChEmJdL3Hm2Aa7-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-aWChEmJdL3Hm2Aa7-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-aWChEmJdL3Hm2Aa7-license').classList.add = "no-license"
};
document.getElementById('repo-aWChEmJdL3Hm2Aa7-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for PanQiWei\/AutoGPTQ.")
}).catch(err =&gt; {
const c = document.getElementById('repo-aWChEmJdL3Hm2Aa7-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for PanQiWei\/AutoGPTQ.")
})
&lt;/script&gt;
&lt;p&gt;AutoGPTQ 一个基于 GPTQ 算法，简单易用且拥有用户友好型接口的大语言模型量化工具包。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;快速安装&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对于 CUDA 11.7：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install auto-gptq --extra-index-url https://huggingface.github.io/autogptq-index/whl/cu117/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;对于 CUDA 11.8：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install auto-gptq --extra-index-url https://huggingface.github.io/autogptq-index/whl/cu118/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;ul&gt;
&lt;li&gt;对于 RoCm 5.4.2：&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install auto-gptq --extra-index-url https://huggingface.github.io/autogptq-index/whl/rocm542/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更多详细信息，请访问 &lt;a class="link" href="https://github.com/AutoGPTQ/AutoGPTQ/" target="_blank" rel="noopener" &gt;AutoGPTQ
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="autoawq"&gt;
&lt;a href="#autoawq" class="header-anchor"&gt;#&lt;/a&gt;
AutoAWQ
&lt;/h3&gt;
&lt;a href="https://github.com/casper-hansen/AutoAWQ" target="_blank" class="card-github fetch-waiting no-styling"
repo="casper-hansen/AutoAWQ" id="repo-FLYjNBrrx5tsF0rW-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-FLYjNBrrx5tsF0rW-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;casper-hansen&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;AutoAWQ&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-FLYjNBrrx5tsF0rW-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-FLYjNBrrx5tsF0rW-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-FLYjNBrrx5tsF0rW-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-FLYjNBrrx5tsF0rW-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-FLYjNBrrx5tsF0rW-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-FLYjNBrrx5tsF0rW-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/casper-hansen\/AutoAWQ', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-FLYjNBrrx5tsF0rW-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-FLYjNBrrx5tsF0rW-language').innerText = data.language;
document.getElementById('repo-FLYjNBrrx5tsF0rW-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-FLYjNBrrx5tsF0rW-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-FLYjNBrrx5tsF0rW-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-FLYjNBrrx5tsF0rW-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-FLYjNBrrx5tsF0rW-license').classList.add = "no-license"
};
document.getElementById('repo-FLYjNBrrx5tsF0rW-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for casper-hansen\/AutoAWQ.")
}).catch(err =&gt; {
const c = document.getElementById('repo-FLYjNBrrx5tsF0rW-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for casper-hansen\/AutoAWQ.")
})
&lt;/script&gt;
&lt;p&gt;AutoAWQ 是另一款自动化模型量化工具，支持多种量化精度，并提供灵活的配置选项，可以根据不同的硬件平台和性能需求进行调整。&lt;/p&gt;
&lt;p&gt;AutoAWQ 是一个易于使用的 4 位量化模型软件包。与 FP16 相比，AutoAWQ 可将模型速度提高 3 倍，内存需求减少 3 倍。AutoAWQ 实现了用于量化 LLMs 的激活感知权重量化（AWQ）算法。AutoAWQ 是在 MIT 的原始工作 &lt;a class="link" href="https://github.com/mit-han-lab/llm-awq" target="_blank" rel="noopener" &gt;AWQ
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
基础上创建和改进的。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安装方法：&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;安装前，确保安装了 CUDA &amp;gt;= 12.1（注意：以下只是最快捷的安装方法）&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install autoawq
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更多详细信息和示例，请访问 &lt;a class="link" href="https://github.com/casper-hansen/AutoAWQ" target="_blank" rel="noopener" &gt;AutoAWQ
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="neural-compressor"&gt;
&lt;a href="#neural-compressor" class="header-anchor"&gt;#&lt;/a&gt;
Neural Compressor
&lt;/h3&gt;
&lt;a href="https://github.com/intel/neural-compressor" target="_blank" class="card-github fetch-waiting no-styling"
repo="intel/neural-compressor" id="repo-W48Rmh9698tIEVn7-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-W48Rmh9698tIEVn7-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;intel&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;neural-compressor&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-W48Rmh9698tIEVn7-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-W48Rmh9698tIEVn7-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-W48Rmh9698tIEVn7-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-W48Rmh9698tIEVn7-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-W48Rmh9698tIEVn7-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-W48Rmh9698tIEVn7-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/intel\/neural-compressor', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-W48Rmh9698tIEVn7-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-W48Rmh9698tIEVn7-language').innerText = data.language;
document.getElementById('repo-W48Rmh9698tIEVn7-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-W48Rmh9698tIEVn7-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-W48Rmh9698tIEVn7-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-W48Rmh9698tIEVn7-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-W48Rmh9698tIEVn7-license').classList.add = "no-license"
};
document.getElementById('repo-W48Rmh9698tIEVn7-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for intel\/neural-compressor.")
}).catch(err =&gt; {
const c = document.getElementById('repo-W48Rmh9698tIEVn7-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for intel\/neural-compressor.")
})
&lt;/script&gt;
&lt;p&gt;Neural Compressor 是英特尔开发的模型压缩工具包，支持所有主流深度学习框架（TensorFlow、PyTorch、ONNX Runtime 和 MXNet）上流行的模型压缩技术。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;安装方法：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install &lt;span class="s2"&gt;&amp;#34;neural-compressor&amp;gt;=2.3&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;transformers&amp;gt;=4.34.0&amp;#34;&lt;/span&gt; torch torchvision
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更多详细信息和示例，请访问 &lt;a class="link" href="https://github.com/intel/neural-compressor" target="_blank" rel="noopener" &gt;Neural Compressor
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h2 id="模型部署"&gt;
&lt;a href="#%e6%a8%a1%e5%9e%8b%e9%83%a8%e7%bd%b2" class="header-anchor"&gt;#&lt;/a&gt;
模型部署
&lt;/h2&gt;&lt;p&gt;将训练好的 LLM 部署到生产环境至关重要。以下是一些常用的 LLM 部署工具：&lt;/p&gt;
&lt;h3 id="vllm"&gt;
&lt;a href="#vllm" class="header-anchor"&gt;#&lt;/a&gt;
vLLM
&lt;/h3&gt;
&lt;a href="https://github.com/vllm-project/vllm" target="_blank" class="card-github fetch-waiting no-styling"
repo="vllm-project/vllm" id="repo-4VRd1e5EzXZiSMxH-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-4VRd1e5EzXZiSMxH-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;vllm-project&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;vllm&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-4VRd1e5EzXZiSMxH-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-4VRd1e5EzXZiSMxH-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-4VRd1e5EzXZiSMxH-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-4VRd1e5EzXZiSMxH-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-4VRd1e5EzXZiSMxH-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-4VRd1e5EzXZiSMxH-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/vllm-project\/vllm', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-4VRd1e5EzXZiSMxH-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-4VRd1e5EzXZiSMxH-language').innerText = data.language;
document.getElementById('repo-4VRd1e5EzXZiSMxH-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-4VRd1e5EzXZiSMxH-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-4VRd1e5EzXZiSMxH-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-4VRd1e5EzXZiSMxH-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-4VRd1e5EzXZiSMxH-license').classList.add = "no-license"
};
document.getElementById('repo-4VRd1e5EzXZiSMxH-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for vllm-project\/vllm.")
}).catch(err =&gt; {
const c = document.getElementById('repo-4VRd1e5EzXZiSMxH-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for vllm-project\/vllm.")
})
&lt;/script&gt;
&lt;p&gt;vLLM 是一个快速、易用的 LLM 推理服务库。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;快速&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;SOTA 服务吞吐量&lt;/li&gt;
&lt;li&gt;利用 PagedAttention 高效管理注意力键值内存&lt;/li&gt;
&lt;li&gt;持续批量处理收到的请求&lt;/li&gt;
&lt;li&gt;利用 CUDA/HIP 图进行加速&lt;/li&gt;
&lt;li&gt;量化：支持 GPTQ、AWQ、SqueezeLLM、FP8 KV 高速缓存&lt;/li&gt;
&lt;li&gt;优化的 CUDA 内核&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;灵活&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;与流行的 Hugging Face 模型无缝集成&lt;/li&gt;
&lt;li&gt;利用各种解码算法（包括并行采样、波束搜索等）提供高吞吐量服务&lt;/li&gt;
&lt;li&gt;为分布式推理提供张量并行支持&lt;/li&gt;
&lt;li&gt;流输出&lt;/li&gt;
&lt;li&gt;兼容 OpenAI 的应用程序接口服务器&lt;/li&gt;
&lt;li&gt;支持 NVIDIA GPU、AMD GPU、Intel CPU 和 GPU
-（实验性）支持前缀缓存
-（试验性）支持多种语言&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;无缝支持&lt;/strong&gt;
&lt;ul&gt;
&lt;li&gt;基于 Transformer 的模型，例如 Llama&lt;/li&gt;
&lt;li&gt;基于 MoE 的模型，例如 Mixtral&lt;/li&gt;
&lt;li&gt;多模态模型，例如 LLaVA&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;快速安装：&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;pip install vllm
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;更多详细信息，请查看 &lt;a class="link" href="https://vllm.readthedocs.io/en/latest/" target="_blank" rel="noopener" &gt;vLLM
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
官方文档。&lt;/p&gt;
&lt;h3 id="sgl"&gt;
&lt;a href="#sgl" class="header-anchor"&gt;#&lt;/a&gt;
SGL
&lt;/h3&gt;
&lt;a href="https://github.com/sgl-project/sglang" target="_blank" class="card-github fetch-waiting no-styling"
repo="sgl-project/sglang" id="repo-mlpQP351YySnypgp-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-mlpQP351YySnypgp-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;sgl-project&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;sglang&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-mlpQP351YySnypgp-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-mlpQP351YySnypgp-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-mlpQP351YySnypgp-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-mlpQP351YySnypgp-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-mlpQP351YySnypgp-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-mlpQP351YySnypgp-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/sgl-project\/sglang', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-mlpQP351YySnypgp-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-mlpQP351YySnypgp-language').innerText = data.language;
document.getElementById('repo-mlpQP351YySnypgp-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-mlpQP351YySnypgp-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-mlpQP351YySnypgp-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-mlpQP351YySnypgp-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-mlpQP351YySnypgp-license').classList.add = "no-license"
};
document.getElementById('repo-mlpQP351YySnypgp-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for sgl-project\/sglang.")
}).catch(err =&gt; {
const c = document.getElementById('repo-mlpQP351YySnypgp-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for sgl-project\/sglang.")
})
&lt;/script&gt;
&lt;p&gt;SGLang 是一种结构化生成语言，专为大型语言模型（LLMs）而设计。它通过共同设计前端语言和运行系统，使你与 LLMs 的交互更快、更可控。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;灵活的前端语言&lt;/strong&gt;：通过链式生成调用、高级提示、控制流、多种模式、并行性和外部交互，可轻松编写 LLM 应用程序。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;高性能后端运行时&lt;/strong&gt;：具有 RadixAttention 功能，可通过在多次调用中重复使用 KV 缓存来加速复杂的 LLM 程序。它还可以作为独立的推理引擎，实现所有常用技术（如连续批处理和张量并行）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更多详细信息，请访问 &lt;a class="link" href="https://github.com/sgl-project/" target="_blank" rel="noopener" &gt;SGL
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="skypilot"&gt;
&lt;a href="#skypilot" class="header-anchor"&gt;#&lt;/a&gt;
SkyPilot
&lt;/h3&gt;
&lt;a href="https://github.com/skypilot-org/skypilot" target="_blank" class="card-github fetch-waiting no-styling"
repo="skypilot-org/skypilot" id="repo-XsghPBWFB0XuKNmJ-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-XsghPBWFB0XuKNmJ-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;skypilot-org&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;skypilot&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-XsghPBWFB0XuKNmJ-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-XsghPBWFB0XuKNmJ-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-XsghPBWFB0XuKNmJ-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-XsghPBWFB0XuKNmJ-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-XsghPBWFB0XuKNmJ-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-XsghPBWFB0XuKNmJ-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/skypilot-org\/skypilot', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-XsghPBWFB0XuKNmJ-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-XsghPBWFB0XuKNmJ-language').innerText = data.language;
document.getElementById('repo-XsghPBWFB0XuKNmJ-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-XsghPBWFB0XuKNmJ-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-XsghPBWFB0XuKNmJ-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-XsghPBWFB0XuKNmJ-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-XsghPBWFB0XuKNmJ-license').classList.add = "no-license"
};
document.getElementById('repo-XsghPBWFB0XuKNmJ-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for skypilot-org\/skypilot.")
}).catch(err =&gt; {
const c = document.getElementById('repo-XsghPBWFB0XuKNmJ-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for skypilot-org\/skypilot.")
})
&lt;/script&gt;
&lt;p&gt;SkyPilot 是 UC Berkeley RISELab 推出的灵活的云端 LLM 部署工具，支持多种云平台和硬件加速器，可以自动选择最优的部署方案，并提供成本优化功能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;多云支持:&lt;/strong&gt; 支持 AWS, GCP, Azure 等多种云平台，方便用户选择合适的部署环境。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;轻松扩展&lt;/strong&gt;：排队和运行多个作业，自动管理&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;轻松接入对象存储&lt;/strong&gt;：轻松访问对象存储（S3、GCS、R2）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更多详细信息，请访问 &lt;a class="link" href="https://github.com/skypilot-org/skypilot" target="_blank" rel="noopener" &gt;SkyPilot
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="tensorrt-llm"&gt;
&lt;a href="#tensorrt-llm" class="header-anchor"&gt;#&lt;/a&gt;
TensorRT-LLM
&lt;/h3&gt;
&lt;a href="https://github.com/NVIDIA/TensorRT-LLM" target="_blank" class="card-github fetch-waiting no-styling"
repo="NVIDIA/TensorRT-LLM" id="repo-LAs89aiLNW8OcHMe-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-LAs89aiLNW8OcHMe-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;NVIDIA&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;TensorRT-LLM&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-LAs89aiLNW8OcHMe-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-LAs89aiLNW8OcHMe-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-LAs89aiLNW8OcHMe-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-LAs89aiLNW8OcHMe-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-LAs89aiLNW8OcHMe-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-LAs89aiLNW8OcHMe-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/NVIDIA\/TensorRT-LLM', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-LAs89aiLNW8OcHMe-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-LAs89aiLNW8OcHMe-language').innerText = data.language;
document.getElementById('repo-LAs89aiLNW8OcHMe-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-LAs89aiLNW8OcHMe-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-LAs89aiLNW8OcHMe-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-LAs89aiLNW8OcHMe-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-LAs89aiLNW8OcHMe-license').classList.add = "no-license"
};
document.getElementById('repo-LAs89aiLNW8OcHMe-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for NVIDIA\/TensorRT-LLM.")
}).catch(err =&gt; {
const c = document.getElementById('repo-LAs89aiLNW8OcHMe-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for NVIDIA\/TensorRT-LLM.")
})
&lt;/script&gt;
&lt;p&gt;TensorRT-LLM 是 NVIDIA 推出的高性能 LLM 推理引擎，能够充分利用 GPU 加速计算，并针对 Transformer 模型结构进行了优化，大幅提升推理速度。&lt;/p&gt;
&lt;p&gt;TensorRT-LLM 为用户提供了易于使用的 Python API，用于定义大型语言模型 (LLMs) 和构建 TensorRT 引擎，这些引擎包含最先进的优化技术，可在英伟达™（NVIDIA®）图形处理器上高效执行推理。TensorRT-LLM 还包含用于创建执行这些 TensorRT 引擎的 Python 和 C++ 运行时的组件。&lt;/p&gt;
&lt;p&gt;详细信息，请访问 &lt;a class="link" href="https://github.com/NVIDIA/TensorRT-LLM" target="_blank" rel="noopener" &gt;TensorRT-LLM
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="openvino"&gt;
&lt;a href="#openvino" class="header-anchor"&gt;#&lt;/a&gt;
OpenVino
&lt;/h3&gt;
&lt;a href="https://github.com/openvinotoolkit/openvino" target="_blank" class="card-github fetch-waiting no-styling"
repo="openvinotoolkit/openvino" id="repo-aUg8kAcWODZ8n6CW-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-aUg8kAcWODZ8n6CW-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;openvinotoolkit&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;openvino&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-aUg8kAcWODZ8n6CW-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-aUg8kAcWODZ8n6CW-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-aUg8kAcWODZ8n6CW-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-aUg8kAcWODZ8n6CW-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-aUg8kAcWODZ8n6CW-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-aUg8kAcWODZ8n6CW-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/openvinotoolkit\/openvino', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-aUg8kAcWODZ8n6CW-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-aUg8kAcWODZ8n6CW-language').innerText = data.language;
document.getElementById('repo-aUg8kAcWODZ8n6CW-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-aUg8kAcWODZ8n6CW-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-aUg8kAcWODZ8n6CW-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-aUg8kAcWODZ8n6CW-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-aUg8kAcWODZ8n6CW-license').classList.add = "no-license"
};
document.getElementById('repo-aUg8kAcWODZ8n6CW-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for openvinotoolkit\/openvino.")
}).catch(err =&gt; {
const c = document.getElementById('repo-aUg8kAcWODZ8n6CW-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for openvinotoolkit\/openvino.")
})
&lt;/script&gt;
&lt;p&gt;OpenVINO™ 是用于优化和部署人工智能推理的开源工具包。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;推理优化&lt;/strong&gt;：提升深度学习在计算机视觉、自动语音识别、生成式人工智能、使用大型和小型语言模型的自然语言处理以及许多其他常见任务中的性能。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;灵活的模型支持&lt;/strong&gt;：使用 TensorFlow、PyTorch、ONNX、Keras 和 PaddlePaddle 等流行框架训练的模型。无需原始框架即可转换和部署模型。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;广泛的平台兼容性&lt;/strong&gt;：减少资源需求，在从边缘到云的一系列平台上高效部署。OpenVINO™ 支持在 CPU（x86、ARM）、GPU（支持 OpenCL 的集成和独立 GPU）和 AI 加速器（英特尔 NPU）上进行推理。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;社区和生态系统&lt;/strong&gt;：加入一个活跃的社区，为提高各个领域的深度学习性能做出贡献。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;详细信息，请访问 &lt;a class="link" href="https://github.com/openvinotoolkit/openvino" target="_blank" rel="noopener" &gt;OpenVino
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="tgi"&gt;
&lt;a href="#tgi" class="header-anchor"&gt;#&lt;/a&gt;
TGI
&lt;/h3&gt;
&lt;a href="https://github.com/huggingface/text-generation-inference" target="_blank" class="card-github fetch-waiting no-styling"
repo="huggingface/text-generation-inference" id="repo-pTPkVYmat6iAtJLx-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-pTPkVYmat6iAtJLx-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;huggingface&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;text-generation-inference&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-pTPkVYmat6iAtJLx-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-pTPkVYmat6iAtJLx-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-pTPkVYmat6iAtJLx-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-pTPkVYmat6iAtJLx-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-pTPkVYmat6iAtJLx-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-pTPkVYmat6iAtJLx-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/huggingface\/text-generation-inference', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-pTPkVYmat6iAtJLx-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-pTPkVYmat6iAtJLx-language').innerText = data.language;
document.getElementById('repo-pTPkVYmat6iAtJLx-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-pTPkVYmat6iAtJLx-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-pTPkVYmat6iAtJLx-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-pTPkVYmat6iAtJLx-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-pTPkVYmat6iAtJLx-license').classList.add = "no-license"
};
document.getElementById('repo-pTPkVYmat6iAtJLx-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for huggingface\/text-generation-inference.")
}).catch(err =&gt; {
const c = document.getElementById('repo-pTPkVYmat6iAtJLx-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for huggingface\/text-generation-inference.")
})
&lt;/script&gt;
&lt;p&gt;文本生成推理（TGI）是一个用于部署和服务大型语言模型（LLMs）的工具包。TGI 可为最流行的开源 LLMs 实现高性能文本生成，包括 Llama、Falcon、StarCoder、BLOOM、GPT-NeoX 等。&lt;/p&gt;
&lt;p&gt;TGI 实现了许多功能，可以在 &lt;a class="link" href="https://github.com/huggingface/text-generation-inference" target="_blank" rel="noopener" &gt;TGI
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页上找到详细信息。&lt;/p&gt;
&lt;h2 id="本地运行"&gt;
&lt;a href="#%e6%9c%ac%e5%9c%b0%e8%bf%90%e8%a1%8c" class="header-anchor"&gt;#&lt;/a&gt;
本地运行
&lt;/h2&gt;&lt;p&gt;得益于模型压缩和优化技术，我们也可以在个人设备上运行 LLM：&lt;/p&gt;
&lt;h3 id="mlx"&gt;
&lt;a href="#mlx" class="header-anchor"&gt;#&lt;/a&gt;
MLX
&lt;/h3&gt;
&lt;a href="https://github.com/ml-explore/mlx" target="_blank" class="card-github fetch-waiting no-styling"
repo="ml-explore/mlx" id="repo-aFyU1OLymjJwTIDj-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-aFyU1OLymjJwTIDj-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;ml-explore&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;mlx&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-aFyU1OLymjJwTIDj-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-aFyU1OLymjJwTIDj-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-aFyU1OLymjJwTIDj-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-aFyU1OLymjJwTIDj-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-aFyU1OLymjJwTIDj-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-aFyU1OLymjJwTIDj-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/ml-explore\/mlx', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-aFyU1OLymjJwTIDj-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-aFyU1OLymjJwTIDj-language').innerText = data.language;
document.getElementById('repo-aFyU1OLymjJwTIDj-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-aFyU1OLymjJwTIDj-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-aFyU1OLymjJwTIDj-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-aFyU1OLymjJwTIDj-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-aFyU1OLymjJwTIDj-license').classList.add = "no-license"
};
document.getElementById('repo-aFyU1OLymjJwTIDj-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for ml-explore\/mlx.")
}).catch(err =&gt; {
const c = document.getElementById('repo-aFyU1OLymjJwTIDj-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for ml-explore\/mlx.")
})
&lt;/script&gt;
&lt;p&gt;MLX 是一个专门支持在 Apple 设备上运行 LLM 的框架，充分利用 Metal 加速计算，并提供简单易用的 API，方便开发者将 LLM 集成到 iOS 应用中.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;相似的应用程序接口&lt;/strong&gt;：MLX 的 Python API 与 NumPy 非常相似。MLX 还拥有功能齐全的 C++、C 和 Swift API，这些 API 与 Python API 非常相似。MLX 拥有更高级别的软件包，如 &lt;code&gt;mlx.nn&lt;/code&gt; 和 &lt;code&gt;mlx.optimizers&lt;/code&gt; ，其 API 与 PyTorch 非常接近，可简化更复杂模型的构建。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可组合函数变换&lt;/strong&gt;：MLX 支持用于自动微分、自动矢量化和计算图优化的可组合函数变换。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;懒计算&lt;/strong&gt;：MLX 中的计算只有在需要时才将数组实体化。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;动态图构建&lt;/strong&gt;：MLX 中的计算图形是动态构建的。改变函数参数的形状不会导致编译速度变慢，而且调试简单直观。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多设备&lt;/strong&gt;：操作可在任何支持的设备（目前是 CPU 和 GPU）上运行。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;统一内存&lt;/strong&gt;：统一内存模型是 MLX 与其他框架的一个显著区别。MLX 中的阵列位于共享内存中。对 MLX 数组的操作可在任何支持的设备类型上执行，而无需传输数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;MLX 是机器学习研究人员为机器学习研究人员设计的。该框架旨在方便用户使用，但仍能高效地训练和部署模型。框架本身的设计概念也很简单。我们的目标是让研究人员能够轻松扩展和改进 MLX，从而快速探索新思路。更多详细信息，请访问 &lt;a class="link" href="https://github.com/ml-explore/mlx" target="_blank" rel="noopener" &gt;MLX
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="llamacpp"&gt;
&lt;a href="#llamacpp" class="header-anchor"&gt;#&lt;/a&gt;
Llama.cpp
&lt;/h3&gt;&lt;p&gt;Llama.cpp 是使用 C++ 实现的 Llama 模型推理引擎，可以在 CPU 上高效运行，并支持多种操作系统和硬件平台，方便开发者在资源受限的设备上运行 LLM。&lt;/p&gt;
&lt;a href="https://github.com/ggerganov/llama.cpp" target="_blank" class="card-github fetch-waiting no-styling"
repo="ggerganov/llama.cpp" id="repo-GtIlLTRqRWLojYGt-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-GtIlLTRqRWLojYGt-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;ggerganov&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;llama.cpp&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-GtIlLTRqRWLojYGt-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-GtIlLTRqRWLojYGt-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-GtIlLTRqRWLojYGt-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-GtIlLTRqRWLojYGt-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-GtIlLTRqRWLojYGt-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-GtIlLTRqRWLojYGt-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/ggerganov\/llama.cpp', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-GtIlLTRqRWLojYGt-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-GtIlLTRqRWLojYGt-language').innerText = data.language;
document.getElementById('repo-GtIlLTRqRWLojYGt-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-GtIlLTRqRWLojYGt-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-GtIlLTRqRWLojYGt-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-GtIlLTRqRWLojYGt-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-GtIlLTRqRWLojYGt-license').classList.add = "no-license"
};
document.getElementById('repo-GtIlLTRqRWLojYGt-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for ggerganov\/llama.cpp.")
}).catch(err =&gt; {
const c = document.getElementById('repo-GtIlLTRqRWLojYGt-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for ggerganov\/llama.cpp.")
})
&lt;/script&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CPU 推理:&lt;/strong&gt; 针对 CPU 平台进行优化，可以在没有 GPU 的设备上运行 LLM。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;跨平台支持:&lt;/strong&gt; 支持 Linux, macOS, Windows 等多种操作系统，方便用户在不同平台上使用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;轻量级部署:&lt;/strong&gt; 编译后的二进制文件体积小，方便用户部署和使用.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更多详细信息，请访问 &lt;a class="link" href="https://github.com/ggerganov/llama.cpp" target="_blank" rel="noopener" &gt;Llama.cpp
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="ollama"&gt;
&lt;a href="#ollama" class="header-anchor"&gt;#&lt;/a&gt;
Ollama
&lt;/h3&gt;
&lt;a href="https://github.com/ollama/ollama" target="_blank" class="card-github fetch-waiting no-styling"
repo="ollama/ollama" id="repo-EpF4o2hdBkaXPXZB-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-EpF4o2hdBkaXPXZB-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;ollama&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;ollama&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-EpF4o2hdBkaXPXZB-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-EpF4o2hdBkaXPXZB-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-EpF4o2hdBkaXPXZB-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-EpF4o2hdBkaXPXZB-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-EpF4o2hdBkaXPXZB-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-EpF4o2hdBkaXPXZB-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/ollama\/ollama', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-EpF4o2hdBkaXPXZB-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-EpF4o2hdBkaXPXZB-language').innerText = data.language;
document.getElementById('repo-EpF4o2hdBkaXPXZB-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-EpF4o2hdBkaXPXZB-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-EpF4o2hdBkaXPXZB-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-EpF4o2hdBkaXPXZB-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-EpF4o2hdBkaXPXZB-license').classList.add = "no-license"
};
document.getElementById('repo-EpF4o2hdBkaXPXZB-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for ollama\/ollama.")
}).catch(err =&gt; {
const c = document.getElementById('repo-EpF4o2hdBkaXPXZB-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for ollama\/ollama.")
})
&lt;/script&gt;
&lt;p&gt;在 &lt;a class="link" href="https://cuterwrite.top/p/ollama/" &gt;【Ollama：从入门到进阶】
&lt;/a&gt;
一文中介绍过，Ollama 是一个用于构建大型语言模型应用的工具，它提供了一个简洁易用的命令行界面和服务器，让你能够轻松下载、运行和管理各种开源 LLM。与需要复杂配置和强大硬件的传统 LLM 不同，Ollama 让你能够方便地像使用手机 App 一样体验 LLM 的强大功能。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;简单易用&lt;/strong&gt;：Ollama 提供了一个简洁易用的命令行工具，方便用户下载、运行和管理 LLM。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;多种模型&lt;/strong&gt;：Ollama 支持多种开源 LLM，包括 Qwen2、Llama3、Mistral 等。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;兼容 OpenAI 接口&lt;/strong&gt;：Ollama 支持 OpenAI API 接口，便于切换原有应用到 Ollama 上。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更多详细信息，请访问 &lt;a class="link" href="https://github.com/ollama/ollama" target="_blank" rel="noopener" &gt;Ollama
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h2 id="agent-及-rag-框架"&gt;
&lt;a href="#agent-%e5%8f%8a-rag-%e6%a1%86%e6%9e%b6" class="header-anchor"&gt;#&lt;/a&gt;
Agent 及 RAG 框架
&lt;/h2&gt;&lt;p&gt;将 LLM 与外部数据和工具结合，可以构建更强大的应用。以下是一些常用的 Agent 及 RAG 框架：&lt;/p&gt;
&lt;h3 id="llamaindex"&gt;
&lt;a href="#llamaindex" class="header-anchor"&gt;#&lt;/a&gt;
LlamaIndex
&lt;/h3&gt;
&lt;a href="https://github.com/run-llama/llama_index" target="_blank" class="card-github fetch-waiting no-styling"
repo="run-llama/llama_index" id="repo-j8nyyLbsK6CAkuH0-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-j8nyyLbsK6CAkuH0-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;run-llama&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;llama_index&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-j8nyyLbsK6CAkuH0-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-j8nyyLbsK6CAkuH0-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-j8nyyLbsK6CAkuH0-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-j8nyyLbsK6CAkuH0-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-j8nyyLbsK6CAkuH0-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-j8nyyLbsK6CAkuH0-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/run-llama\/llama_index', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-j8nyyLbsK6CAkuH0-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-j8nyyLbsK6CAkuH0-language').innerText = data.language;
document.getElementById('repo-j8nyyLbsK6CAkuH0-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-j8nyyLbsK6CAkuH0-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-j8nyyLbsK6CAkuH0-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-j8nyyLbsK6CAkuH0-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-j8nyyLbsK6CAkuH0-license').classList.add = "no-license"
};
document.getElementById('repo-j8nyyLbsK6CAkuH0-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for run-llama\/llama_index.")
}).catch(err =&gt; {
const c = document.getElementById('repo-j8nyyLbsK6CAkuH0-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for run-llama\/llama_index.")
})
&lt;/script&gt;
&lt;p&gt;LlamaIndex（GPT 索引）是用于 LLM 应用程序的数据框架。使用 LlamaIndex 构建应用程序通常需要使用 LlamaIndex 核心和一组选定的集成（或插件）。在 Python 中使用 LlamaIndex 构建应用程序有两种方法：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;启动器： &lt;code&gt;llama-index&lt;/code&gt; ( &lt;a class="link" href="https://pypi.org/project/llama-index/" target="_blank" rel="noopener" &gt;https://pypi.org/project/llama-index/
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
)。Python 入门包，包括核心 LlamaIndex 以及部分集成。&lt;/li&gt;
&lt;li&gt;定制化：&lt;code&gt;llama-index-core&lt;/code&gt; ( &lt;a class="link" href="https://pypi.org/project/llama-index-core/" target="_blank" rel="noopener" &gt;https://pypi.org/project/llama-index-core/
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
)。安装核心 LlamaIndex，并在 LlamaHub 上添加应用程序所需的 LlamaIndex 集成包。目前有 300 多个 LlamaIndex 集成包可与核心无缝协作，让你可以使用自己喜欢的 LLM、嵌入和向量存储数据库进行构建&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;LlamaIndex Python 库是以名字命名的，因此包含 &lt;code&gt;core&lt;/code&gt; 的导入语句意味着使用的是核心包。相反，那些不含 &lt;code&gt;core&lt;/code&gt; 的语句则意味着使用的是集成包。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&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="c1"&gt;# typical pattern&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.core.xxx&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ClassABC&lt;/span&gt; &lt;span class="c1"&gt;# core submodule xxx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.xxx.yyy&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;SubclassABC&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&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="c1"&gt;# integration yyy for submodule xxx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# concrete example&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.core.llms&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;LLM&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;llama_index.llms.openai&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;OpenAI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="crewai"&gt;
&lt;a href="#crewai" class="header-anchor"&gt;#&lt;/a&gt;
CrewAI
&lt;/h3&gt;
&lt;a href="https://github.com/joaomdmoura/crewAI" target="_blank" class="card-github fetch-waiting no-styling"
repo="joaomdmoura/crewAI" id="repo-BTxAFAqkOtlrXWzq-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-BTxAFAqkOtlrXWzq-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;joaomdmoura&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;crewAI&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-BTxAFAqkOtlrXWzq-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-BTxAFAqkOtlrXWzq-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-BTxAFAqkOtlrXWzq-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-BTxAFAqkOtlrXWzq-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-BTxAFAqkOtlrXWzq-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-BTxAFAqkOtlrXWzq-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/joaomdmoura\/crewAI', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-BTxAFAqkOtlrXWzq-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-BTxAFAqkOtlrXWzq-language').innerText = data.language;
document.getElementById('repo-BTxAFAqkOtlrXWzq-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-BTxAFAqkOtlrXWzq-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-BTxAFAqkOtlrXWzq-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-BTxAFAqkOtlrXWzq-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-BTxAFAqkOtlrXWzq-license').classList.add = "no-license"
};
document.getElementById('repo-BTxAFAqkOtlrXWzq-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for joaomdmoura\/crewAI.")
}).catch(err =&gt; {
const c = document.getElementById('repo-BTxAFAqkOtlrXWzq-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for joaomdmoura\/crewAI.")
})
&lt;/script&gt;
&lt;p&gt;CrewAI 是一个构建 AI Agent 的框架，可以将 LLM 与其他工具和 API 集成，实现更复杂的任务，例如自动执行网页操作、生成代码等。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;主要特点：&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;基于角色的智能体设计&lt;/strong&gt;：你可以使用特定的角色、目标和工具来自定义智能体。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;自主智能体间委托&lt;/strong&gt;：智能体可以自主地将任务委托给其他智能体，并相互查询信息，从而提高解决问题的效率。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;灵活的任务管理&lt;/strong&gt;：可以使用可定制的工具来定义任务，并动态地将任务分配给智能体。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;流程驱动&lt;/strong&gt;：该系统以流程为中心，目前支持按顺序执行任务和分层流程。未来还会支持更复杂的流程，例如协商和自主流程。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;保存输出为文件&lt;/strong&gt;：可以将单个任务的输出保存为文件，以便以后使用。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;将输出解析为 Pydantic 或 Json&lt;/strong&gt;：可以将单个任务的输出解析为 Pydantic 模型或 Json 格式，以便于后续处理和分析。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;支持开源模型&lt;/strong&gt;：可以使用 OpenAI 或其他开源模型来运行您的智能体团队。更多关于配置智能体与模型连接的信息，包括如何连接到本地运行的模型，请参阅&lt;a class="link" href="https://docs.crewai.com/how-to/LLM-Connections/" target="_blank" rel="noopener" &gt;将 crewAI 连接到大型语言模型
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;更多详细信息，请访问 &lt;a class="link" href="https://github.com/joaomdmoura/crewAI" target="_blank" rel="noopener" &gt;CrewAI
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h3 id="opendevin"&gt;
&lt;a href="#opendevin" class="header-anchor"&gt;#&lt;/a&gt;
OpenDevin
&lt;/h3&gt;
&lt;a href="https://github.com/opendevin/opendevin" target="_blank" class="card-github fetch-waiting no-styling"
repo="opendevin/opendevin" id="repo-gsitDIcu0YlSlOF5-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-gsitDIcu0YlSlOF5-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;opendevin&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;opendevin&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-gsitDIcu0YlSlOF5-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-gsitDIcu0YlSlOF5-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-gsitDIcu0YlSlOF5-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-gsitDIcu0YlSlOF5-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-gsitDIcu0YlSlOF5-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-gsitDIcu0YlSlOF5-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/opendevin\/opendevin', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-gsitDIcu0YlSlOF5-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-gsitDIcu0YlSlOF5-language').innerText = data.language;
document.getElementById('repo-gsitDIcu0YlSlOF5-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-gsitDIcu0YlSlOF5-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-gsitDIcu0YlSlOF5-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-gsitDIcu0YlSlOF5-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-gsitDIcu0YlSlOF5-license').classList.add = "no-license"
};
document.getElementById('repo-gsitDIcu0YlSlOF5-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for opendevin\/opendevin.")
}).catch(err =&gt; {
const c = document.getElementById('repo-gsitDIcu0YlSlOF5-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for opendevin\/opendevin.")
})
&lt;/script&gt;
&lt;p&gt;OpenDevin 是一个由人工智能和 LLMs 驱动的自主软件工程师平台。&lt;/p&gt;
&lt;p&gt;OpenDevin 智能体与人类开发人员合作编写代码、修复错误和发布功能。&lt;/p&gt;
&lt;p&gt;详细信息，请访问 &lt;a class="link" href="https://github.com/opendevin/opendevin" target="_blank" rel="noopener" &gt;OpenDevin
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
的项目主页。&lt;/p&gt;
&lt;h2 id="模型评测"&gt;
&lt;a href="#%e6%a8%a1%e5%9e%8b%e8%af%84%e6%b5%8b" class="header-anchor"&gt;#&lt;/a&gt;
模型评测
&lt;/h2&gt;&lt;p&gt;为了选择合适的 LLM 并评估其性能，我们需要进行模型评测：&lt;/p&gt;
&lt;h3 id="lmsys"&gt;
&lt;a href="#lmsys" class="header-anchor"&gt;#&lt;/a&gt;
LMSys
&lt;/h3&gt;&lt;p&gt;LMSys Org 是由加州大学伯克利分校的学生和教师与加州大学圣地亚哥分校以及卡内基梅隆大学合作成立的开放式研究组织。&lt;/p&gt;
&lt;p&gt;目标是通过共同开发开放模型、数据集、系统和评估工具，使大型模型对每个人都可访问。训练大型语言模型并广泛提供它们的应用，同时也在开发分布式系统以加速它们的训练和推理过程。&lt;/p&gt;
&lt;p&gt;目前，LMSys Chatbot Area 是最被认可的大模型排行榜之一，受多家公司和研究机构的认可。&lt;/p&gt;
&lt;p&gt;排行榜地址：&lt;a class="link" href="https://arena.lmsys.org/" target="_blank" rel="noopener" &gt;https://arena.lmsys.org/
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;h3 id="opencompass"&gt;
&lt;a href="#opencompass" class="header-anchor"&gt;#&lt;/a&gt;
OpenCompass
&lt;/h3&gt;&lt;p&gt;OpenCompass 是一个 LLM 评估平台，支持 100 多个数据集上的各种模型（Llama3、Mistral、InternLM2、GPT-4、LLaMa2、Qwen、GLM、Claude 等）。&lt;/p&gt;
&lt;a href="https://github.com/open-compass/opencompass" target="_blank" class="card-github fetch-waiting no-styling"
repo="open-compass/opencompass" id="repo-PTAnDD1LKPg6UH4t-card"&gt;
&lt;div class="gc-titlebar"&gt;
&lt;div class="gc-titlebar-left"&gt;
&lt;div class="gc-owner"&gt;
&lt;div id="repo-PTAnDD1LKPg6UH4t-avatar" class="gc-avatar"&gt;&lt;/div&gt;
&lt;div class="gc-user"&gt;open-compass&lt;/div&gt;
&lt;/div&gt;
&lt;div class="gc-divider"&gt;/&lt;/div&gt;
&lt;div class="gc-repo"&gt;opencompass&lt;/div&gt;
&lt;/div&gt;
&lt;div class="github-logo"&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;div id="repo-PTAnDD1LKPg6UH4t-description" class="gc-description"&gt;Waiting for api.github.com...&lt;/div&gt;
&lt;div class="gc-infobar"&gt;
&lt;div id="repo-PTAnDD1LKPg6UH4t-stars" class="gc-stars"&gt;0&lt;/div&gt;
&lt;div id="repo-PTAnDD1LKPg6UH4t-forks" class="gc-forks"&gt;0&lt;/div&gt;
&lt;div id="repo-PTAnDD1LKPg6UH4t-license" class="gc-license"&gt;unkown&lt;/div&gt;
&lt;div id="repo-PTAnDD1LKPg6UH4t-language" class="gc-language"&gt;Waiting...&lt;/div&gt;
&lt;/div&gt;
&lt;/a&gt;
&lt;script id="repo-PTAnDD1LKPg6UH4t-script" type="text/javascript" defer&gt;
fetch('https://api.cuterwrite.top/api/repos/open-compass\/opencompass', {
referrerPolicy: "no-referrer"
})
.then(response =&gt; response.json())
.then(data =&gt; {
document.getElementById('repo-PTAnDD1LKPg6UH4t-description').innerText = data.description.replace(
/:[a-zA-Z0-9_]+:/g, '');
document.getElementById('repo-PTAnDD1LKPg6UH4t-language').innerText = data.language;
document.getElementById('repo-PTAnDD1LKPg6UH4t-forks').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.forks).replaceAll("\u202f", '');
document.getElementById('repo-PTAnDD1LKPg6UH4t-stars').innerText = Intl.NumberFormat('en-us', {
notation: "compact",
maximumFractionDigits: 1
}).format(data.stargazers_count).replaceAll("\u202f", '');
const avatarEl = document.getElementById('repo-PTAnDD1LKPg6UH4t-avatar');
avatarEl.style.backgroundImage = 'url(' + data.owner.avatar_url + ')';
avatarEl.style.backgroundColor = 'transparent';
if (data.license?.spdx_id) {
document.getElementById('repo-PTAnDD1LKPg6UH4t-license').innerText = data.license.spdx_id
} else {
document.getElementById('repo-PTAnDD1LKPg6UH4t-license').classList.add = "no-license"
};
document.getElementById('repo-PTAnDD1LKPg6UH4t-card').classList.remove("fetch-waiting");
console.log("[GITHUB-CARD] Loaded card for open-compass\/opencompass.")
}).catch(err =&gt; {
const c = document.getElementById('repo-PTAnDD1LKPg6UH4t-card');
c.classList.add("fetch-error");
console.warn("[GITHUB-CARD] (Error) Loading card for open-compass\/opencompass.")
})
&lt;/script&gt;
&lt;h3 id="open-llm-leaderboard"&gt;
&lt;a href="#open-llm-leaderboard" class="header-anchor"&gt;#&lt;/a&gt;
Open LLM Leaderboard
&lt;/h3&gt;&lt;p&gt;Open LLM Leaderboard 是一个持续更新的 LLM 排行榜，根据多个评测指标对不同模型进行排名，方便开发者了解最新的模型性能和发展趋势。&lt;/p&gt;
&lt;p&gt;排行榜地址：&lt;a class="link" href="https://huggingface.co/spaces/open-llm-leaderboard/open_llm_leaderboard" target="_blank" rel="noopener" &gt;https://huggingface.co/spaces/open-llm-leaderboard/open_llm_leaderboard
&lt;span style="white-space: nowrap;"&gt;&lt;svg width=".8em" height=".8em" viewBox="0 0 21 21"
xmlns="http://www.w3.org/2000/svg"&gt;
&lt;path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" /&gt;
&lt;path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z"
fill="currentColor"&gt;
&lt;/svg&gt;&lt;/span&gt;
&lt;/a&gt;
&lt;/p&gt;
&lt;h2 id="总结"&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;#&lt;/a&gt;
总结
&lt;/h2&gt;&lt;p&gt;LLM 生态正在蓬勃发展，涵盖了从模型训练到应用落地的各个环节。相信随着技术的不断进步，LLM 将会在更多领域发挥重要作用，为我们带来更加智能的应用体验。&lt;/p&gt;</description></item><item><title>RDMA 之 Memory Window</title><link>https://cuterwrite.top/p/rdma-memory-window/</link><pubDate>Wed, 26 Jun 2024 23:55:00 +0000</pubDate><guid>https://cuterwrite.top/p/rdma-memory-window/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/2024-06-16_116373724_p0_master1200.webp" alt="Featured image of post RDMA 之 Memory Window" /&gt;&lt;p&gt;&lt;strong&gt;本文欢迎非商业转载，转载请注明出处。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;声明：仅用于收藏，便于阅读&lt;/p&gt;&lt;span class="cite"&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;Savir, &lt;/span&gt;&lt;a href="https://zhuanlan.zhihu.com/p/353590347"&gt;&lt;cite&gt;知乎专栏：14. RDMA 之 Memory Window&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;strong&gt;本文是“RDMA 杂谈”专栏文章的第 14 篇，欢迎转载，转载请注明出处&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;我们在 &lt;a class="link" href="https://cuterwrite.top/p/rdma-mr/" &gt;【RDMA 之 Memory Region】
&lt;/a&gt;
一文中介绍过 Memory Region，它是一片由用户注册的特殊的内存区域：一方面其中的内容不会被换页到硬盘中，另一方面 RDMA 网卡中记录了它的地址转换关系，使得硬件拿到用户指定在 WR 中的虚拟地址之后找到对应的物理地址。&lt;/p&gt;
&lt;p&gt;本文我们来讲解 Memory Window 的概念，它是一种基于 Memory Region 的、更灵活的内存管理单元。除了 MW 的概念之外，本文也会更详细的介绍一些 RDMA 领域的内存相关概念，比如 L_Key/R_Key 等。本文配合 &lt;a class="link" href="https://cuterwrite.top/p/rdma-mr/" &gt;【RDMA 之 Memory Region】
&lt;/a&gt;
阅读效果更佳，建议先读者温习一下。&lt;/p&gt;
&lt;h2 id="memory-window-是什么"&gt;
&lt;a href="#memory-window-%e6%98%af%e4%bb%80%e4%b9%88" class="header-anchor"&gt;#&lt;/a&gt;
Memory Window 是什么
&lt;/h2&gt;&lt;p&gt;Memory Window 简称 MW，中文就翻译成内存窗口吧。是一种由用户申请的，用于让远端节点访问本端内存区域的 RDMA 资源。每个 MW 都会绑定（称为 bind）在一个已经注册的 MR 上，但是它相比于 MR 可以提供更灵活的权限控制。MW 可以粗略理解为是 MR 的子集，一个 MR 上可以划分出很多 MW，每个 MW 都可以设置自己的权限。MW 和 MR 的关系如下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_1.webp"
alt="2024-06-28_12_1" width="30%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;MR 与 MW 的关系&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="内存的访问权限控制"&gt;
&lt;a href="#%e5%86%85%e5%ad%98%e7%9a%84%e8%ae%bf%e9%97%ae%e6%9d%83%e9%99%90%e6%8e%a7%e5%88%b6" class="header-anchor"&gt;#&lt;/a&gt;
内存的访问权限控制
&lt;/h2&gt;&lt;p&gt;为了后文说明为何设计 MW，我们先来把 MR 和 MW 都涉及的权限控制讲解一下。&lt;/p&gt;
&lt;h3 id="mrmw-的权限配置"&gt;
&lt;a href="#mrmw-%e7%9a%84%e6%9d%83%e9%99%90%e9%85%8d%e7%bd%ae" class="header-anchor"&gt;#&lt;/a&gt;
MR/MW 的权限配置
&lt;/h3&gt;&lt;p&gt;这里的权限，指的是本端/对端节点，对于本端内存的读/写权限，它们两两组合形成了四种权限：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;本端&lt;/th&gt;
&lt;th&gt;对端&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;读&lt;/td&gt;
&lt;td&gt;Local Read&lt;/td&gt;
&lt;td&gt;Remote Read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;写&lt;/td&gt;
&lt;td&gt;Local Write&lt;/td&gt;
&lt;td&gt;Remote Write&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;除了这四种权限之外，还有 Atomic 权限等，不在本文讨论范围内。&lt;/p&gt;
&lt;p&gt;上表中这四种权限中最低的是本地读（Local Read），是用户必须赋予 MR/MW 的权限，因为如果一块内存本地的用户都无法访问的话，那就失去意义了；另外还有个限制，如果某个 MR 需要配置远端写（Remote Write）或者还没介绍的远端原子操作权限（Remote Atomic），那么也一定要配置本地写（Local Write）权限。在此约束之下，每个 MR 或者 MW 都可以按需配置权限，比如我们注册的一个 MR 需要允许远端节点写入数据，而不允许读，那么我们就打开 Remote Write 权限，关闭 Remote Read 权限。这样 HCA（网卡）收到对端发起的对这个 MR 范围内的某个地址的 WRITE 请求之后，就可以予以放行；而 HCA 收到对端对这个 MR 的 READ 操作时，就会拒绝这个请求，并返回错误信息给对端。&lt;/p&gt;
&lt;h3 id="memory-key"&gt;
&lt;a href="#memory-key" class="header-anchor"&gt;#&lt;/a&gt;
Memory Key
&lt;/h3&gt;&lt;p&gt;上述的访问权限配置，并不能杜绝恶意用户对于本地或者远端内存的访问。比如某个节点给了一块内存区域的 Remote Write 权限，那么岂不是任意远端节点（进程）只要传入了合法的地址信息，都可以对这片区域进行写入了？因此，IB 规范设计了 Memory Key，简单理解它就是访问 MR 的钥匙机制，只有持有正确的钥匙，才能打开 MR/MW 的大门。&lt;/p&gt;
&lt;p&gt;Key 是一串数字，由两部分组成：24bit 的 Index 以及 8bit 的 Key：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_2.webp"
alt="2024-06-28_12_2" width="60%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;L_Key/R_Key 的组成&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;其中，Index 用于 HCA 快速索引到本地的虚拟-物理地址转换表等 MR 相关的信息，而 Key 用于校验整个字段的合法性，以防止未授权的用户任意传递 Index。&lt;/p&gt;
&lt;p&gt;Memory Key 按照用途分为两种，Local Key 和 Remote Key：&lt;/p&gt;
&lt;h4 id="l_key"&gt;
&lt;a href="#l_key" class="header-anchor"&gt;#&lt;/a&gt;
L_Key
&lt;/h4&gt;&lt;p&gt;即 Local Key，关联到一个 MR 上，用于 HCA 访问本端内存。当本端的某个进程试图使用一个已经注册的 MR 的内存时，HCA 会校验其传递的 L_Key。并且利用 L_Key 中的索引查找地址转换表，把虚拟地址翻译成物理地址然后访问内存。&lt;/p&gt;
&lt;p&gt;我们在 &lt;a class="link" href="https://cuterwrite.top/p/rdma-shared-receive-queue/" &gt;【RDMA 之 Shared Receive Queue】
&lt;/a&gt;
一文中描述过 sge，sge 由起始地址、长度和秘钥组成。用户在填写 WR 时，如果需要 HCA 访问本端内存，那么就需要通过一个 sge 的链表（sgl）来描述内存块，这里 sge 的秘钥填的就是 L_Key，也就是下图中的 key1 和 key3，他们分别是 MR1 的 L_Key 和 MR2 的 L_Key。如果没有 L_Key，那么任何一个本地用户进程都可以指挥硬件访问其他本地用户注册的 MR 的内容，硬件也难以高效的将虚拟地址翻译成物理地址。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_3.webp"
alt="2024-06-28_12_3" width="50%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;L_Key 的作用&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id="r_key"&gt;
&lt;a href="#r_key" class="header-anchor"&gt;#&lt;/a&gt;
R_Key
&lt;/h4&gt;&lt;p&gt;即 Remote Key，关联到一个 MR 或者 MW 上，用于远端节点访问本端内存。当远端节点试图访问本端的内存时，一方面本端的 HCA 会校验 R_Key 是否合法，另一方面会利用 R_Key 中的索引查地址转换表，把虚拟地址翻译成物理地址然后访问内存。&lt;/p&gt;
&lt;p&gt;凡是 RDMA 操作（即 Write/Read/Atomic），用户都要在 WR 中携带远端内存区域的 R_Key。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_4.webp"
alt="2024-06-28_12_4" width="70%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;R_Key 的作用&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;IB 规范通过上述两种机制，来确保 MR 可以按照用户的期望被正确且安全的访问。我们用一个比喻来总结下 MR/MW 权限控制相关的内容：&lt;/p&gt;
&lt;p&gt;A 给自己的房间（MR）配了两把钥匙（Memory Key），一把留作自用（L_Key），另一把钥匙（R_Key）邮寄（可以是任何通信方式）给了 B。B 可以在 A 不在家的时候（本端 CPU 不感知远端节点对本地内存的 RDMA 操作），通过钥匙（R_Key）打开门。打开门之后，可能 B 只能隔着玻璃查看房间的摆设（A 只给了这个 MR 远程读权限），或者进入房间内发现漆黑一片什么也看不到，但是可以向房间里放物品（A 只给了这个 MR 远程写权限），当然也有可能没有玻璃也开了灯（同时给了远程读写权限）。&lt;/p&gt;
&lt;h2 id="为什么要有-mw"&gt;
&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e6%9c%89-mw" class="header-anchor"&gt;#&lt;/a&gt;
为什么要有 MW
&lt;/h2&gt;&lt;p&gt;简而言之，设计 MW 的目的就是想更灵活的控制内存的远程访问权限。&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://cuterwrite.top/p/rdma-mr/" &gt;【RDMA 之 Memory Region】
&lt;/a&gt;
一文中我们介绍过用户注册 MR 的过程，需要从用户态陷入内核态，调用内核提供的函数 pin 住内存（防止换页），然后制作虚拟-物理地址映射表并下发给硬件。&lt;/p&gt;
&lt;p&gt;因为 MR 是由内核管理的，如果用户想修改一个已经存在的 MR 的信息，比如我想收回某个 MR 的远端写权限，只保留远端读权限；或者想要使一个之前已经授权给远端节点的 R_Key 失效，那么用户需要通过重注册 MR（Reregister MR）接口来进行修改，该接口等价于先取消注册 MR（Deregister MR），然后注册 MR（Register MR）。&lt;strong&gt;上述流程需要陷入内核态来完成，而这个过程是耗时较长的&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;不同于需要通过控制路径修改权限的 MR，&lt;strong&gt;MW 在创建好之后，可以通过数据路径（即通过用户态直接下发 WR 到硬件的方式）动态的绑定到一个已经注册的 MR 上，并同时设置或者更改其访问权限，这个过程的速度远远超过重新注册 MR 的过程&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;那么现在为了使一片内存能够被远端节点进行 RDMA WRITE/READ 操作，我们就拥有了注册 MR 以及注册 MW 然后绑定到一个已注册的 MR 两种方式，它们都会产生一个 R_Key 来提供给远端节点。前一种方式准备阶段的步骤简单，但是不够灵活，一旦注册之后修改起来会比较麻烦；后一种方式相比前一种多了注册 MW 和绑定 MW 到 MR 两种操作，但是可以方便迅速的控制远端访问权限。&lt;/p&gt;
&lt;h2 id="mw-和-mr-权限的关系"&gt;
&lt;a href="#mw-%e5%92%8c-mr-%e6%9d%83%e9%99%90%e7%9a%84%e5%85%b3%e7%b3%bb" class="header-anchor"&gt;#&lt;/a&gt;
MW 和 MR 权限的关系
&lt;/h2&gt;&lt;p&gt;也许有的读者会想到，MR 申请时配置了自己的权限，MW 绑定到 MR 时也会配置自己的权限，这两者的权限是什么关系呢？IB 规范在 10.6.7.2.2 节有专门介绍：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;When binding a Memory Window, a Consumer can request any combination of remote access rights for the Window. However, if the associated Region does not have local write access enabled and the Consumer requests remote write or remote atomic access for the Window, the Channel Interface must return an error either at bind time or access time.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;总结来说，&lt;strong&gt;如果想要给 MW 配置远程写或者远程原子操作（Atomic）权限，那么它绑定到的 MR 必须有本地写权限，其他情况下两者权限互不干扰&lt;/strong&gt;：远端用户用 MW，就要遵循 MW 的权限配置；远端用户用 MR，就要遵循 MR 的权限配置。&lt;/p&gt;
&lt;h2 id="用户接口"&gt;
&lt;a href="#%e7%94%a8%e6%88%b7%e6%8e%a5%e5%8f%a3" class="header-anchor"&gt;#&lt;/a&gt;
用户接口
&lt;/h2&gt;&lt;p&gt;老样子，用户接口时我们按照控制路径和数据路径来分类：&lt;/p&gt;
&lt;h3 id="控制路径"&gt;
&lt;a href="#%e6%8e%a7%e5%88%b6%e8%b7%af%e5%be%84" class="header-anchor"&gt;#&lt;/a&gt;
控制路径
&lt;/h3&gt;&lt;p&gt;MW 支持增、删和查，不能直接修改：&lt;/p&gt;
&lt;h4 id="创建allocate-mw"&gt;
&lt;a href="#%e5%88%9b%e5%bb%baallocate-mw" class="header-anchor"&gt;#&lt;/a&gt;
创建——Allocate MW
&lt;/h4&gt;&lt;p&gt;申请 MW，主要是创建 MW 相关的软件结构和让硬件做好准备，用户需要指定后文中介绍的 MW 的类型。这个接口会产生一个 Memory Window 的句柄，用户以后可以用这个句柄指代这个 MW。&lt;/p&gt;
&lt;p&gt;注意此时 MW 没有绑定到 MR 上，处于不可从远端访问的状态。&lt;/p&gt;
&lt;h4 id="删除deallocate-mw"&gt;
&lt;a href="#%e5%88%a0%e9%99%a4deallocate-mw" class="header-anchor"&gt;#&lt;/a&gt;
删除——Deallocate MW
&lt;/h4&gt;&lt;p&gt;取消注册 MW。很好理解，就是销毁相关资源。&lt;/p&gt;
&lt;h4 id="查询query-mw"&gt;
&lt;a href="#%e6%9f%a5%e8%af%a2query-mw" class="header-anchor"&gt;#&lt;/a&gt;
查询——Query MW
&lt;/h4&gt;&lt;p&gt;查询 MW 的信息，包括 R_Key 及其状态、MW 类型以及 PD 等。&lt;/p&gt;
&lt;p&gt;需要再次强调的是，虽然这个 Verbs 在 IB 规范中有描述，但是并没有在 RDMA 软件栈中实现相关的 API。类似情况的 Verbs 接口还有不少，RDMA 软件栈以实用为原则，没有用户需求的接口一般都没有实现。&lt;/p&gt;
&lt;h3 id="数据路径"&gt;
&lt;a href="#%e6%95%b0%e6%8d%ae%e8%b7%af%e5%be%84" class="header-anchor"&gt;#&lt;/a&gt;
数据路径
&lt;/h3&gt;&lt;p&gt;MW 在数据路径有一套独特的接口，分为 Bind 和 Invalidate 两类：&lt;/p&gt;
&lt;h4 id="绑定bind"&gt;
&lt;a href="#%e7%bb%91%e5%ae%9abind" class="header-anchor"&gt;#&lt;/a&gt;
绑定——Bind
&lt;/h4&gt;&lt;p&gt;Bind(ing)意为“绑定”，指的是将一个 MW“关联”到一个已经注册的 MR 的指定范围上，并配置一定的读写权限。绑定的结果会产生一个 R_key，用户可以把这个 R_Key 传递给远端节点用于远程访问。注意一个 MW 可以被多次绑定，一个 MR 上也可以绑定多个 MW。如果一个 MR 还有被绑定的 MW，那么这个 MR 是不能被取消注册的。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_5.webp"
alt="2024-06-28_12_5" width="90%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Bind 的软硬件交互&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;Bind 有两种方式，一种是调用 Post Send 接口下发 Bind MW WR，一种是调用 Bind MW 接口。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Post Send Bind MW WR&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;前文我们讲过，相比于 MR，MW 最大的优势就是可以从数据路径快速的配置权限。Post Send Bind MW WR 操作，指的就是用户通过 post send 接口（比如 ibv_post_send()）下发一个 WR 到 SQ 中，这个 WR 的操作类型（比如 SEND/RDMA WRITE/RDMA READ）被指定为 BIND MW，此外 WR 中还携带有权限和要绑定到的 MR 的范围信息。与其他 WR 不同，下发 Bind MW 的 WR 之后，硬件并不会发送任何数据包，而是将 MW 绑定到了指定 MR 上。&lt;/p&gt;
&lt;p&gt;这种方式仅适用于后文介绍的 Type 2 的 MW。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Bind MW&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;虽然这是一个独立的接口，但是实际是在 Post Send Bind MW WR 外面又封装了一层。用户传入 MW 绑定的相关信息，包括权限及要绑定的 MR 的信息，驱动程序负责组装和下发 WR 到硬件中。该接口成功后，会将新生成的 R_Key 返回给用户。&lt;/p&gt;
&lt;p&gt;这种方式仅适用于后文介绍的 Type 1 的 MW。&lt;/p&gt;
&lt;p&gt;上述两种操作的关系是这样的：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_6.webp"
alt="2024-06-28_12_6" width="auto" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;两种 Bind 操作的关系&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h4 id="无效化invalidate"&gt;
&lt;a href="#%e6%97%a0%e6%95%88%e5%8c%96invalidate" class="header-anchor"&gt;#&lt;/a&gt;
无效化——Invalidate
&lt;/h4&gt;&lt;p&gt;Invalidate 意为无效化，指的是用户通过下发一个带有 Invalidate 操作码的 WR 到硬件而使一个 R_Key 无效的操作。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;需要强调的是，Invalidate 操作的对象是 R_Key 而不是 MW 本身，即 Invalidate 之后的效果是：远端用户无法再使用这个 R_Key 访问对应的 MW，而 MW 资源仍然存在，以后仍然可以生成新的 R_Key 给远端使用。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Invalidate 操作只能用于下文介绍的 Type 2 的 MW。&lt;/p&gt;
&lt;p&gt;按照 Invalidate 操作的发起方不同，又可以进一步分成两种：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Local Invalidate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;本地无效操作。上层用户如果想在不回收 MW 资源的情况下，收回某个远端的用户的 R_Key 的权限。那么就可以下发一个 Local Invalidate 操作到 SQ 中，硬件收到之后会对相应的 MR 的配置进行修改。成功执行之后，如果持有这个 R_Key 的远端用户想要对 MW 进行 RDMA 操作，将会被本地的硬件拒绝并返回错误。&lt;/p&gt;
&lt;p&gt;因为是本地操作，所以硬件收到这个 WR 之后也不会发送消息到链路上。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_7.webp"
alt="2024-06-28_12_7" width="60%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Local Invalidate 操作的软硬件交互&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;Remote Invalidate&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;远端无效操作。当一个远端用户不再使用一个 R_Key 之后，可以主动发送消息，让本端回收这个 R_Key。远端用户下发一个带有此操作码的 WR 到 SQ 中，其硬件收到后，将会组装一个报文并发送到本端。本端硬件收到远端的 Remote Invalidate 操作之后，将会把对应的 R_Key 置为不可用状态。同 Local Invalidate 一样，此后对端将无法使用这个 R_Key 对对应的 MW 进行 RDMA 操作。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_12_8.webp"
alt="2024-06-28_12_8" width="90%" loading="lazy"&gt;&lt;figcaption&gt;
&lt;h4&gt;Remote Invalidate 操作的软硬件交互&lt;/h4&gt;
&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h2 id="mw-的类型"&gt;
&lt;a href="#mw-%e7%9a%84%e7%b1%bb%e5%9e%8b" class="header-anchor"&gt;#&lt;/a&gt;
MW 的类型
&lt;/h2&gt;&lt;p&gt;根据实现和应用场景的不同，IB 规范对 MW 进行了分类：&lt;/p&gt;
&lt;h3 id="type-1"&gt;
&lt;a href="#type-1" class="header-anchor"&gt;#&lt;/a&gt;
Type 1
&lt;/h3&gt;&lt;p&gt;Type 1 的 MW 通过 PD 和一个 QP 关联，不会绑定到一个 QP 上，所以也不会影响销毁同一个 PD 下的 QP。&lt;/p&gt;
&lt;p&gt;Type 1 的 MW 的 R_Key 的 key 域段由驱动和硬件掌握，这里“掌握”的意思是，由驱动和硬件分配 key，而不是上层用户。这也是前文中说 Type 1 的 MW 不能被执行 Invalidate 操作的原因。如果 Type 1 MW 的用户想要使一个 R_Key 失效，那么重新通过 Bind MW 接口绑定一次这个 MW，硬件或者驱动就回自动分配一个新的 R_Key 的 key 域段，原有的 R_Key 也就失效了。&lt;/p&gt;
&lt;p&gt;此外，如果用户暂时想要使一个 MW 不再绑定到任何 MR，但是又想保留相关的资源而不是销毁这个 MW，那么可以通过调用 Bind MW 接口，并将 MW 长度设置为 0 来实现。&lt;/p&gt;
&lt;p&gt;IB 规范允许多个 Type 1 MW 绑定到同一个 MR 上，范围可以相互覆盖。&lt;/p&gt;
&lt;h3 id="type-2"&gt;
&lt;a href="#type-2" class="header-anchor"&gt;#&lt;/a&gt;
Type 2
&lt;/h3&gt;&lt;p&gt;Type 2 的 MW 赋予了用户更大的自由度，其 R_Key 的 key 域段由用户掌握，即用户想怎么分配就怎么分配。前文已经讲过，用户通过 Post Send Bind MW WR 操作来进行绑定，这个过程并不会返回 R_Key。用户必须记住 Allocate MW 时的 index，并且和其选择的 8 bit key 组成 R_Key 并发送给对端。&lt;/p&gt;
&lt;p&gt;用户可以通过前文介绍过的 Invalidate 操作来使一个 R_Key 无效，如果想要分配一个新的 R_Key 到 MW 上，必须先通过 Invalidate 操作无效之前的 R_Key。&lt;/p&gt;
&lt;p&gt;与 Type 1 不同，Type 2 的 MW 不支持 0 长度的绑定。&lt;/p&gt;
&lt;p&gt;IB 规范同样也允许多个 Type 2 绑定到同一个 MR 上，范围可以相互覆盖。&lt;/p&gt;
&lt;p&gt;此外，根据绑定关系不同，Type 2 还可以分为两种实现方式，它们的差异仅在于和 QP 的绑定关系上。&lt;/p&gt;
&lt;h4 id="type-2a"&gt;
&lt;a href="#type-2a" class="header-anchor"&gt;#&lt;/a&gt;
Type 2A
&lt;/h4&gt;&lt;p&gt;通过 QPN 和一个 QP 关联，也就是说远端访问这个 MW 范围内的内存时候，除了 R_Key 之外，还必须指定正确的 QPN。如果一个 QP 上还有绑定的 Type 2A 的 MW，那么这个 QP 不可以被销毁。&lt;/p&gt;
&lt;h4 id="type-2b"&gt;
&lt;a href="#type-2b" class="header-anchor"&gt;#&lt;/a&gt;
Type 2B
&lt;/h4&gt;&lt;p&gt;通过 QPN 和 PD 与一个 QP 关联，比 Type 2A 多了个 PD 的校验，即远端通过 RDMA 操作访问 MW 的内存时，除了 QPN 要正确之外，其指定的本端 QP 的 PD 要与绑定这个 MW 时的 PD 相同。另外，与 Type 2A 不同，QP 如果还有 Type 2B MW 绑定关系时是可以被销毁的。&lt;/p&gt;
&lt;p&gt;这里 IB 规范中原有的介绍就比较分散，我们来简单总结一下几种 MW 的异同：&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Type 1&lt;/th&gt;
&lt;th&gt;Type 2A&lt;/th&gt;
&lt;th&gt;Type 2B&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;关联关系&lt;/td&gt;
&lt;td&gt;PD&lt;/td&gt;
&lt;td&gt;QP&lt;/td&gt;
&lt;td&gt;PD + QP&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;R_Key 的 key 域归属&lt;/td&gt;
&lt;td&gt;驱动+硬件&lt;/td&gt;
&lt;td&gt;用户&lt;/td&gt;
&lt;td&gt;用户&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;绑定方式&lt;/td&gt;
&lt;td&gt;Bind MW 绑定后之前的 R_Key 自动失效&lt;/td&gt;
&lt;td&gt;Post Send Bind MWWR 绑定前需要先使之前的 R_Key 无效化&lt;/td&gt;
&lt;td&gt;Post Send Bind MWWR 绑定前需要先使之前的 R_Key 无效化&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;是否支持零长度&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;是否支持 Invalidate&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;关联的 QP 是否可以被销毁&lt;/td&gt;
&lt;td&gt;-&lt;/td&gt;
&lt;td&gt;否&lt;/td&gt;
&lt;td&gt;是&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;此外，IB 规范中对上述几种类型还有如下描述：HCA 必须实现 Type 1 的 MW，另外可以仅选择实现 Type 2A 和 2B 中的一种。Type 1 和 Type 2 的 MW 可以同时关联到同一个 MR 上。因为我了解到的应用程序中使用 MW 的情况不多，所以具体在什么场景下应该使用哪种 MW 也说不出所以然来，如果读者有对这方面的了解欢迎一起交流。&lt;/p&gt;
&lt;p&gt;好了，MW 就讲到这里，到此为止 RDMA 技术中常见的资源就都介绍完了。&lt;/p&gt;
&lt;p&gt;鉴于一般支持 RDMA 的设备都比较昂贵，下一篇我将介绍如何通过软件模拟设备的方式——即 Soft-RoCE 进行一些编程实验。&lt;/p&gt;
&lt;h2 id="ib-规范相关章节"&gt;
&lt;a href="#ib-%e8%a7%84%e8%8c%83%e7%9b%b8%e5%85%b3%e7%ab%a0%e8%8a%82" class="header-anchor"&gt;#&lt;/a&gt;
IB 规范相关章节
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;3.5.3 Memory Keys 介绍&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;9.4.1.1 Invalidate 操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10.6.7 权限管理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;11.2.10.9~12 相关 Verbs 介绍&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考文档"&gt;
&lt;a href="#%e5%8f%82%e8%80%83%e6%96%87%e6%a1%a3" class="header-anchor"&gt;#&lt;/a&gt;
参考文档
&lt;/h2&gt;&lt;p&gt;[1] IB Specification Vol 1-Release-1.4&lt;/p&gt;
&lt;p&gt;[2] Linux Kernel Networking - Implementation and Theory. Chapter 13&lt;/p&gt;</description></item><item><title>RDMA 之 Shared Receive Queue</title><link>https://cuterwrite.top/p/rdma-shared-receive-queue/</link><pubDate>Wed, 26 Jun 2024 23:34:00 +0000</pubDate><guid>https://cuterwrite.top/p/rdma-shared-receive-queue/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/2024-06-16_116373922_p0_master1200.webp" alt="Featured image of post RDMA 之 Shared Receive Queue" /&gt;&lt;p&gt;&lt;strong&gt;本文欢迎非商业转载，转载请注明出处。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;声明：仅用于收藏，便于阅读&lt;/p&gt;&lt;span class="cite"&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;Savir, &lt;/span&gt;&lt;a href="https://zhuanlan.zhihu.com/p/279904125"&gt;&lt;cite&gt;知乎专栏：11. RDMA 之 Shared Receive Queue&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;我们曾在 &lt;a class="link" href="https://cuterwrite.top/p/rdma-element/" &gt;【3. RDMA 基本元素】
&lt;/a&gt;
中简单介绍了 SRQ 的概念，本文将带大家了解更多关于 SRQ 的细节。&lt;/p&gt;
&lt;h2 id="基本概念"&gt;
&lt;a href="#%e5%9f%ba%e6%9c%ac%e6%a6%82%e5%bf%b5" class="header-anchor"&gt;#&lt;/a&gt;
基本概念
&lt;/h2&gt;&lt;h3 id="什么是-srq"&gt;
&lt;a href="#%e4%bb%80%e4%b9%88%e6%98%af-srq" class="header-anchor"&gt;#&lt;/a&gt;
什么是 SRQ
&lt;/h3&gt;&lt;p&gt;全称为 Shared Receive Queue，直译为共享接收队列。我们知道，RDMA 通信的基本单位是 QP，每个 QP 都由一个发送队列 SQ 和接收队列 RQ 组成。&lt;/p&gt;
&lt;p&gt;SRQ 是 IB 协议为了给接收端节省资源而设计的。我们可以把一个 RQ 共享给所有关联的 QP 使用，这个公用的 RQ 就称为 SRQ。当与其关联的 QP 想要下发接收 WQE 时，都填写到这个 SRQ 中。然后每当硬件接收到数据后，就根据 SRQ 中的下一个 WQE 的内容把数据存放到指定位置。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_11_1.webp"
alt="2024-06-28_11_1" width="80%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="为什么要用-srq"&gt;
&lt;a href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e7%94%a8-srq" class="header-anchor"&gt;#&lt;/a&gt;
为什么要用 SRQ
&lt;/h3&gt;&lt;p&gt;通常情况下，我们向 SQ 中下任务的数量要远远超过向 RQ 中下发任务的数量。为什么呢？请先回忆一下哪些操作类型会用到 SQ，哪些又会用到 RQ。&lt;/p&gt;
&lt;p&gt;SEND/WRITE/READ 都需要通信发起方向 SQ 中下发一个 WR，而只有和 SEND 配合的 RECV 操作才需要通信响应方下发 WR 到 RQ 中（带立即数的 Write 操作也会消耗 Receive WR，我们还没讲到）。而我们又知道，SEND-RECV 这一对操作通常都是用于传递控制信息，WRITE 和 READ 才是进行大量远端内存读写操作时的主角，所以自然 SQ 的使用率是远远高于 RQ 的。&lt;/p&gt;
&lt;p&gt;每个队列都是有实体的，占用着内存以及网卡的片上存储空间。在商用场景下，QP 的数量是可能达到十万级甚至更高的，对内存容量提出了很高的要求，内存都是白花花的银子买的，SRQ 就是 IB 协议为了节省用户的内存而设计的一种机制。&lt;/p&gt;
&lt;p&gt;来看一下协议中对为什么要使用 SRQ 的官方解释（10.2.9.1 章节）：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Without SRQ, an RC, UC or UD Consumer must post the number of receive WRs necessary to handle incoming receives on a given QP. If the Consumer cannot predict the incoming rate on a given QP, because, for example, the connection has a bursty nature, the Consumer must either: post a sufficient number of RQ WRs to handle the highest incoming rate for each connection, or, for RC, let message flow control cause the remote sender to back off until local Consumer posts more WRs.&lt;/p&gt;
&lt;p&gt;• Posting sufficient WRs on each QP to hold the possible incoming rate, wastes WQEs, and the associated Data Segments, when the Receive Queue is inactive. Furthermore, the HCA doesn’t provide a way of reclaiming these WQEs for use on other connections.&lt;/p&gt;
&lt;p&gt;• Letting the RC message flow control cause the remote sender to back off can add unnecessary latencies, specially if the local Consumer is unaware that the RQ is starving.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;简单来说，就是没有 SRQ 的情况下，因为 RC/UC/UD 的接收方不知道对端什么时候会发送过来多少数据，所以必须做好最坏的打算，做好突发性收到大量数据的准备，也就是向 RQ 中下发足量的接收 WQE；另外 RC 服务类型可以利用流控机制来反压发送方，也就是告诉对端”我这边 RQ WQE 不够了“，这样发送端就会暂时放缓或停止发送数据。&lt;/p&gt;
&lt;p&gt;但是正如我们前文所说，第一种方法由于是为最坏情况准备的，大部分时候有大量的 RQ WQE 处于空闲状态未被使用，这对内存是一种极大地浪费；第二种方法虽然不用下发那么多 RQ WQE 了，但是流控是有代价的，即会增加通信时延。&lt;/p&gt;
&lt;p&gt;而 SRQ 通过允许很多 QP 共享接收 WQE（以及用于存放数据的内存空间）来解决了上面的问题。当任何一个 QP 收到消息后，硬件会从 SRQ 中取出一个 WQE，根据其内容存放接收到的数据，然后硬件通过 Completion Queue 来返回接收任务的完成信息给对应的上层用户。&lt;/p&gt;
&lt;p&gt;我们来看一下使用 SRQ 比使用普通的 RQ 可以节省多少内存&lt;sup id="fnref:1"&gt;&lt;a href="#fn:1" class="footnote-ref" role="doc-noteref"&gt;1&lt;/a&gt;&lt;/sup&gt;：&lt;/p&gt;
&lt;p&gt;假设接受数据的节点上有 N 对 QP，并且每个 QP 都可能在随机的时间收到连续的 M 个消息（每个消息都需要消耗一个 RQ 中的 WQE），&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;如果不使用 SRQ 的话，用户一共需要下发 N * M 个 RQ WQE。&lt;/li&gt;
&lt;li&gt;如果使用 SRQ 的话，用户只需要下发 K * M 个 RQ WQE，而 K 远小于 N。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这个 K 是可以由用户根据业务来配置的，如果存在大量的并发接收的情况，那么就把 K 设置大一点，否则 K 设置成个位数就足够应付一般的情况了。&lt;/p&gt;
&lt;p&gt;我们一共节省了 (N - K) * M 个 RQ WQE，RQ WQE 本身其实不是很大，大约在几个 KB 的样子，看起来好像占不了多少内存。但是如前文所说，实际上节省的还有用于&lt;strong&gt;存放数据的内存空间&lt;/strong&gt;，这可是很大一块内存了，我们用图来说明：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_11_2.webp"
alt="2024-06-28_11_2" width="80%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;上图中的 SRQ 中有两个 RQ WQE，我们看一下 RQ WQE 的内容，它们是由数个 sge（Scatter/Gather Element）组成的，每个 sge 由一个内存地址，长度和秘钥组成。有了起始地址和长度，sge 就可以指向一块连续的内存区域，那么多个 sge 就可以表示多个彼此离散的连续内存块，我们称多个 sge 为 sgl（Scatter/Gather List）。sge 在 IB 软件协议栈中随处可见（其实在整个 Linux 都很常见），可以用非常少的空间表示非常大的内存区域，IB 的用户都使用 sge 来指定发送和接收区域的。&lt;/p&gt;
&lt;p&gt;可以简单估算下每个 sge 可以指向多大的内存区域，length 是一个 32bit 的无符号整型，可以表示 4GB 的空间。假设一个 RQ WQE 最大可以存放 256 个 sge，那么一个 RQ WQE 一共就是 1TB。当然实际上不可能这么大，这里只是想直观的告诉读者 RQ WQE 背后可能占用着多大的内存空间。&lt;/p&gt;
&lt;h3 id="srqc"&gt;
&lt;a href="#srqc" class="header-anchor"&gt;#&lt;/a&gt;
SRQC
&lt;/h3&gt;&lt;p&gt;即 SRQ Context。同 QPC 一样，SRQC 是用来告知硬件跟 SRQ 有关的属性的，包括深度、WQE 大小等信息，本文不再赘述了。&lt;/p&gt;
&lt;h3 id="srqn"&gt;
&lt;a href="#srqn" class="header-anchor"&gt;#&lt;/a&gt;
SRQN
&lt;/h3&gt;&lt;p&gt;即 SRQ Number。同 QP 一样，每个节点中可能存在多个 SRQ，为了标识和区分这些 SRQ，每个 SRQ 都有一个序号，称为 SRQN。&lt;/p&gt;
&lt;h3 id="srq-的-pd"&gt;
&lt;a href="#srq-%e7%9a%84-pd" class="header-anchor"&gt;#&lt;/a&gt;
SRQ 的 PD
&lt;/h3&gt;&lt;p&gt;我们在 &lt;a class="link" href="https://cuterwrite.top/p/rdma-protection-domain/" &gt;【7. RDMA 之 Protection Domain】
&lt;/a&gt;
中介绍过 Protection Domain 的概念，它用来隔离不同的 RDMA 资源。每个 SRQ 都必须指定一个自己的 PD，可以跟自己关联的 QP 的 PD 相同，也可以不同；SRQ 之间也可以使用相同的 PD。&lt;/p&gt;
&lt;p&gt;如果在使用 SRQ 的时候，收到了数据包，那么只有在要访问的 MR 和 SRQ 处于同一个 PD 下，才会正常接收这个数据包，否则会产生立即错误。&lt;/p&gt;
&lt;h2 id="异步事件"&gt;
&lt;a href="#%e5%bc%82%e6%ad%a5%e4%ba%8b%e4%bb%b6" class="header-anchor"&gt;#&lt;/a&gt;
异步事件
&lt;/h2&gt;&lt;p&gt;我们在 &lt;a class="link" href="https://cuterwrite.top/p/rdma-completion-queue/" &gt;【10. RDMA 之 Completion Queue】
&lt;/a&gt;
一文中介绍过，IB 协议根据错误的上报方式将错误类型分为立即错误，完成错误和异步错误。其中的异步错误类似于中断/事件，所以我们有时候也称其为异步事件。每个 HCA 都会注册一个事件处理函数专门用来处理异步事件，收到异步事件后，驱动程序会对其进行必要的处理和进一步上报给用户。&lt;/p&gt;
&lt;p&gt;关于 SRQ 有一个特殊的异步事件，用来及时通知上层用户 SRQ 的状态，即 SRQ Limit Reached 事件。&lt;/p&gt;
&lt;h3 id="srq-limit"&gt;
&lt;a href="#srq-limit" class="header-anchor"&gt;#&lt;/a&gt;
SRQ Limit
&lt;/h3&gt;&lt;p&gt;SRQ 可以设置一个水线/阈值，当队列中剩余的 WQE 数量小于水线时，这个 SRQ 会就上报一个异步事件。提醒用户“队列中的 WQE 快用完了，请下发更多 WQE 以防没有地方接收新的数据”。这个水线/阈值就被称为 SRQ Limit，这个上报的事件就被称为 SRQ Limit Reached。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_11_3.webp"
alt="2024-06-28_11_3" width="30%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;因为 SRQ 是多个 QP 共享的，所以如果深度比较小的情况下，很有可能突然里面的 WQE 就用完了。所以协议设计了这种机制，来保证用户能够及时干预 WQE 不够的情况。&lt;/p&gt;
&lt;p&gt;上报异步事件之后，SRQ Limit 的值会被硬件重新设置为 0（应该是为了防止一直上报异步事件给上层）。当然用户可以不使用这个机制，只需要将 SRQ Limit 的值设为 0 即可。&lt;/p&gt;
&lt;h2 id="用户接口"&gt;
&lt;a href="#%e7%94%a8%e6%88%b7%e6%8e%a5%e5%8f%a3" class="header-anchor"&gt;#&lt;/a&gt;
用户接口
&lt;/h2&gt;&lt;h3 id="控制面"&gt;
&lt;a href="#%e6%8e%a7%e5%88%b6%e9%9d%a2" class="header-anchor"&gt;#&lt;/a&gt;
控制面
&lt;/h3&gt;&lt;p&gt;还是老四样——“增、删、改、查”：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建——Create SRQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;创建 SRQ 的时候，跟 QP 一样会申请所有 SRQ 相关的软硬件资源，比如驱动程序会申请 SRQN，申请 SRQC 的空间并向其中填写配置。创建 SRQ 时还必须指定每个 SRQ 的深度（能存放多少 WQE）以及每个 WQE 的最大 sge 数量。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;销毁——Destroy SRQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;销毁 SRQ 的所有相关软硬件资源。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改——Modify SRQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;除了 SRQ 深度等属性外，SRQ Limit 的值也是通过这个接口设置的。因为每次产生 SRQ Limit Reached 事件之后，水线的值都会被清零，所以每次都需要用户调用 Modify SRQ 重新设置水线。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查询——Query SRQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;通常是用来查询水线的配置的。&lt;/p&gt;
&lt;h3 id="数据面"&gt;
&lt;a href="#%e6%95%b0%e6%8d%ae%e9%9d%a2" class="header-anchor"&gt;#&lt;/a&gt;
数据面
&lt;/h3&gt;&lt;h3 id="post-srq-receive"&gt;
&lt;a href="#post-srq-receive" class="header-anchor"&gt;#&lt;/a&gt;
Post SRQ Receive
&lt;/h3&gt;&lt;p&gt;跟 Post Receive 一样，就是向 SRQ 中下发接收 WQE，里面包含了作为接收缓冲区的内存块的信息。需要注意的是，&lt;strong&gt;主语是 SRQ，与 QP 没有任何关系&lt;/strong&gt;，现在用户是不关心这个 SRQ 被哪些 QP 关联的。&lt;/p&gt;
&lt;h2 id="srq-和-rq-的区别"&gt;
&lt;a href="#srq-%e5%92%8c-rq-%e7%9a%84%e5%8c%ba%e5%88%ab" class="header-anchor"&gt;#&lt;/a&gt;
SRQ 和 RQ 的区别
&lt;/h2&gt;&lt;p&gt;从功能上来说，SRQ 和 RQ 一样都是用来储存接收任务书的，但是由于 SRQ 的共享性，所以其和 RQ 有一些差异。&lt;/p&gt;
&lt;h3 id="状态机"&gt;
&lt;a href="#%e7%8a%b6%e6%80%81%e6%9c%ba" class="header-anchor"&gt;#&lt;/a&gt;
状态机
&lt;/h3&gt;&lt;p&gt;我们在 &lt;a class="link" href="https://cuterwrite.top/p/rdma-queue-pair/" &gt;【9. RDMA 之 Queue Pair】
&lt;/a&gt;
中介绍过，QP 有着复杂的状态机，不同的状态下 QP 的收发能力存在差异。而 SRQ 只有非错误和错误两种状态：&lt;/p&gt;
&lt;p&gt;无论是哪种状态下，用户都可以向 SRQ 中下发 WQE，但是在错误状态下，相关联的 QP 不能从这个 SRQ 中获得收到的数据。另外在错误状态下，用户也无法查询和修改 SRQ 的属性。&lt;/p&gt;
&lt;p&gt;QP 处于错误状态时，可以通过 Modify QP 来使其回到 RESET 状态，但是对 SRQ 来说，只能通过销毁它来退出错误状态。&lt;/p&gt;
&lt;h3 id="接收流程"&gt;
&lt;a href="#%e6%8e%a5%e6%94%b6%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;#&lt;/a&gt;
接收流程
&lt;/h3&gt;&lt;p&gt;对于一个 QP 来说，RQ 和 SRQ 不能同时使用，两者需选其一，如果对一个已经关联 SRQ 的 QP 的 RQ 下发 WQE，那么会返回一个立即错误。&lt;/p&gt;
&lt;p&gt;下面我们来对比看一下 SRQ 和 RQ 的接收流程。本小结的内容是本文的重点，相信读者看过之后，就对 SRQ 的机制有比较完整的了解了。&lt;/p&gt;
&lt;h3 id="rq-的接收流程"&gt;
&lt;a href="#rq-%e7%9a%84%e6%8e%a5%e6%94%b6%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;#&lt;/a&gt;
RQ 的接收流程
&lt;/h3&gt;&lt;p&gt;首先，我们重温一下普通 RQ 的接收流程（结合发送端的完整流程请阅读 &lt;a class="link" href="https://cuterwrite.top/p/rdma-op/" &gt;【4. RDMA 操作类型】
&lt;/a&gt;
）一文）：&lt;/p&gt;
&lt;ol start="0"&gt;
&lt;li&gt;
&lt;p&gt;创建 QP。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 Post Recv 接口，用户分别向 QP2 和 QP3 的 RQ 下发接收 WQE，WQE 中包含接收到数据后放到哪块内存区域的信息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件收到数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件发现是发给 QP3 的，那么从 QP3 的 RQ 中取出 WQE1，将接收到的数据放到 WQE1 指定的内存区域。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件完成数据存放后，向 QP3 的 RQ 关联的 CQ3 产生一个 CQE，上报任务完成信息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户从 CQ3 中取出 WC（CQE），然后从指定内存区域取走数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件收到数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件发现是发送给 QP2 的，那么从 QP2 的 RQ 中取出 WQE1，将接收到的数据放到 WQE1 指定的内存区域。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件完成数据存放后，向 QP2 的 RQ 关联的 CQ2 产生一个 CQE，上报任务完成信息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户从 CQ2 中取出 WC（CQE），然后从指定内存区域取走数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_11_4.webp"
alt="2024-06-28_11_4" width="90%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="srq-的接收流程"&gt;
&lt;a href="#srq-%e7%9a%84%e6%8e%a5%e6%94%b6%e6%b5%81%e7%a8%8b" class="header-anchor"&gt;#&lt;/a&gt;
SRQ 的接收流程
&lt;/h3&gt;&lt;p&gt;而 SRQ 的接收流程有一些区别：&lt;/p&gt;
&lt;ol start="0"&gt;
&lt;li&gt;
&lt;p&gt;创建 SRQ1，并创建 QP2 和 QP3，都关联到 SRQ1 上。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;通过 Post SRQ Recv 接口，用户向 SRQ1 中下发两个接收 WQE，WQE 中包含接收到数据后放到哪块内存区域的信息。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件收到数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件发现是发给 QP3 的，从 SRQ1 中取出第一个 WQE（现在是 WQE1），根据 WQE 内容存放收到的数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;SRQ 中的每个 WQE 是“无主的“，不关联到任何一个 QP，硬件按队列顺序依次取出 WQE 就把数据放到里面了。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start="4"&gt;
&lt;li&gt;
&lt;p&gt;硬件发现 QP3 的 RQ 关联的 CQ 是 CQ3，所以向其中产生一个 CQE。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户从 CQ3 中取出 CQE，从指定内存区域取走数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;细心地读者可能会问，用户下发 WR 时，每个 WR 都指定了一些未来用来存放数据的内存区域。但是 SRQ 是一个池子，里面每个 WQE 都指向了不同的若干段内存区域。用户收到某个 QP 对应的 CQ 中的 WC 后如何知道接收到的数据存放到哪里了呢？&lt;/p&gt;
&lt;p&gt;WC 中其实有 wr_id 信息，告知用户数据放到哪个 WR（WQE）指定的内存区域了，既然 WR 是用户下发的，用户自然知道其指向的具体位置。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start="6"&gt;
&lt;li&gt;
&lt;p&gt;硬件收到数据&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件发现是发给 QP2 的，从 SRQ1 中取出第一个 WQE（现在是 WQE2），根据 WQE 内容存放收到的数据。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;硬件发现 QP2 的 RQ 关联的 CQ 是 CQ2，所以向其中产生一个 CQE。&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;用户从 CQ2 中取出 CQE，从指定内存区域取走数据。&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-28_11_5.webp"
alt="2024-06-28_11_5" width="90%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h2 id="总结"&gt;
&lt;a href="#%e6%80%bb%e7%bb%93" class="header-anchor"&gt;#&lt;/a&gt;
总结
&lt;/h2&gt;&lt;p&gt;本文首先介绍了 SRQ 的基本概念，然后是其设计初衷、相关机制和用户接口，最后对比 RQ 描述了 SRQ 的接收流程。在实际业务中，SRQ 的使用率还是蛮高的，希望读者能够深入理解。&lt;/p&gt;
&lt;p&gt;就写到这里吧，感谢阅读。下一篇我将给大家介绍下 Memeory Window。&lt;/p&gt;
&lt;h2 id="协议相关章节"&gt;
&lt;a href="#%e5%8d%8f%e8%ae%ae%e7%9b%b8%e5%85%b3%e7%ab%a0%e8%8a%82" class="header-anchor"&gt;#&lt;/a&gt;
协议相关章节
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;10.2.9 SRQ 的设计思想以及相关操作&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10.2.3 SRQ 和 QP 的 PD&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10.8.2 关联 SRQ 的 QP 和不使用 SRQ 的 QP 的关系&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10.8.5 SRQ 相关的返回 WC&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;11.5.2.4 异步事件&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="其他参考资料"&gt;
&lt;a href="#%e5%85%b6%e4%bb%96%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;#&lt;/a&gt;
其他参考资料
&lt;/h2&gt;&lt;div class="footnotes" role="doc-endnotes"&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id="fn:1"&gt;
&lt;p&gt;Linux Kernel Networking - Implement and Theory. Chapter 13. Shared Receive Queue&amp;#160;&lt;a href="#fnref:1" class="footnote-backref" role="doc-backlink"&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;</description></item><item><title>RDMA 之 Completion Queue</title><link>https://cuterwrite.top/p/rdma-completion-queue/</link><pubDate>Wed, 26 Jun 2024 23:11:00 +0000</pubDate><guid>https://cuterwrite.top/p/rdma-completion-queue/</guid><description>&lt;img src="https://cloud.cuterwrite.top/img/2024-06-16_116903369_p0_master1200.webp" alt="Featured image of post RDMA 之 Completion Queue" /&gt;&lt;p&gt;&lt;strong&gt;本文欢迎非商业转载，转载请注明出处。&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;声明：仅用于收藏，便于阅读&lt;/p&gt;&lt;span class="cite"&gt;&lt;span&gt;― &lt;/span&gt;&lt;span&gt;Savir, &lt;/span&gt;&lt;a href="https://zhuanlan.zhihu.com/p/259650980"&gt;&lt;cite&gt;知乎专栏：10. RDMA 之 Completion Queue&lt;/cite&gt;&lt;/a&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p&gt;我们曾经在前面的文章中简单介绍过 CQ，本文将更深入的讲解关于它的一些细节。阅读本文前，读者可以先温习一下这篇文章： &lt;a class="link" href="https://cuterwrite.top/p/rdma-element/" &gt;【“3. RDMA 基本元素”】
&lt;/a&gt;
。&lt;/p&gt;
&lt;h2 id="基本概念"&gt;
&lt;a href="#%e5%9f%ba%e6%9c%ac%e6%a6%82%e5%bf%b5" class="header-anchor"&gt;#&lt;/a&gt;
基本概念
&lt;/h2&gt;&lt;p&gt;我们先回顾下 CQ 的作用。CQ 意为完成队列，它的作用和 WQ（SQ 和 RQ）相反，硬件通过 CQ 中的 CQE/WC 来告诉软件某个 WQE/WR 的完成情况。再次提醒读者，对于上层用户来说一般用 WC，对于驱动程序来说，一般称为 CQE，本文不对两者进行区分。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_1.webp"
alt="2024-06-27_10_1" width="80%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;CQE 可以看作一份“报告”，其中写明了某个任务的执行情况，其中包括：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;本次完成了哪个 QP 的哪一个 WQE 指定的任务（QP Number 和 WR ID）&lt;/li&gt;
&lt;li&gt;本次任务执行了什么操作（Opcode 操作类型）&lt;/li&gt;
&lt;li&gt;本次任务执行成功/失败，失败原因是 XXX（Status 状态和错误码）&lt;/li&gt;
&lt;li&gt;&amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;每当硬件处理完一个 WQE 之后，都会产生一个 CQE 放在 CQ 队列中。如果一个 WQE 对应的 CQE 没有产生，那么这个 WQE 就会一直被认为还未处理完，这意味着什么呢？&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;涉及从内存中取数据的操作（SEND 和 WRITE）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在产生 CQE 之前，硬件可能还未发送消息，可能正在发送消息，可能对端有接收到正确的消息。由于内存区域是在发送前申请好的，所以上层软件收到对应的 CQE 之前，其必须认为这片内存区域仍在使用中，不能将所有相关的内存资源进行释放。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;涉及向内存中存放数据的操作（RECV 和 READ）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在产生 CQE 之前，有可能硬件还没有开始写入数据，有可能数据才写了一半，也有可能数据校验出错。所以上层软件在获得 CQE 之前，这段用于存放接收数据的内存区域中的内容是不可信的。&lt;/p&gt;
&lt;p&gt;总之，用户必须获取到 CQE 并确认其内容之后才能认为消息收发任务已经完成。&lt;/p&gt;
&lt;h3 id="何时产生"&gt;
&lt;a href="#%e4%bd%95%e6%97%b6%e4%ba%a7%e7%94%9f" class="header-anchor"&gt;#&lt;/a&gt;
何时产生
&lt;/h3&gt;&lt;p&gt;我们将按照服务类型（本篇只讲 RC 和 UD）和操作类型来分别说明，因为不同的情况产生 CQE 的时机和含义都不同，建议读者回顾第 4 篇&lt;a class="link" href="https://cuterwrite.top/p/rdma-op/" &gt;【“4. RDMA 基本操作”】
&lt;/a&gt;
和第 5 篇&lt;a class="link" href="https://cuterwrite.top/p/rdma-service-types/" &gt;【“5. RDMA 基本服务类型”】
&lt;/a&gt;
。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;可靠服务类型（RC）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;前面的文章说过，&lt;strong&gt;可靠意味着本端关心发出的消息能够被对端准确的接收&lt;/strong&gt;，这是通过 ACK、校验和重传等机制保证的。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SEND&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;SEND 操作需要硬件从内存中获取数据，然后组装成数据包通过物理链路发送到对端。对 SEND 来说，Client 端产生 CQE 表示&lt;strong&gt;对端已准确无误的收到数据&lt;/strong&gt;，对端硬件收到数据并校验之后，会回复 ACK 包给发送方。发送方收到这 ACK 之后才会产生 CQE，从而告诉用户这个任务成功执行了。如图所示，左侧 Client 端在红点的位置产生了本次任务的 CQE。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_2.webp"
alt="2024-06-27_10_2" width="50%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;RECV&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;RECV 操作需要硬件将收到的数据放到用户 WQE 中指定的内存区域，完成校验和数据存放动作后，硬件就会产生 CQE。如上图右侧 Server 端所示。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;WRITE&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;对于 Client 端来说，WRITE 操作和 SEND 操作是一样的，硬件会从内存中取出数据，并等待对端回复 ACK 后，才会产生 CQE。差别在于，因为 WRITE 是 RDMA 操作，对端 CPU 不感知，自然用户也不感知，所以上面的图变成了这样：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_3.webp"
alt="2024-06-27_10_3" width="50%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;READ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;READ 和 RECV 有点像，Client 端发起 READ 操作后，对端会回复我们想读取的数据，然后本端校验没问题后，会把数据放到 WQE 中指定的位置。完成上述动作后，本端会产生 CQE。READ 同样是 RDMA 操作，对端用户不感知，自然也没有 CQE 产生。这种情况上图变成了这样：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_4.webp"
alt="2024-06-27_10_4" width="50%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;不可靠服务类型（UD）&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因为不可靠的服务类型没有重传和确认机制，所以产生 CQE 表示硬件&lt;strong&gt;已经将对应 WQE 指定的数据发送出去了&lt;/strong&gt;。以前说过 UD 只支持 SEND-RECV 操作，不支持 RDMA 操作。所以对于 UD 服务的两端，CQE 产生时机如下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_5.webp"
alt="2024-06-27_10_5" width="50%" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="wq-和-cq-的对应关系"&gt;
&lt;a href="#wq-%e5%92%8c-cq-%e7%9a%84%e5%af%b9%e5%ba%94%e5%85%b3%e7%b3%bb" class="header-anchor"&gt;#&lt;/a&gt;
WQ 和 CQ 的对应关系
&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;每个 WQ 都必须关联一个 CQ，而每个 CQ 可以关联多个 SQ 和 RQ。&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;这里的所谓“关联”，指的是一个 WQ 的所有 WQE 对应的 CQE，都会被硬件放到绑定的 CQ 中，需要注意同属于一个 QP 的 SQ 和 RQ 可以各自关联不同的 CQ。如下图所示，QP1 的 SQ 和 RQ 都关联了 CQ1，QP2 的 RQ 关联到了 CQ1、SQ 关联到了 CQ2。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_6.webp"
alt="2024-06-27_10_6" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;因为每个 WQ 必须关联一个 CQ，所以用户创建 QP 前需要提前创建好 CQ，然后分别指定 SQ 和 RQ 将会使用的 CQ。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;同一个 WQ 中的 WQE，其对应的 CQE 间是保序的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;硬件是按照“先进先出”的 FIFO 顺序从某一个 WQ（SQ 或者 RQ）中取出 WQE 并进行处理的，而向 WR 关联的 CQ 中存放 CQE 时，也是遵从这些 WQE 被放到 WQ 中的顺序的。简单来说，就是谁先被放到队列里，谁就先被完成。该过程如下图所示：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_7.webp"
alt="2024-06-27_10_7" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;需要注意的是，使用 SRQ 的情况以及 RD 服务类型的 RQ 这两种情况是不保序的，本文中不展开讨论。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;不同 WQ 中的 WQE，其对应的 CQE 间是不保序的&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;前文中我们说过，一个 CQ 可能会被多个 WQ 共享。这种情况下，是不能保证这些 WQE 对应的 CQE 的产生顺序的。如下图所示（WQE 编号表示下发的次序，即 1 最先被下发，6 最后被下发）：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_8.webp"
alt="2024-06-27_10_8" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;上面的描述其实还包含了“同一个 QP 的 SQ 和 RQ 中的 WQE，其对应的 CQE 间是不保序的”的情况，这一点其实比较容易理解，SQ 和 RQ，一个负责主动发起的任务，一个负责被动接收的任务，它们本来就可以是认为是两条不同方向的通道，自然不应该相互影响。假设用户对同一个 QP 先下发了一个 Receive WQE，又下发一个 Send WQE，总不能对端不给本端发送消息，本端就不能发送消息给对端了吧？&lt;/p&gt;
&lt;p&gt;既然这种情况下 CQE 产生的顺序和获取 WQE 的顺序是不相关的，那么上层应用和驱动是如何知道收到的 CQE 关联的是哪个 WQE 呢？其实很简单，&lt;strong&gt;CQE 中指明它所对应的 WQE 的编号&lt;/strong&gt;就可以了。&lt;/p&gt;
&lt;p&gt;另外需要注意的是，即使在多个 WQ 共用一个 CQ 的情况下，“同一个 WQ 中的 WQE，其对应的 CQE 间是保序的”这一点也是一定能够保证的，即上图中的属于 WQ1 的 WQE 1、3、4 对应的 CQE 一定是按照顺序产生的，对于属于 WQ2 的 WQE 2、5、6 也是如此。&lt;/p&gt;
&lt;h3 id="cqc"&gt;
&lt;a href="#cqc" class="header-anchor"&gt;#&lt;/a&gt;
CQC
&lt;/h3&gt;&lt;p&gt;同 QP 一样，CQ 只是一段存放 CQE 的队列内存空间。硬件除了知道首地址以外，对于这片区域可以说是一无所知。所以需要提前跟软件约定好格式，然后驱动将申请内存，并按照格式把 CQ 的基本信息填写到这片内存中供硬件读取，这片内存就是 CQC。CQC 中包含了 CQ 的容量大小，当前处理的 CQE 的序号等等信息。所以把 QPC 的图稍微修改一下，就能表示出 CQC 和 CQ 的关系：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_9.webp"
alt="2024-06-27_10_9" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;h3 id="cqn"&gt;
&lt;a href="#cqn" class="header-anchor"&gt;#&lt;/a&gt;
CQN
&lt;/h3&gt;&lt;p&gt;CQ Number，就是 CQ 的编号，用来区别不同的 CQ。CQ 没有像 QP0 和 QP1 一样的特殊保留编号，本文中不再赘述了。&lt;/p&gt;
&lt;h2 id="完成错误"&gt;
&lt;a href="#%e5%ae%8c%e6%88%90%e9%94%99%e8%af%af" class="header-anchor"&gt;#&lt;/a&gt;
完成错误
&lt;/h2&gt;&lt;p&gt;IB 协议中有三种错误类型，立即错误（immediate error）、完成错误（Completion Error）以及异步错误（Asynchronous Errors)。&lt;/p&gt;
&lt;p&gt;立即错误的是“立即停止当前操作，并返回错误给上层用户”；完成错误指的是“通过 CQE 将错误信息返回给上层用户”；而异步错误指的是“通过中断事件的方式上报给上层用户”。可能还是有点抽象，我们来举个例子说明这两种错误都会在什么情况下产生：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户在 Post Send 时传入了非法的操作码，比如想在 UD 的时候使用 RDMA WRITE 操作。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;结果：产生立即错误（有的厂商在这种情况会产生完成错误）&lt;/p&gt;
&lt;p&gt;一般这种情况下，驱动程序会直接退出 post send 流程，并返回错误码给上层用户。注意此时 WQE 还没有下发到硬件就返回了。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户下发了一个 WQE，操作类型为 SEND，但是长时间没有受到对方的 ACK。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;结果：产生完成错误&lt;/p&gt;
&lt;p&gt;因为 WQE 已经到达了硬件，所以硬件会产生对应的 CQE，CQE 中包含超时未响应的错误详情。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用户态下发了多个 WQE，所以硬件会产生多个 CQE，但是软件一直没有从 CQ 中取走 CQE，导致 CQ 溢出。
结果：产生异步错误&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;因为软件一直没取 CQE，所以自然不会从 CQE 中得到信息。此时 IB 框架会调用软件注册的事件处理函数，来通知用户处理当前的错误。&lt;/p&gt;
&lt;p&gt;由此可见，它们都是底层向上层用户报告错误的方式，只是产生的时机不一样而已。IB 协议中对不同情况的错误应该以哪种方式上报做了规定，比如下图中，对于 Modify QP 过程中修改非法的参数，应该返回立即错误。&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_10.webp"
alt="2024-06-27_10_10" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;本文的重点在于 CQ，所以介绍完错误类型之后，我们着重来看一下完成错误。完成错误是硬件通过在 CQE 中填写错误码来实现上报的，一次通信过程需要发起端（Requester）和响应端（Responder）参与，具体的错误原因也分为本端和对端。我们先来看一下错误检测是在什么阶段进行的（下图对 IB 协议中 Figure 118 进行了重画）：&lt;/p&gt;
&lt;figure&gt;&lt;img src="https://cloud.cuterwrite.top/img/2024-06-27_10_11.webp"
alt="2024-06-27_10_11" width="auto" loading="lazy"&gt;
&lt;/figure&gt;
&lt;p&gt;Requester 的错误检测点有两个：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;本地错误检测&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;即对 SQ 中的 WQE 进行检查，如果检测到错误，就从本地错误检查模块直接产生 CQE 到 CQ，不会发送数据到响应端了；如果没有错误，则发送数据到对端。&lt;/p&gt;
&lt;ol start="2"&gt;
&lt;li&gt;远端错误检测&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;即检测响应端的 ACK 是否异常，ACK/NAK 是由对端的本地错误检测模块检测后产生的，里面包含了响应端是否有错误，以及具体的错误类型。无论远端错误检测的结果是否有问题，都会产生 CQE 到 CQ 中。&lt;/p&gt;
&lt;p&gt;Responder 的错误检测点只有一个：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;本地错误检测&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;实际上检测的是对端报文是否有问题，IB 协议也将其称为“本地”错误检测。如果检测到错误，则会体现在 ACK/NAK 报文中回复给对端，以及在本地产生一个 CQE。&lt;/p&gt;
&lt;p&gt;需要注意的是，上述的产生 ACK 和远端错误检测只对面向连接的服务类型有效，无连接的服务类型。比如 UD 类型并不关心对端是否收到，接收端也不会产生 ACK，所以在 Requester 的本地错误检测之后就一定会产生 CQE，无论是否有远端错误。&lt;/p&gt;
&lt;p&gt;然后我们简单介绍下几种常见的完成错误：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;RC 服务类型的 SQ 完成错误&lt;/li&gt;
&lt;li&gt;Local Protection Error
&lt;ul&gt;
&lt;li&gt;本地保护域错误。本地 WQE 中指定的数据内存地址的 MR 不合法，即用户试图使用一片未注册的内存中的数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Remote Access Error
&lt;ul&gt;
&lt;li&gt;远端权限错误。本端没有权限读/写指定的对端内存地址。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Transport Retry Counter Exceeded Error
&lt;ul&gt;
&lt;li&gt;重传超次错误。对端一直未回复正确的 ACK，导致本端多次重传，超过了预设的次数。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;RC 服务类型的 RQ 完成错误&lt;/li&gt;
&lt;li&gt;Local Access Error
&lt;ul&gt;
&lt;li&gt;本地访问错误。说明对端试图写入其没有权限写入的内存区域。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Local Length Error
&lt;ul&gt;
&lt;li&gt;本地长度错误。本地 RQ 没有足够的空间来接收对端发送的数据。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;完整的完成错误类型列表请参考 IB 协议的 10.10.3 节。&lt;/p&gt;
&lt;h2 id="用户接口"&gt;
&lt;a href="#%e7%94%a8%e6%88%b7%e6%8e%a5%e5%8f%a3" class="header-anchor"&gt;#&lt;/a&gt;
用户接口
&lt;/h2&gt;&lt;p&gt;同 QP 一样，我们依然从通信准备阶段（控制面）和通信进行阶段（数据面）来介绍 IB 协议对上层提供的关于 CQ 的接口。&lt;/p&gt;
&lt;h3 id="控制面"&gt;
&lt;a href="#%e6%8e%a7%e5%88%b6%e9%9d%a2" class="header-anchor"&gt;#&lt;/a&gt;
控制面
&lt;/h3&gt;&lt;p&gt;同 QP 一样，还是“增删改查”四种，但是可能因为对于 CQ 来说，上层用户是资源使用者而不是管理者，只能从 CQ 中读数据而不能写数据，所以对用户开放的可配的参数就只有“CQ 规格”一种。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;创建——Create CQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;创建的时候用户必须指定 CQ 的规格，即能够储存多少个 CQE，另外用户还可以填写一个 CQE 产生后的回调函数指针（下文会涉及）。内核态驱动会将其他相关的参数配置好，填写到跟硬件约定好的 CQC 中告知硬件。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;销毁——Destroy CQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;释放一个 CQ 软硬件资源，包含 CQ 本身及 CQC，另外 CQN 自然也将失效。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;修改——Resize CQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;这里名字稍微有点区别，因为 CQ 只允许用户修改规格大小，所以就用的 Resize 而不是 Modify。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;查询——Query CQ&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;查询 CQ 的当前规格，以及用于通知的回调函数指针。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;通过对比 RDMA 规范和软件协议栈，可以发现很多 verbs 接口并不是按照规范实现的。所以读者如果发现软件 API 和协议有差异时也无须感到疑惑，RDMA 技术本身一直还在演进，软件框架也处于活跃更新的状态。如果更关心编程实现，那么请以软件协议栈的 API 文档为准；如果更关心学术上的研究，那么请以 RDMA 规范为准。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="数据面"&gt;
&lt;a href="#%e6%95%b0%e6%8d%ae%e9%9d%a2" class="header-anchor"&gt;#&lt;/a&gt;
数据面
&lt;/h3&gt;&lt;p&gt;CQE 是硬件将信息传递给软件的媒介，虽然软件知道在什么情况下会产生 CQE，但是软件并不知道具体什么时候硬件会把 CQE 放到 CQ 中。在通信和计算机领域，我们把这种接收方不知道发送方什么时候发送的模式称为“异步”。我们先来举一个网卡的例子，再来说明用户如何通过数据面接口获取 CQE（WC）。&lt;/p&gt;
&lt;p&gt;网卡收到数据包后如何让 CPU 知道这件事，并进行数据包处理，有两种常见的模式：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;中断模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;当数据量较少，或者说偶发的数据交换较多时，适合采用中断模式——即 CPU 平常在做其他事情，当网卡收到数据包时，会上报中断打断 CPU 当前的任务，CPU 转而来处理数据包（比如 TCP/IP 协议栈的各层解析）。处理完数据之后，CPU 跳回到中断前的任务继续执行。&lt;/p&gt;
&lt;p&gt;每次中断都需要保护现场，也就是把当前各个寄存器的值、局部变量的值等等保存到栈中，回来之后再恢复现场（出栈），这本身是有开销的。如果业务负载较重，网卡一直都在接收数据包，那么 CPU 就会一直收到中断，CPU 将一直忙于中断切换，导致其他任务得不到调度。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;轮询模式&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以除了中断模式之外，网卡还有一种轮询模式，即收到数据包后都先放到缓冲区里，CPU 每隔一段时间会去检查网卡是否受到数据。如果有数据，就把缓冲区里的数据一波带走进行处理，没有的话就接着处理别的任务。&lt;/p&gt;
&lt;p&gt;通过对比中断模式我们可以发现，轮询模式虽然每隔一段时间需要 CPU 检查一次，带来了一定的开销，但是当业务繁忙的时候采用轮询模式能够极大的减少中断上下文的切换次数，反而减轻了 CPU 的负担。&lt;/p&gt;
&lt;p&gt;现在的网卡，一般都是中断+轮询的方式，也就是根据业务负载动态切换。&lt;/p&gt;
&lt;p&gt;在 RDMA 协议中，CQE 就相当于是网卡收到的数据包，RDMA 硬件把它传递给 CPU 去处理。RDMA 框架定义了两种对上层的接口，分别是 poll 和 notify，对应着轮询和中断模式。&lt;/p&gt;
&lt;h3 id="poll-completion-queue"&gt;
&lt;a href="#poll-completion-queue" class="header-anchor"&gt;#&lt;/a&gt;
Poll completion queue
&lt;/h3&gt;&lt;p&gt;很直白，poll 就是轮询的意思。用户调用这个接口之后，CPU 就会定期去检查 CQ 里面是否有新鲜的 CQE，如果有的话，就取出这个 CQE（注意取出之后 CQE 就被“消耗”掉了），解析其中的信息并返回给上层用户。&lt;/p&gt;
&lt;h3 id="request-completion-notification"&gt;
&lt;a href="#request-completion-notification" class="header-anchor"&gt;#&lt;/a&gt;
Request completion notification
&lt;/h3&gt;&lt;p&gt;直译过来是请求完成通知，用户调用这个接口之后，相当于向系统注册了一个中断。这样当硬件将 CQE 放到 CQ 中后，会立即触发一个中断给 CPU，CPU 进而就会停止手上的工作取出 CQE，处理后返回给用户。&lt;/p&gt;
&lt;p&gt;同样的，这两种接口使用哪种，取决于用户对于实时性的要求，以及实际业务的繁忙程度。&lt;/p&gt;
&lt;p&gt;感谢阅读，CQ 就介绍到这里，下篇打算详细讲讲 SRQ。&lt;/p&gt;
&lt;h2 id="协议相关章节"&gt;
&lt;a href="#%e5%8d%8f%e8%ae%ae%e7%9b%b8%e5%85%b3%e7%ab%a0%e8%8a%82" class="header-anchor"&gt;#&lt;/a&gt;
协议相关章节
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;9.9 CQ 错误检测和恢复&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10.2.6 CQ 和 WQ 的关系&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;10.10 错误类型及其处理&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;11.2.8 CQ 相关控制面接口&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;11.4.2 CQ 相关数据面接口&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="其他参考资料"&gt;
&lt;a href="#%e5%85%b6%e4%bb%96%e5%8f%82%e8%80%83%e8%b5%84%e6%96%99" class="header-anchor"&gt;#&lt;/a&gt;
其他参考资料
&lt;/h2&gt;&lt;p&gt;[1] Linux Kernel Networking - Implement and Theory. Chapter 13. Completion Queue&lt;/p&gt;</description></item></channel></rss>