iT邦幫忙

2026 iThome 鐵人賽

DAY 2
1
Software Development

在 AI Compiler 工程師的路上系列 第 2

Day01:從 SpacemiT K1 規格讀懂 RISC-V CPU 架構

  • 分享至 

  • xImage
  •  

目前手邊是用 Banana Pi BPI-F3 的 RISC-V 開發板,它的 SoC 是 SpacemiT K1 ,它有 8 核心、64-bit RISC-V AI CPU,支援 RVA22 Profile 和 256-bit RVV 1.0。

規格表上的專有名詞很多,但這些名詞和實際會遇到的問題有什麼相關?
像是編譯目標要怎麼設、RVV 一輪能處理多少資料、多核心要怎麼用、效能測試為什麼需要控制環境。

本篇大綱

  • 先看 K1 規格裡和 compiler / kernel有關的欄位。
  • 再拆 RV64GCVB、RVA22、RVV 1.0、Vector-256bit 這幾個名字。
  • 接著看核心數、cache、記憶體頻寬、DVFS 對 kernel 和效能測試的影響。
  • 最後整理今天學到的觀念。

我從 K1 硬體規格開始,再往 intrinsic、 kernel 調校、compiler產生程式碼的方式。後面看到 vsetvl-march、反組譯、效能測試中位數時,今天這些規格欄位就會派上用場。

先把 K1 規格翻成工程問題

從 Banana Pi 官方文件與我目前整理的資料,可以先挑出和這個系列最有關的幾個欄位:

規格 可以問的工程問題
64-bit RISC-V CPU ABI、指標寬度、Linux user space、工具鏈目標要怎麼設定?
RV64GCVB compiler是否知道目標 CPU 支援哪些 RISC-V 擴充?
RVA22 Profile 這顆 CPU 是否適合用應用處理器軟體堆疊來理解?
RVV 1.0 / 256-bit 向量 intrinsic 和compiler產生的向量程式碼一輪能處理多少元素?
8 cores 單一 RVV kernel 之外,要不要再做執行緒層級平行化?
L2 cache/ LPDDR4X 頻寬 運算子會受算術吞吐量限制,還是受記憶體搬移限制?
AI 指令 / AI 算力 這是標準 RVV 能力,還是廠商擴充 / 函式庫才用得到的能力?
DVFS / TDP 效能測試的頻率、溫度、電源策略有沒有被控制?

CPU 規格會影響後面每個實作決策:-march 怎麼寫、intrinsic 迴圈怎麼寫、資料要不要分塊、執行緒數量怎麼選、效能測試結果能不能比較。

RV64GCVB 要怎麼讀

K1 相關資料裡會看到 RV64GCVB 這種寫法。可以先拆成幾個部分:

  • RV64:64-bit RISC-V。這會影響 ABI、指標寬度、暫存器寬度和 Linux user space。
  • G:一組標準擴充的簡寫,在目前 ISA 規格中等價於 IMAFDZicsrZifencei
  • C:compressed instruction,可以把部分常見指令用 16-bit 編碼表示,對程式碼大小有幫助。
  • V:Vector Extension,也就是這系列會用到的 RVV。
  • B:bit manipulation 相關擴充的簡寫。現行的 B 包含 ZbaZbbZbs;K1 文件另外列出 Zbc

對compiler來說,這串字會先影響目標功能。compiler需要知道目標 CPU 有哪些擴充,才有機會產生對應的指令。

實作時不能直接把文件上的 RV64GCVB 原封不動貼到 -march。不同 GCC / LLVM 版本對 RISC-V 擴充 name 的接受程度不一樣,B 這類 擴充 在工具鏈裡也可能要拆成更細的 zbazbbzbczbs

所以至少要做兩個檢查:

  1. 檢查目前 toolchain 接受哪些 -march 寫法。
  2. 編譯後用反組譯檢查二進位檔裡有沒有出現預期的 RVV 指令。

