iT邦幫忙

2026 iThome 鐵人賽

DAY 1
0

所以,蝦米是優化?

首先,蝦米是優化?

假設今天我們手上有一個 Kernel、一個程式,或者 whatever,反正我們現在只知道一件事情:它跑了 100 ms。

但 100 ms 到底是快還是慢?其實不知道。因為我們不知道它跑在什麼硬體上、不知道 input size,也不知道同樣的事情別人需要花多少時間。現在的 100 ms 就只是一個測量結果而已,它自己並不能告訴我們效能到底好不好。

所以要談優化,第一件事情其實很簡單:你需要一個比較的對象。

假設同樣的運算、同樣的 input、同樣的硬體,我們有另外一個版本只需要 50 ms,那事情就開始有意思了。100 ms 跟 50 ms 放在一起,我們終於可以說後者有 2x speedup,或者換個角度說,它的 execution time 減少了 50%。

這個比較對象可以是修改之前的版本,可以是另一套 implementation,也可以是某個我們估算出來的硬體上限。後面我們甚至會開始從算力、Memory Bandwidth 這些東西去估:「這個 Kernel 理論上到底還能快多少?」但不管是哪一種,背後其實都是同一件事:

有比較,才有優化。

沒有 Baseline 的 100 ms,不是快,也不是慢。它就只是 100 ms。

不過,有了 Baseline,也不代表看到哪裡可以變快就要衝過去改。

假設今天整個程式跑完需要 100 ms,其中 Program A 花了 80 ms,Program B 花了 20 ms。你看了一下 Program B,覺得這東西寫得有夠爛,改一改應該可以直接快兩倍。

然後你真的做到了:

Program A: 80 ms
Program B: 20 ms → 10 ms

Program B 快了整整 2x,execution time 直接少了一半,單看這個結果其實很漂亮。但放回整個程式:

Before: 80 + 20 = 100 ms
After:  80 + 10 =  90 ms

你花了很多力氣把一段程式優化了 2x,最後 End-to-End 只從 100 ms 變成 90 ms,大概是 1.11x speedup

這就是效能優化裡一個很現實的問題:一個東西「能優化多少」,跟它「值不值得優化」,其實是兩件不同的事情。

如果一段程式只佔整體執行時間的 20%,那就算你有一天突然得到神力,把它從 20 ms 直接優化成 0 ms,剩下那 80 ms 還是好端端地站在那裡。所以整個程式最快也只能:

100 ms → 80 ms

也就是最多 1.25x

這件事情其實就是 Amdahl's Law 在講的東西。假設可以被加速的部分佔原本執行時間的比例是 (P),而我們把這部分加速了 (S) 倍,那整體的 Speedup 會是:

Amdahl's Law

這個公式真正想講的事情很簡單:你沒有動到的那部分,最後會變成你的極限。

所以比起看到哪段 Code 很醜就先救哪段,我們更在意的是時間到底花在哪裡。如果一個 Kernel 只佔整個程式的 1%,就算把它優化得跟鬼一樣,對整體效能可能還是沒什麼影響;反過來,一個 Kernel 佔了 70% 的時間,就算最後只能快個 20%,搞不好都比前面那個有價值得多。

簡單來說就是:

先找大頭。

不然很容易忙了一整天,Benchmark 也真的變快了,最後一看 End-to-End:

「嗯?」

「大的勒?」

那時間到底花去哪了?

找到大頭之後,接下來才是比較麻煩的地方。

一個 Kernel 跑了 10 ms,而且佔整個程式 70% 的時間,我們現在知道它很重要,卻還是不知道這 10 ms 到底花去哪裡。這也是為什麼「慢」本身其實沒有告訴我們該怎麼優化。

這邊先不急著看一大堆 GPU Metrics,也先不管 Warp、Occupancy、Cache、Register。那些後面都會慢慢遇到。我們現在先很粗暴地把時間切成三個方向:

Compute、Memory、Overhead。

有些工作是真的需要做很多計算,資料都準備好了,GPU 的計算單元也一直在工作,但就是還有一大堆東西沒算完。這種我們先叫它 Compute Bound

另一種剛好相反。計算本身可能根本沒多少,GPU 一下就算完了,時間反而花在把資料搬進來、搬出去。這種比較接近 Memory Bound

最後還有一種比較尷尬:Kernel 本身可能都很快,但工作切得太碎,每次都要 Launch、Dispatch、Synchronization,最後「叫 GPU 去工作」這件事情本身開始變得不能忽略。這種我們先放進 Overhead Bound

這三種情況可以先想成一間工廠:

Compute、Memory 與 Overhead 的工廠示意圖

Memory 負責把原料送進來,Compute 是工廠裡真正加工東西的機器,而 Overhead 則是每次開工以前要處理的那些事情。

如果今天原料一直送不進來,那把工廠裡的機器換成兩倍快,大概也沒什麼用。反過來,如果原料早就堆滿整間工廠,現在是機器真的做不完,那再買十台卡車來送貨,也不會讓成品生得比較快。

至於如果工廠每做一顆螺絲就關門一次,下一顆螺絲來了再重新開門、打卡、開機……

那工廠跟卡車可能都沒有問題。

是你的開工方式很有問題。

後面會看到的 Memory Bandwidth、Tensor Core、Kernel Fusion、Shared Memory,甚至 PTX,其實都不是「用了就會變快」的魔法。它們各自在處理不同的限制。

所以比起先問「CUDA 有哪些優化技巧」,我們現在比較想知道的是:

到底是什麼東西,限制了它繼續變快?


系列文
GPU 效能優化實戰:30 天從 Kernel 到 Profiling1
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
Wolke
iT邦研究生 4 級 ‧ 2026-08-17 14:08:09

一開始就把 100 ms 拉回到 baseline 來看,超有感;沒有比較對象時,快慢真的都只是數字。還有你舉 Program B 從 20 ms 壓到 10 ms,整體卻只從 100 變 90 ms,那個落差一秒就懂,Amdahl's Law 也突然變得很接地氣。先找大頭再動手這個節奏很對,也很像在做 GPU / AI 開發時先抓瓶頸。手邊有多的 Lovable 額度想送給有緣人,有興趣可從連結看看我的系列。 https://ithelp.ithome.com.tw/articles/10401174

我要留言

立即登入留言