
最近在關注 NVIDIA GPU 性能優化時看到了 SASS2MLIR 相關的一些實驗結論通過把 SASSStreaming AssemblyNVIDIA GPU 上真正執行的機器碼逆向提升到 MLIR再基于 MLIR 做一輪新的優化能夠在不少實際 kernel 上獲得約 20% 到 100% 以上的 Nvidia GPU 性能提升。這個幅度讓我很感興趣因為常規的 CUDA 優化路徑往往在 PTX 層面做到極致后就很難再看到這種量級的收益。這篇文章會圍繞 SASS2MLIR 這條技術路線展開。全文目標讀者是正在做 CUDA kernel 性能優化、關注編譯器后端、研究 MLIR 工具鏈的開發者以及想在 NVIDIA GPU 上把程序性能再往上推一步的工程團隊。讀完你會理解 SASS2MLIR 是什么、為什么能帶來這么大的性能提升、它的核心設計思路以及如何在真實項目里驗證這類優化思路。1. 背景為什么 GPU 性能優化會卡在 SASS 這一層1.1 從 CUDA C 到 SASS 的編譯路徑先帶大家梳理一條最基礎的鏈路。一個 CUDA 程序從源碼到真正在 GPU 上執行通常經歷下面幾個階段CUDA C/C 源碼 ↓ NVVM IR / PTX可移植中間表示 ↓ SASSNVIDIA GPU 真正執行的機器碼 ↓ GPU 硬件執行其中 PTX 是 NVIDIA 定義的虛擬指令集它和具體 GPU 架構解耦。PTX 代碼在安裝驅動安裝完成后會被驅動或 CUDA 后端編譯成對應的 SASS。SASS 才是 Ampere、Ada、Hopper、Blackwell 等具體 GPU 微架構上真正跑的指令。也就是說開發者寫的 CUDA C 只是第一層編譯器在生成 PTX 時已經做過一輪優化生成 SASS 時又做了一輪優化。到了 SASS 這一層指令已經從“給人看”的匯編變成了直接面對硬件微架構的機器碼。1.2 源碼層和 PTX 層優化為什么不夠很多時候大家做 CUDA 性能優化會做這樣一些事情調整線程塊大小、網格大小。改共享內存 Bank Conflict。把多個小數組訪問改成向量化訪問。手動展開循環。用__restrict__關鍵字提升編譯器優化能力。把關鍵中間變量改成register或調整作用域。這些優化在 CUDA 源碼和 PTX 層面確實有效但問題在于NVCC 把 PTX 編譯成 SASS 時后端編譯器有自己的一套寄存器分配、指令調度和指令選擇策略。它不一定完全理解算法層面你最重視的那個數據流。當你已經寫出性能不錯的 PTX 時后端再翻譯成 SASS可能引入額外的寄存器溢出、調度不夠緊湊、訪存指令沒有充分合并等問題。所以一個很自然的想法出現了能不能直接拿到 SASS反著把它“翻譯”成一種更適合做性能優化的中間表示再重新優化一輪生成更好的 SASS這就是 SASS2MLIR 這條路線的核心動機。1.3 SASS2MLIR 解決什么問題SASS2MLIR 要做的事情總結起來就是把二進制中或 cubin 中已有的 SASS 指令反編譯并提升到 MLIR在 MLIR 層對這些指令做架構相關的分析和變換最后再生成優化后的 SASS 或其他 GPU 代碼形式。它和我們熟悉的逆向工程不太一樣。普通反匯編可能只是為了讀代碼、理解邏輯而 SASS2MLIR 的目的非常明確為了重新優化。它不犧牲對底層硬件行為的精確描述同時把優化空間最充分地暴露出來。2. SASS、PTX、MLIR三個核心概念拆解2.1 SASS 指令長什么樣SASS 指令和 PTX 指令有很強的對應關系但又不完全一致。舉一個直觀的例子。PTX 中一次 32 位全局內存加載可能長這樣ld.global.f32 %r1, [%rd2];對應的 SASS 在常見 Ampere 架構上可能是LDG.E R0, [R2.64];也就是說SASS 是經過指令選擇后的真實硬件指令。它包含操作碼LDG、STG、FADD、FFMA、IMAD 等。寄存器操作數。謂詞寄存器Predicate Register用于條件執行。立即數、偏移量。內存指令的 cache hint、訪問寬度、地址空間信息。這些細節在 PTX 層可能被抽象成“全局內存加載”在 SASS 層則直接對應著具體的硬件執行行為和延遲特性。2.2 PTX 的優化局限PTX 和 GPU 微架構不完全綁定。同一個 PTX 可以在多個架構上運行這帶來了可移植性但也意味著 PTX 中的一些表示保留了一定的抽象性。例如 PTX 中的浮點指令不直接規定它目標微架構上應該用多少個周期、是否要用特殊數據路徑。真正執行性能是由 SASS 決定的。簡單來說優化一個還沒有綁定真實硬件行為的中間表示很難做到極致。PTX 是“半抽象”的SASS 是“完全具體”的。在完全具體的層面做優化有機會把每條指令的周期、流水線行為、端口壓力、寄存器壓力都納入考慮。2.3 MLIR 為什么適合做這一層優化MLIRMulti-Level Intermediate Representation是一個編譯器基礎設施框架。它不是一個單一 IR而是一整套可以自由組合的 IR 方言Dialect。MLIR 有幾個特性非常適合 SASS2MLIR多級抽象你可以創建一個自定義 Dialect把 SASS 指令用一種結構化方式表達出來。同時可以借用已有的affine、linalg、vector等方言表達循環、向量化等高層次信息。Pass 機制MLIR 提供了成熟的 Pass 管理、調試與驗證基礎設施。你可以很方便地寫一個“移除冗余指令”的 Pass然后在不同內核上測試效果。模式重寫MLIR 的PatternRewriter特別適合 SASS 層這種“小范圍指令級變換”例如把一個 32 位加載合并成 128 位加載、把多條 FFMA 合并成快速路徑指令等。可度量性和插樁MLIR 允許開發者對指令成本建模然后基于成本模型做貪心或整數規劃式調度。所以 SASS2MLIR 并不是簡單把 SASS 變成一種文本而是要利用 MLIR 生態的整套優化基建重新“編譯”一次 SASS。3. 20% 到 100% 的性能提升從哪里來根據 SASS2MLIR 主題中提到的 findings性能提升幅度大致在 20% 到 100% 以上。為什么區間這么寬因為它高度依賴內核的瓶頸類型。下面我從幾個常見的性能瓶頸維度來說明提升來源。3.1 寄存器溢出與寄存器分配優化SASS 已經是機器碼但機器碼不代表寄存器分配是最優的。后端編譯器在寄存器不足時會往局部內存溢出一部分變量而局部內存訪問實際上會落到顯存路徑延遲比寄存器高一個數量級。SASS2MLIR 會在更高一層重新構建寄存器沖突圖重新做寄存器分配。它可以看到整個 kernel 的所有 SASS 指令因此有機會消除不必要的溢出。如果一個 kernel 原本在 NSight Compute 中顯示Local Memory占用異常高那么 SASS2MLIR 通過重新分配寄存器有機會直接把局部內存訪問變成寄存器訪問。這種場景下出現 50% 到 100% 以上的提升完全合理。3.2 指令級并行ILP與調度GPU 使用大量線程來隱藏延遲但這并不意味著指令調度不重要。在同一個 warp 內如果兩條指令存在數據依賴必須等待前一條完成。SASS2MLIR 可以對指令依賴圖進行重新調度在不改變語義的前提下把無關指令穿插到數據依賴間隙中。一個調度良好的 SASS 可以把 FFMA 的延遲完全隱藏調度差的 SASS 則會讓流水線頻繁停頓。這種優化在計算密集且依賴鏈較長的 kernel 上通常能帶來 20% 到 40% 的收益。3.3 訪存指令合并與向量化SASS 層的LDG.E表示 32 位加載LDG.E.128表示 128 位加載。如果 SASS2MLIR 識別到多個對連續地址的 32 位加載并且線程的訪問模式允許合并那么可以把它變換為更寬的向量加載。這樣一來減少指令數量、減少地址計算次數、降低內存事務數。代價是需要保證數據對齊和語義一致性。SASS2MLIR 在 MLIR 層做這類模式匹配時比直接操作二進制要自然得多。這種優化在帶寬受限的 kernel 上很有效例如數據搬運類、memcpy風格、科學計算 stencil 類 kernel。3.4 冗余指令消除與特化SASS 是由編譯器自動生成的但編譯器在某些情況下會生成冗余指令。例如一個立即數被重復加載到寄存器。地址計算存在重復公共子表達式。多個分支目標相同可以合并。某些比較指令的結果被重復計算。MLIR 的 CSE公共子表達式消除、DCE死代碼消除對 SASS 層同樣適用。跑完一輪 DCE指令總數通常可以減少 5% 到 15%。指令數減少并不總是線性轉化為性能提升但如果原本指令吞吐逼近上限這個收益就非常可觀。3.5 對特定硬件特性的重新利用在 SASS 層工具鏈可以看到目標 GPU 的具體特性例如異步拷貝指令cp.async。Tensor Core 指令。L2 緩存持久性提示。特殊函數單元。不同 cache 提示.CA、.CG、.CS、.LU。SASS2MLIR 在 MLIR 層可以給這些指令建立 cost model根據實際瓶頸決定是否使用這些特性。比如一個原本使用普通LDG的 kernel如果它訪存模式更適合 L2 命中可以重新選擇帶.CAhint 的變體。這種優化機會在 CUDA 源碼層面很難自動化但在 SASS2MLIR 層面卻很自然。4. SASS2MLIR 的技術原理從 SASS 反編譯到重新生成4.1 整體流程SASS2MLIR 工具鏈大致包含以下幾個階段。cubin / 可執行文件 ↓ 階段1SASS 反匯編 ↓ SASS 指令序列文本 / 結構化對象 ↓ 階段2SASS 指令提升到 MLIR ↓ SASS-Dialect自定義方言 輔助方言 ↓ 階段3MLIR 優化 Pass ↓ 優化后的 SASS 指令表示 ↓ 階段4指令選擇與代碼生成 ↓ 優化后的 SASS / 可執行內容4.2 SASS 反匯編與指令編碼解析NVIDIA 官方提供了一些工具來查看 SASScuobjdump -sass從 cubin 中提取 SASS 匯編文本。nvdisasm對 cubin 做反匯編支持十六進制指令輸出。例如下面這個命令可以導出包含十六進制編碼的 SASScuobjdump -sass -hex example.cubin example.sass拿到 SASS 文本后需要進一步解析。SASS 是定長指令不同架構長度不同常見為 16 字節或更長。指令編碼里包含操作碼、目的地寄存器、源寄存器、謂詞、立即數、標志位等信息。解析這些字段是 SASS2MLIR 第一階段的核心工作。這一步的難點在于不同 GPU 架構的 SASS 編碼不同。Turing、Ampere、Ada、Hopper、Blackwell 的指令編碼有很多細節差異。SASS2MLIR 如果要做到跨架構就需要針對每個架構實現不同的解碼器。4.3 將 SASS 提升到 MLIR 自定義方言為了便于優化SASS2MLIR 通常會設計一個SASSDialect。每個 SASS 指令對應 dialect 中的一個 op。例如// 示意SASS Dialect 中的一條 FP32 乘加指令 %sreg0 sass.ffma %sreg1, %sreg2, %sreg3 : (f32, f32, f32) - f32同時某些 SASS 指令會對應更高級別的語義例如循環、分支、地址計算。SASS2MLIR 不一定要把它們完全還原成原始 C 代碼只要表達成可分析的 CFG控制流圖和 DFG數據流圖即可。MLIR 中一個非常有價值的設計是 Dialect 之間可以互操作。SASS Dialect 中表示的高層次指令在優化時可以利用已有的vector方言來表達向量化利用memref方言來表達內存訪問再利用affine方言來表達循環結構。這樣傳統的仿射循環優化方法也能用在 SASS 級代碼上。4.4 優化 Pass 設計SASS2MLIR 的優化 Pass 通常包括Pass 類型優化目標例子指令合并減少指令數合并相鄰 FFMA向量化提高訪存效率合并為 LDG.E.128CSE/DCE消除冗余刪除重復地址計算寄存器分配降低壓力重新分配寄存器消除溢出指令調度提高 ILP重排無依賴指令分支優化提升控制流效率合并重復分支Cache Hint 選擇利用緩存特性增加 L2 持久性 hint每個 Pass 都需要基于 SASS 的語義模型。例如指令調度 Pass 必須知道每條指令的延遲、占用哪個執行端口、是否有寫后讀依賴等。這些信息需要維護一個針對目標 microarchitecture 的 cost model。4.5 生成優化后的 SASS優化結束后SASS2MLIR 需要把優化后的 IR 變回 SASS 指令文本再通過驅動或工具重新組裝成可加載的 cubin。這一步類似于傳統后端代碼生成。由于指令選擇空間相對有限通常把 IR 映射回 SASS 指令編碼即可。注意這里不是每次都需要生成完整 cubin。在一些集成方案中SASS2MLIR 也可以輸出一個新的.sass文本然后由開發者通過自定義加載器在運行時替換 kernel 指令。5. 模擬實戰查看 SASS 并分析優化空間雖然完整搭建一套 SASS2MLIR 工具鏈工作量很大但我們可以通過一個小實驗來理解它的工作對象。下面我會帶你實際導出一個 kernel 的 SASS并用 Python 做一次簡單的指令統計找到性能優化的初步線索。5.1 環境準備我們需要一臺帶 NVIDIA GPU 的機器并安裝好 NVIDIA 驅動。CUDA Toolkit包含nvdisasm和cuobjdump。一個簡單的 CUDA kernel 和對應的.cubin文件。Python 3用來做文本分析。版本方面無需特別指定本文示例以常見 CUDA 環境為準。如果你的環境中工具版本不同命令輸出格式可能會有細微差異但整體思路不變。先準備一個最簡單的 CUDA 源文件test_kernel.cu// 文件路徑test_kernel.cu __global__ void vector_add(const float* a, const float* b, float* c, int n) { int i blockIdx.x * blockDim.x threadIdx.x; if (i n) { c[i] a[i] b[i]; } }使用 NVCC 編譯出 cubinnvcc -archsm_80 -cubin test_kernel.cu -o test_kernel.cubin這里-archsm_80表示面向 Ampere 架構生成 cubin。如果你的 GPU 是其他架構可以改成對應的 compute capability例如sm_90對應 Hopper 架構。5.2 導出 SASS 指令使用cuobjdump導出 SASScuobjdump -sass -hex test_kernel.cubin test_kernel.sass生成的test_kernel.sass中會包含 kernel 的 SASS 指令。部分輸出可能類似/*0058*/ IMAD.MOV.U32 R1, RZ, RZ, c[0x0][0x28] ; /*0060*/ !P0 IMAD.MOV.U32 R2, RZ, RZ, 0x0 ; /*0068*/ LDG.E R4, [R2.64] ; /*0070*/ LDG.E R5, [R2.640x4] ; /*0078*/ FADD R4, R4, R5 ; /*0080*/ STG.E [R2.64], R4 ;這些指令就是 SASS2MLIR 要處理的原始材料。你可以看到LDG.E、FADD、STG.E這些真實硬件指令。5.3 用 Python 做指令統計下面我們用一個簡單的 Python 腳本從 SASS 文本中統計指令類別和線程束級別行為。# 文件路徑analyze_sass.py import re from collections import Counter def parse_sass_text(text): instructions [] for line in text.splitlines(): # 匹配類似 /*0058*/ IMAD.MOV.U32 R1, RZ, RZ, c[0x0][0x28] ; m re.search(r/\*[0-9a-fA-F]\*/\s(.*?);, line) if not m: continue instr_part m.group(1).strip() if not instr_part: continue # 取第一個空格前的部分作為主操作碼例如 LDG.E、FADD、STG.E parts instr_part.split() opcode parts[0].split(.)[0] instructions.append({ full_opcode: parts[0], base_opcode: opcode, operands: instr_part }) return instructions def main(): with open(test_kernel.sass, r, encodingutf-8) as f: text f.read() instrs parse_sass_text(text) print(f共解析到 {len(instrs)} 條 SASS 指令) counter Counter(i[full_opcode] for i in instrs) print(\n完整操作碼統計) for op, cnt in counter.most_common(20): print(f{op:20s} {cnt}) base_counter Counter(i[base_opcode] for i in instrs) print(\n基礎操作碼統計) for op, cnt in base_counter.most_common(10): print(f{op:20s} {cnt}) if __name__ __main__: main()運行腳本python analyze_sass.py輸出示例共解析到 34 條 SASS 指令 完整操作碼統計 IMAD.MOV.U32 8 LDG.E 4 FADD 2 STG.E 2 ... 基礎操作碼統計 IMAD 14 LDG 4 FADD 2 STG 2 ...通過這個統計你可以初步判斷這個 kernel 是指令數很少的訪存型 kernel主要開銷應該來自全局內存訪問。SASS2MLIR 想在這個 kernel 上做進一步優化重點就應該放在是否能合并LDG.E為LDG.E.128。是否能減少IMAD地址計算指令。是否能通過調整訪存模式提升緩存命中率。5.4 在 MLIR 層構建 SASS Dialect 的示意如果你要在 MLIR 里真正實現 SASS2MLIR第一個階段就是定義 Dialect。下面是一個極其簡化的示意展示“SASS 指令提升到 MLIR op”的基本形態。實際工程中你會使用 TableGen 來定義 Dialect而不是手寫 C op。// 示意SASS Dialect 的 ops 定義思路 // 這不是完整可編譯代碼只是表達設計方向 def SASSLDGEOp : SASSOpldg_e { let summary Global load 32-bit with cache hint; let arguments (ins SASS_RegOperand:$dst, SASS_MemOperand:$addr, SASS_Predicate:$pred ); let results (outs SASS_RegOperand:$res); } def SASSFADDOp : SASSOpfadd { let summary Floating point add; let arguments (ins SASS_RegOperand:$src0, SASS_RegOperand:$src1 ); let results (outs SASS_RegOperand:$res); }你沒有必要逐行去理解這段 C/TableGen 代碼只需要知道SASS2MLIR 并不是把 SASS 當成純文本處理而是把它結構化成一個可分析、可變換、可生成代碼的 IR 圖。這正是它能做自動優化而不是簡單文本替換的基礎。5.5 驗證優化效果無論你是手工優化 SASS還是通過 SASS2MLIR 自動優化最終都要用性能分析工具驗證。推薦使用 NVIDIA Nsight Computencu --set full ./your_application重點關注幾個指標Durationkernel 執行時間。Compute (SM) Throughput計算單元利用率。Memory Throughput內存帶寬利用率。Achieved Occupancy實際占用率。Registers Per Thread每線程寄存器數。Local Memory局部內存溢出情況。如果優化后Duration下降且Compute Throughput或Memory Throughput更接近瓶頸說明優化是有效的。如果 Duration 下降不明顯甚至上升則有可能出現了指令調度變差或寄存器溢出加劇的問題。6. 常見問題與排查思路SASS2MLIR 或者圍繞 SASS 做性能優化時大家最常遇到的問題集中在下面幾個方面。6.1 反匯編和工具鏈問題問題現象常見原因解決思路nvdisasm提示架構不支持本地工具版本過舊或不認識新架構升級 CUDA Toolkit確認 cubin 與目標架構匹配cuobjdump -sass輸出為空cubin 中已剝離符號或 SASS 信息編譯時不要使用-lineinfo剝離相關選項重新生成 cubin反匯編指令格式不統一不同架構間 SASS 編碼差異需要按架構分別解析不能假設統一格式Python 正則解析不到指令文本格式變更或帶額外制表符先打印原始文本調整正則匹配規則6.2 優化后性能反而下降這是非常常見的。并不是所有 SASS 變換都能帶來正收益。問題現象常見原因解決思路kernel 耗時增加 5%~20%指令調度破壞了原本良好的訪存合并對照優化前后 SASS檢查訪存指令寬度和地址模式寄存器溢出增加向量化后寄存器壓力上升增加每個線程的寄存器上限或調整 tile 大小分支發散加劇分支合并后改變了控制流結構使用 Nsight Compute 查看 branch efficiency緩存命中率下降Cache hint 選擇不匹配回退 hint 設置改用默認策略遇到性能下降時先不要急著否定方案。先把優化前后的 SASS 用diff對比找到關鍵差異再結合 profiling 數據定位是寄存器、流水線還是訪存問題。6.3 SASS2MLIR 的通用落地困難問題現象常見原因解決思路工具鏈復雜周期長SASS 編碼多、架構多、pass 多從一個架構、一個 kernel 類型開始不做全架構覆蓋無法保證所有 kernel 語義一致SASS 中部分指令副作用難建模對內存讀寫、bar.sync、原子操作做保守處理生成 SASS 無法被驅動加載指令編碼或重定位信息不正確借助cuModuleLoadDataEx等接口調試加載流程優化結果不穩定調度算法依賴成本模型誤差引入回歸測試集對每個 kernel 維護基線數據6.4 環境相關風險還有一類問題是環境層面的。例如在 WSL、Docker 等環境中訪問 GPU或者驅動版本不一致時即使 SASS2MLIR 生成了新的代碼運行驗證也會失敗。對于這類問題建議先確保基礎 GPU 環境正常。比如在宿主機用nvidia-smi確認驅動在 WSL 里用nvidia-smi確認 WSL GPU 特性是否可用再繼續做 SASS 分析和優化。7. 最佳實踐與工程建議7.1 先從瓶頸明確的 kernel 入手SASS2MLIR 不是萬能工具。性能提升區間在 20%~100%背后是不同瓶頸帶來的不同優化空間。如果你的 kernel 已經接近理論帶寬極限SASS2MLIR 能幫你的就有限。反過來如果你的 kernel 存在明顯的寄存器溢出、指令冗余、訪存未合并那收益空間就很大。建議先用 Nsight Compute 做一次系統性 profiling找出指標最差、耗時占比最高的 2~3 個 kernel再針對它們做 SASS 層的重優化。7.2 建立完善的回歸基線SASS 層優化比源碼層優化更危險因為你離硬件語義更近一個微小的編碼錯誤就可能導致錯誤結果。建議工程上做到對每個 kernel 保存優化前 SASS 和優化后 SASS。建立正確性測試使用已知輸入輸出對比結果。對浮點 kernel設置合理的誤差閾值不要使用嚴格相等。記錄每個 kernel 的寄存器數、局部內存字節數、指令數、耗時。用 Git 管理優化腳本和 SASS 分析工具。7.3 關注架構差異不要迷信單一結論SASS2MLIR 在 Ampere 上取得的效果不一定能在 Ada 或 Hopper 上復現。不同微架構的指令延遲、端口數量、緩存行為差異很大。一個在sm_80上有效的 Load 合并策略在sm_90上可能因為異步拷貝指令更優而不再有用。所以在實際項目中一定要針對部署目標架構單獨驗證。如果生產環境 GPU 型號混雜建議在 CI 中準備多臺不同架構的測試機。7.4 保留源碼層優化能力SASS2MLIR 適合作為源碼優化的“最后一公里”而不是替代源碼優化。你應該繼續維護高質量的 CUDA C/C 源碼保持算法可讀性和可維護性。SASS2MLIR 或任何 SASS 級重新優化更像是對編譯器后端結果的一次“修補”和“再打磨”。7.5 關注相關生態CUDA、MLIR 與 GPU 容器化做 SASS 層優化時不要忽略整個 GPU 工具鏈。例如CUDA 版本升級后編譯器生成的 SASS 質量可能已經變化原來的手動優化可能不再適用。MLIR 生態目前在很多 AI 編譯器項目中已經很成熟你可以在其中找到可復用的 Dialect 和 Pass。如果程序運行在 Docker 或 Kubernetes 這類容器環境中記得提前安裝 NVIDIA Container Toolkit否則即使生成了優化后的 SASS驗證也會被環境問題卡住。這些基礎環境問題雖然聽起來瑣碎卻是真實項目中影響效率的頭號因素。8. 總結與下一步學習方向SASS2MLIR 給我最大的啟發是GPU 性能優化不應該停留在源碼或 PTX 思維中。SASS 是真實硬件執行的指令它承載了底層微架構的全部行為信息MLIR 則是現代編譯器基礎設施中最適合做高性能 IR 變換的框架。把這兩者組合起來就有了一個新的優化維度。如果你對這個方向感興趣下一步可以按這個順序學習熟練掌握cuobjdump、nvdisasm和 Nsight Compute能讀懂 SASS 指令。學習 PTX ISA 手冊中指令語義尤其是內存訪問、謂詞、地址模式。選擇一塊 Ampere 或更新的 GPU 硬件開始手工對簡單 kernel 做 SASS 級微調體會指令調度的感覺。學習 MLIR 官方教程理解 Dialect、Pass、PatternRewriter 等核心概念。嘗試為少量 SASS 指令設計一個最小的自定義 Dialect實現從文本解析到 IR 生成的小工具鏈。在真實項目中建立“源碼層優化 SASS 層優化 CI 回歸驗證”的完整流程。SASS2MLIR 這類技術可能不會成為每個 CUDA 開發者都要親手搭建的工具但它反映了一種很重要的思維任何代碼到了最終硬件層都還有進一步優化的可能。理解到這一層再看 GPU 性能優化思路會開闊很多。