後面看 PyTorch Inductor RVV 時,這件事會一直出現。原始碼裡寫了向量化還不夠,最後編出來的 .so 要真的能看到 vsetvlivle32.vvfadd.vv 這類指令,才能說它真的有產生 RVV 。

RVA22:把板子放進 Linux 軟體堆疊

RVA(RISC-V Application Profiles) 是 RISC-V 基金會為了解決硬體碎片化,和統一軟硬體基準而推出的應用處理器設定檔。設定檔的設立是為了明確定義一組強制或可選的指令集擴展,讓作業系統和軟體開發者有共同依照的標準。

然後 RVA 會定期更新,為了跟上軟硬體生態系的成熟腳步,像是我們現在有的開發板就是支援 RVA22。這些版本定義了處理器必須支援的指令集與功能基準,確保編譯出的軟體能在不同廠商的晶片上通用,但今天先不細講 RVA22 到底要求哪些擴充,讓大家有個 RVA 的概念就好。

RVV 1.0 和 Vector-256bit:為什麼下一篇會先講 vsetvl

RVV 1.0 是 RISC-V 向量擴充套件(Vector Extension)的 1.0 正式版本,用來提供高效率的可伸縮向量運算能力,特別針對 AI 和高效能計算(HPC)設計。

Banana Pi 官方文件寫 K1 支援 256-bit RVV 1.0。這個資訊對 RVV intrinsic 最直接的影響是 VLEN (向量長度)的估算。

RVV intrinsic 是一種用 C/C++ 語言寫出來的特殊函數介面,用來讓程式員不用寫組合語言,就能直接操作 RISC-V 向量擴充指令(RVV),我們後續會一直遇到,明天會再仔細介紹。

如果先用 VLEN = 256 bits 估算:

  • e32m1 一輪最多處理 8 個 float32
  • e16m1 一輪最多處理 16 個 16-bit 元素。
  • e8m1 一輪最多處理 32 個 8-bit 元素。
  • e32m2 一輪最多處理 16 個 float32,但會使用更多向量暫存器。

不過寫 RVV intrinsic 時,通常不應該把 8 直接寫死在迴圈裡。RVV 的寫法會讓程式每一輪詢問硬體目前可以處理多少元素:

for (size_t i = 0; i < n; ) {
    size_t vl = __riscv_vsetvl_e32m1(n - i);
    // 這一輪用 vl 個 float32 做 vector load / compute / store
    i += vl;
}

vsetvl 讓同一段程式可以處理尾端不足一個向量的元素,也讓程式比較容易移到不同 VLEN 的 RVV CPU 上。

Vector-256bit 仍然很有用。它可以幫我們估算每輪處理量、暫存器壓力、展開迴圈的成本,也能幫效能測試解釋為什麼某些資料型別比較容易吃到向量化效益。

補充一下這裡的 256-bit 是架構可見的 VLEN,不等於每個 cycle 都能完成 256-bit 運算。K1 文件將向量執行資源描述為兩條 128-bit 管線;實際吞吐量還會受指令類型、依賴關係、載入儲存與管線排程影響。VLMAX 可用來算 lane 數,不能直接當成效能倍數。

8 cores:RVV 和多執行緒是兩件事

K1 是 8 核心 CPU。這個規格很容易讓人直接期待 kernel 變快 8 倍,但 RVV 和多核心平行化要分開看。

RVV intrinsic 描述的是單個硬體執行緒上的向量指令。它讓一個核心在一條指令裡處理多個元素。要用到多個核心,還需要另一層執行緒層級平行化,例如 OpenMP、pthread、執行環境的執行緒池,或 SGLang 後端裡的 parallel for。

因此後面看一個 AI 運算子時,至少要分兩層問:

  • 單一核心上,RVV 有沒有讓內層迴圈變快?
  • 多核心上,執行緒切分、同步成本、資料搬移有沒有吃掉效益?

