Tile 程式設計 (Tile Programming)

重點總覽

項目 重點
Tile 程式模型 在整個 thread block 層級寫程式,描述對多維資料集合(tiles)的運算;compiler 把運算映射到 block 內各 thread
programmer 職責 只指定 grid 維度;每 block 的 thread 數由 compiler 依 tile 運算決定
單一控制流 block 走單一控制流,支援條件與迴圈,但沒有 warp divergence 概念
Array(global array) 多維、存於 device memory可變(mutable)、有 shape 與 dtype
Tile 只存在於 tile code、block 區域、不可變(immutable)、各維為 2 的次方且編譯期已知、不一定有記憶體表示、不可當 kernel 參數
Tile space 將 array 概念性切成等大、不重疊的 tiles;以 tile-space 索引選取 tile
Load / Store load 把 array 區塊讀成 tile(越界可補零);store 為反向、越界寫入被丟棄;另支援 gather/scatter
Tile 運算 elementwise、matrix multiply、reductions、reshape/transpose、type conversion;shape 不同時較小者自動 broadcast
與 SIMT 關係 兩模型共存、per-kernel 選擇;SIMT 細粒度、tile 較高層抽象且可跨架構執行

Tile 程式模型概觀 (1.2.2.3)

除了前述的 SIMT 模型外,CUDA 另支援 tile programming model。在此模型中,programmer 不再為每個 thread 撰寫程式,而是在整個 thread block 的層級撰寫程式,描述對多維資料集合(稱為 tiles)的運算。compiler 負責把這些運算映射到 block 內的各個 thread。

Important

不要混淆 blocktileblock 是執行單位(unit of execution)tile 是資料單位(unit of data)。單一 block 可建立並操作許多不同 shape、不同 data type 的 tiles。

SIMT 模型                          Tile 模型
─────────────                      ─────────────
programmer 寫 per-thread 程式       programmer 寫 per-block 程式
控制每個 thread 如何存取資料         描述對 tiles 的運算
                                    ↓
                              compiler 把運算分配給 block 內各 thread
                              compiler 決定 threads/block
Tip

記法:tile 模型把「thread 層級的決策」交給 compiler,programmer 只需思考「block 對一塊資料做什麼運算」。

Arrays 與 Tiles (1.2.2.3.1)

Tile kernel 處理兩種資料:arraystiles。兩者性質幾乎相反,是本主題最容易混淆的對比,務必用表格牢記。

比較項 Array(global array) Tile
存放位置 device memory 只存在於 tile codeblock 區域
可變性 可變(mutable),可被 store 修改 不可變(immutable),每個運算產生新 tile
維度大小 多維、由 shape 描述 每個維度須為 2 的次方編譯期已知
記憶體表示 一定有(在 device memory) 不一定有;由 compiler 決定(registers / shared memory / SM 其他資源)
可否當 kernel 參數 不可;完全在 tile code 內建立與消耗
屬性 shapedata type 多維值的集合
Warning

Tile 的每個維度必須是 2 的次方編譯期已知(值須在 kernel 執行前可決定,而非執行期才算出)。此外 tile 不能作為 kernel 參數傳遞。這兩點與一般 array 形成例外限制。

Tile space 與資料搬移 (1.2.2.3.2)

資料透過 loadstore 在 array 與 tile 之間搬移,兩者皆建立在 tile space 概念上。

Array (M, N)                        Tile space  (⌈M/tm⌉ × ⌈N/tn⌉)
┌──────────────┐                    ┌────┬────┬────┐
│              │    load (i,j)      │0,0 │0,1 │0,2 │
│   array in   │  ───────────────►  ├────┼────┼────┤
│ device mem   │   store (i,j)      │1,0 │1,1 │1,2 │ ← 邊緣 tile 越界→補零
│              │  ◄───────────────  ├────┼────┼────┤
└──────────────┘                    │... │... │... │
   (mutable)         tile (tm,tn)   └────┴────┴────┘
                     (immutable)
Warning

Load 與 store 的越界行為不對稱:load 越界讀取依指定方式處理(如補零),store 越界寫入則被丟棄。容易考的混淆點。

Tile 運算 (1.2.2.3.3)

Tile 程式提供一組作用於 tile 的內建運算:

Tip

Broadcasting:當兩個不同 shape 的 tile 在同一運算中結合時,較小的 tile 會自動被擴展(expand)以匹配較大者,再套用運算。免去手動複製資料。

與 SIMT 的關係 (1.2.2.3.4)

Tile programming 與 SIMT programming 在 CUDA 中共存(coexist),並非取代關係。

面向 SIMT 程式 Tile 程式
抽象層級 細粒度:對個別 thread 的控制 較高層抽象:簡化 kernel 開發
thread 決策 programmer 控制 交給 compiler
跨架構 可能需調整 同一 tile kernel 可跨不同 GPU 架構執行,無需改原始碼
適用 某些演算法與最佳化技巧仍需要 想要更高層、可攜的描述時
              同一份 device memory(global memory)
        ┌──────────────────────────────────────────┐
        │   SMs / thread blocks / grids(共同硬體)   │
        └──────────────────────────────────────────┘
            ▲                              ▲
            │ per-kernel 選擇               │
      ┌─────┴──────┐                ┌──────┴──────┐
      │ SIMT kernel│   可並存於同一    │ Tile kernel │
      │ 細粒度控制  │   application    │ 高層、可攜   │
      └────────────┘                └─────────────┘

考試/測驗重點

情境/關鍵字 答案
Tile 程式在哪個層級寫程式? 整個 thread block 層級
誰決定每 block 的 thread 數? compiler(依 tile 運算決定);programmer 只給 grid 維度
Tile 模型有 warp divergence 嗎? 沒有;block 走單一控制流
block vs tile block=執行單位;tile=資料單位;一個 block 可有多個 tile
array 可變還是不可變? array mutable;tile immutable(每次運算產生新 tile)
tile 各維度限制 須為 2 的次方編譯期已知
tile 能當 kernel 參數嗎? 不能
tile 一定存在記憶體嗎? 不一定;compiler 決定(registers/shared memory/SM 資源)
tile space 是什麼? 把 array 切成等大、不重疊 tiles 的索引空間
load 越界 vs store 越界 load 依指定處理(如補零);store 越界被丟棄
任意位置存取的運算 gather / scatter
不同 shape tile 結合 較小者自動 broadcast 擴展
同一 tile kernel 可跨架構嗎? 可;thread 決策交給 compiler,無需改原始碼
SIMT 與 tile 能並用嗎? 可;per-kernel 選擇,共用同一 device memory 與硬體
scalar 運算 vs tile 運算誰執行 scalar 由單一 thread;tile 運算由所有 thread 平行執行