AI 生圖與影片
在自己的顯卡上跑大模型:六個官方不會寫的坑,加一個能救你一整晚的驗收標準
「能跑」和「可用」之間,隔著一個你沒去設的門檻:單位耗時。在動手之前先寫下「一支超過幾分鐘我就放棄」,再開始裝。
一個核心觀念
「量化」有兩種完全不同的目的,很多教學混為一談。
| 目的 | 做法 | 效果 |
|---|---|---|
| 省記憶體 | 把權重存成較小的格式(如 int8),用的時候再還原 | 顯存夠用了,但可能變慢 |
| 加速 | 用專門的低精度運算指令直接算,不還原 | 又省又快,但需要專門的運算核心支援 |
判斷方法:去看那個專案的量化程式碼,找它的 forward 函式。如果裡面出現「把權重轉回原精度再相乘」的寫法(通常是一行 weight.to(dtype) * scale),它就是拿速度換記憶體。每一層、每一次運算都要做一次還原,成本很高。
推論:如果原精度版本你的卡放得下,就別開量化。量化只在「不開就完全跑不動」時才用,而且要有心理準備會慢很多。
問 AI 的咒語:
我是新手。請幫我看這段 PyTorch 量化程式碼,判斷它是「只省記憶體」還是「同時也加速」。
判斷依據請講白話,並告訴我我該去看哪一個函式。
【貼上你找到的量化類別程式碼】
按步驟做
Step 1:動手前先算一筆帳(最省時間的一步)
下載任何東西之前,先確認三個數字:
-
模型原精度需要多少顯存。粗算:
參數量 × 每個參數的位元組數。fp32 = 4 bytes、bf16/fp16 = 2 bytes、int8 = 1 byte。例:14B 參數的 bf16 模型約 14 × 2 = 28GB。更準的方法是直接看 Hugging Face 上模型檔案的總大小(見 Step 2)。 -
你的顯卡有多少顯存、現在剩多少。
nvidia-smi --query-gpu=memory.total,memory.used,memory.free --format=csv瀏覽器、遊戲、其他 AI 工具都會佔顯存,實測瀏覽器和背景程式吃掉過 4.6GB。跑之前先關掉。
-
這個模型「一支要多久」。去 repo 的 issues 或 README 搜
it/s、seconds、minutes、A100、4090,找不到就去 issues 搜「slow」。找不到任何速度資訊本身就是警訊。
決策:原精度放不下,你只能用量化;回頭看核心觀念,如果是「拿速度換記憶體」型,在這裡就該停手,去租雲端或用 API。
Step 2:看清楚你要下載什麼
Hugging Face 的模型頁常同時放好幾種重複格式(PyTorch 的 .bin、safetensors、Flax 的 .msgpack、fp32 版本……),你通常只需要其中一種。先列出檔案大小再決定:
curl -s "https://huggingface.co/api/models/<作者>/<模型名>?blobs=true"
我這次因為沒先看,一個語音模型從實際需要的 2.9GB 抓成 24GB。
下載時的坑:命令列工具的 --include / --exclude 萬用字元不可靠,混用明確檔名和萬用字元時它會整包下載(只有一行 Ignoring --include... 警告,很容易略過)。改用 Python 版本比較可控:
from huggingface_hub import snapshot_download
snapshot_download("作者/模型名", local_dir="./weights",
allow_patterns=["你要的資料夾/**"], max_workers=8)
問 AI 的咒語:
我是新手。這是某個 Hugging Face 模型的檔案清單 JSON,請幫我:
1. 依最上層資料夾分組、加總大小(用 GB)
2. 指出哪些是同一個模型的重複格式(我只需要留一種)
3. 給我一段只下載必要檔案的 Python snapshot_download 程式碼
【貼上 JSON】
Step 3:對付版本相容問題
開源專案的 requirements.txt 常釘住一年前的版本。如果你的顯卡比那個版本新,照做一定掛。典型症狀:no kernel image is available for execution on the device,意思是這個函式庫沒有為你這張卡編譯過。
python -c "import torch; print(torch.cuda.get_device_capability(0)); print(torch.cuda.get_arch_list())"
第二行印出的清單裡必須包含第一行的數字,否則就是版本不對。解法是換裝支援你的卡的版本(通常是更新的 CUDA build)。關鍵心法:官方釘的版本是「他們測過的」,不是「唯一能用的」,新卡就大膽往上升。
Step 4:注意力加速庫,最陰險的一類
Flash Attention、xformers 這類函式庫負責讓模型算得快,問題是它們「裝得起來、import 得了、一呼叫就炸」,因為預編譯的版本可能沒有為你的卡編譯。先單獨測一次,不要等跑到一半:
import torch, xformers.ops as xops
q = torch.randn(1, 4096, 16, 128, device='cuda', dtype=torch.bfloat16)
print(xops.memory_efficient_attention(q, q, q).shape) # 炸了就是不支援
如果不支援:多數專案有一條「後端選擇鏈」,依序嘗試好幾個加速庫。要確認鏈的最後有沒有原生兜底(PyTorch 內建的 scaled_dot_product_attention),有些專案的鏈末端直接 raise,那就得自己補一個分支。
問 AI 的咒語:
我是新手。這段程式碼在依序嘗試不同的 attention 後端,最後直接 raise 報錯。
我的顯卡不支援前面那些,請幫我在最後補一個用 PyTorch 原生
scaled_dot_product_attention 的分支。
請特別注意張量的維度順序要跟其他分支的輸出一致,並解釋你怎麼確認的。
【貼上那段 if/elif 程式碼】
額外提醒:有些專案的旗標是從模型檔案的 config.json 讀進來的,不是程式碼裡的預設值。我這次吃過這個虧:補好的分支根本沒被走到,因為 config 把另一個後端設成了 True。改之前先印出來確認實際值。
Step 5:跑起來之後,馬上量時間
這是整份筆記最重要的一步,也是我這次沒做而付出代價的一步。模型開始運算後,立刻算單步耗時,不要等它跑完:看進度條的 s/it 或 it/s,沒有進度條就看日誌時間戳。然後乘上總步數,跟你事先設好的上限比較。超過上限就停手,不要想「再調調看」。
你一定會踩的坑
坑 1:以為「顯存沒爆」就是成功了
顯存剛好夠用,跟跑得動,是兩件事。塞得進去之後才是速度問題的開始。驗收標準要同時包含「裝得下」和「夠快」。
坑 2:跨作業系統的硬編假設
開源專案九成在 Linux 開發,程式碼裡常有:
- 硬編的
/tmp/xxx路徑(Windows 沒有這個目錄) os.system("mv ...")(Windows 的 cmd 沒有mv)- 分散式訓練的通訊後端
nccl(Windows 不支援,要換gloo)
症狀通常很誤導,例如檔案明明產生了,程式卻說「找不到」。解法:路徑用 tempfile.gettempdir(),搬檔用 shutil.move(),通訊後端加判斷 "nccl" if torch.distributed.is_nccl_available() else "gloo"。
坑 3:記憶體(不是顯存)不夠導致的閃退
症狀:沒有錯誤訊息直接消失,或 Segmentation fault / access violation。常見原因有兩個:
- 缺少記憶體管理套件(通常是
accelerate),缺了它載入模型會把整個檔案在記憶體裡複製兩份。日誌裡有一行提示,但夾在一堆訊息中間很容易漏看。 - 建立模型時的預設精度是 fp32。有些程式註解寫著「建立空模型」,實際上真的配置了記憶體,一個 14B 模型用 fp32 建立要 59GB 記憶體。
要看到閃退發生在哪一行,用這個方式啟動:
python -X faulthandler -u 你的腳本.py
它會在崩潰時印出 Python 呼叫堆疊,而不是只給你一個代碼。
坑 4:重跑時的殭屍行程
崩潰過的程式可能沒死透,還佔著顯存和網路埠,下次跑會出現看似無關的錯誤(例如「位址已被使用」)。跑之前先確認:
nvidia-smi --query-gpu=memory.used --format=csv
數字不對就去把舊行程殺掉。另一個怪坑:bash 是「按位元組位移」逐段讀腳本的,如果在舊的執行還沒結束時覆寫同一個 .sh 檔,會出現像 utput_dir: command not found 這種鬼錯誤(指令被從中間切斷)。重跑請換檔名,或先確認前一個行程已經結束。
萬用救援:卡住怎麼問 AI
不管遇到哪種錯誤,這個模板都能用:
我是新手,作業系統是 【Windows 11 / macOS / Ubuntu】,
顯示卡是 【型號 + 顯存大小】。
我在做的事:【一句話說明目標】
我執行的指令:【原文貼上】
完整錯誤訊息:【原文貼上,不要只貼最後一行】
請:
1. 先用白話解釋這個錯誤的意思,以及它通常的根本原因
2. 給我一個「先確認什麼」的檢查步驟(我想先確認診斷對不對,再動手改)
3. 再給解法,一步一步來,每步告訴我預期會看到什麼
4. 如果需要改程式碼,請說明改動的原理,不要只給我貼上就好的片段
兩個使用原則:錯誤訊息一定要貼完整,最後一行通常只是結果,真正的原因在中間;先要診斷再要解法,直接要解法容易得到「試試看這個」的亂槍打鳥,浪費的時間比自己查還多。
一句話總結
「能跑」和「可用」之間,隔著一個你沒去設的門檻:單位耗時。技術驗收如果只檢查「會不會報錯」,你會在一條註定失敗的路上一路修到底,每修好一關都覺得離成功更近。動手之前先寫下:「一支超過 ___ 分鐘我就放棄。」這一行字,可能幫你省下一整個晚上。
這是踩坑實錄與 AI 工具實測系列的一部分。想收到後續完整 SOP,訂閱電子報。
支持這裡的內容:前往 Ko-fi 斗內