這也是效能測試需要小心的地方。單核心微型效能測試、多執行緒運算子效能測試、端到端推論效能測試,回答的是不同問題。

cache 和 LPDDR:很多 kernel 會先卡在資料搬移

K1 的 8 個核心分成兩個 4-core cluster,每個 cluster 共享 512KB L2,合計 1MB。記憶體支援 32-bit LPDDR4 / LPDDR4X,LPDDR4X 最高 2666 MT/s,理論頻寬最高 10.6 GB/s。

這些數字會影響 AI 運算子的效能判讀。像 GEMV、GEMM、attention、quantized linear 這些 kernel ,除了向量算術,也要看資料能不能留在cache裡重用。如果資料一直從 LPDDR 搬,向量算術再快也可能被記憶體頻寬限制住。

所以後面做 RVV 最佳化時還要考慮到

  • 輸入 / weight / 輸出 的資料配置。
  • 每次迴圈有多少資料重用。
  • 工作集合是否放得進cache。
  • 執行緒切分後會不會造成額外記憶體流量。
  • 效能測試的資料大小是否代表真實推論場景。

這些問題會在後面 SGLang RVV 後端和 PyTorch Inductor RVV 章節變得更具體。

AI 指令和標準 RVV 要分開看

K1 官方介紹也提到 AI 算力和 AI 指令。資料表中的 2 TOPS 與專用 AI 指令 / TCM 標在 Cluster 0。
標準 RVV intrinsic 使用的是 RISC-V Vector Extension;廠商 AI 指令通常需要廠商函式庫、特定 intrinsic、組合語言,或compiler後端額外支援。

也就是說,寫一般 __riscv_* RVV intrinsic 時,不會自動用到廠商 AI 指令。後面如果要研究這些 AI 指令,需要另外確認幾件事情

  • 有沒有公開的程式設計指南。
  • 工具鏈是否認得這些指令。
  • Linux user space 程式能不能呼叫對應函式庫或 intrinsic。
  • 效能測試是否能把標準 RVV 和廠商指令的效果分開。

今天先把它放在限制條件裡。這個系列前半會以標準 RVV、SGLang 後端、PyTorch Inductor 產生程式碼為主。

DVFS:效能測試前要先控制環境

K1 支援 DVFS,官方文件也標示 TDP 約 3 到 5W。這代表 CPU 頻率、溫度和電源策略會影響實驗結果。

做compiler或 kernel 效能測試時,這會帶來幾個實際問題:

  • 同一個二進位檔在不同頻率下跑,時間會不同。
  • 長時間效能測試可能受到溫度或電源策略影響。
  • 比較兩個 kernel 時,至少要重複跑多次,看中位數或穩定區間。
  • 如果要宣稱某個最佳化有效,要記錄板子狀態、輸入大小、執行緒數、compiler旗標。

今天先走到這裡

K1 spec
-> RV64GCVB / RVA22:決定compiler目標和作業系統/執行環境基礎能力
-> RVV 1.0 / Vector-256bit:決定 intrinsic 和向量程式碼產生的基本形狀
-> 8 cores:決定執行緒層級平行化和效能測試問題
-> L2 / LPDDR:決定分塊、資料配置、記憶體頻寬壓力
-> DVFS / TDP:決定效能測試要控制頻率、溫度與重複測量

今天讀完最大的收穫是,看到 CPU 規格時,除了問它支援什麼,還要繼續問這個欄位會影響哪一段軟體。

明天會開始寫 RVV intrinsic。我會從 __riscv_vsetvl_e32m1__riscv_vle32_v_f32m1__riscv_vfadd_vv_f32m1 這類函式開始,接著用 K1 的 256-bit 向量估算每一輪可以處理多少資料。

參考資料


上一篇
Day0:開始與終結的序章—在 AI compiler 工程師的路上
下一篇
Day02:用 RVV Intrinsic 寫第一個 Vector Add 運算子
系列文
在 AI Compiler 工程師的路上5
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言