CUDA 環境變數 (CUDA Environment Variables)
重點總覽
CUDA 提供一組環境變數,在「不改程式碼」的前提下調整 device 列舉、JIT 編譯快取、執行行為、module 載入策略與錯誤記錄。與 MPS 相關的變數另載於 GPU Deployment and Management Guide,本篇不涵蓋。下表濃縮五大類最該記的變數。
| 分類 | 代表變數 | 一句話作用 |
|---|---|---|
| Device Enumeration | CUDA_VISIBLE_DEVICES |
控制哪些 GPU 可見、列舉順序(決定 ordinal) |
| Device Enumeration | CUDA_DEVICE_ORDER |
FASTEST_FIRST(預設)或 PCI_BUS_ID 列舉順序 |
| Device Enumeration | CUDA_MANAGED_FORCE_DEVICE_ALLOC |
強制 Unified Memory 用 device memory 實體儲存 |
| JIT Compilation | CUDA_CACHE_DISABLE / _PATH / _MAXSIZE |
控制 on-disk PTX→CUBIN JIT 快取的開關/路徑/大小 |
| JIT Compilation | CUDA_FORCE_PTX_JIT / CUDA_DISABLE_PTX_JIT |
強制走 PTX JIT / 強制只用 embedded CUBIN |
| Execution | CUDA_LAUNCH_BLOCKING |
=1 關閉非同步執行,方便對齊錯誤發生點除錯 |
| Execution | CUDA_DEVICE_MAX_CONNECTIONS |
並行 work queue 數(1–32,預設 8),避免 false dep |
| Execution | CUDA_AUTO_BOOST(deprecated) |
已棄用,改用 nvidia-smi/NVML |
| Module Loading | CUDA_MODULE_LOADING |
LAZY(預設)/ EAGER 控制 kernel 載入時機 |
| Error Log Management | CUDA_LOG_FILE |
把白話錯誤訊息輸出到 stdout/stderr/檔案 |
多數開關型變數以 1 觸發其特殊行為(停用/強制/暫停等)、0 為預設;字串型變數(如 CUDA_DEVICE_ORDER、CUDA_MODULE_LOADING)則取列舉值。
Device Enumeration and Properties
CUDA_VISIBLE_DEVICES
控制哪些 GPU 對 CUDA 應用程式可見,以及它們被列舉的順序。
- 未設定:所有 GPU 可見。
- 設為空字串:沒有任何 GPU 可見。
- 取值:以逗號分隔的 GPU 識別字序列,可用三種形式:
| 識別形式 | 說明 |
|---|---|
| Integer index | GPU 在系統中的序號(同 nvidia-smi,從 0 起)。如 =2,1 使 device 0 不可見,且 device 2 列在 1 之前 |
| GPU UUID 字串 | 格式同 nvidia-smi -L,如 GPU-8932f937-...;允許縮寫,只需足以唯一識別的前綴(如 GPU-8932f937) |
| MIG 識別 | MIG-<GPU-UUID>/<GPU instance ID>/<compute instance ID>,僅支援單一 MIG instance 列舉 |
若清單中出現無效 index,只有「排在無效 index 之前」的 device 可見。例如 CUDA_VISIBLE_DEVICES=0,2,-1,1 只有 device 0 與 2 可見,device 1 因排在無效的 -1 之後而不可見。
ordinal 與可見性的關係:
cudaGetDeviceCount()回傳的數量只計入可見 device,因此使用整數 device id 的 CUDA API 只接受[0, 可見 device 數 - 1]範圍的 ordinal。- 列舉順序決定 ordinal 值。例如
CUDA_VISIBLE_DEVICES=2,1時,cudaSetDevice(0)會把實體 device 2 設為目前 device(因它列舉在最前、ordinal 為 0);之後cudaGetDevice(&device_ordinal)也會得到 0。
CUDA_VISIBLE_DEVICES=2,1
ordinal 0 ─► 實體 device 2 (列舉第一)
ordinal 1 ─► 實體 device 1
cudaSetDevice(0) → 目前 device = 實體 device 2
CUDA_DEVICE_ORDER
控制 CUDA 列舉可用 device 的順序。
| 取值 | 行為 |
|---|---|
FASTEST_FIRST |
用簡單啟發法由快到慢列舉(預設) |
PCI_BUS_ID |
依 PCI bus ID 由小到大列舉(可用 nvidia-smi --query-gpu=...) |
CUDA_MANAGED_FORCE_DEVICE_ALLOC
改變多 GPU 系統中 Unified Memory 的實體儲存方式。取值為數值,零或非零。
- 非零:強制 driver 用 device memory 做實體儲存。此時 process 內所有支援 managed memory 的 device 必須彼此 peer-to-peer 相容,否則回傳
cudaErrorInvalidDevice。 - 0:預設行為。
JIT Compilation
這組變數控制 on-disk Just-In-Time (JIT) 編譯快取與 PTX/CUBIN 的取捨。
| 變數 | 取值 / 預設 | 作用 |
|---|---|---|
CUDA_CACHE_DISABLE |
1 停用 / 0 啟用(預設) |
停用後每次執行都重新做 PTX→CUBIN 編譯(除非 binary 內已有對應架構的 CUBIN) |
CUDA_CACHE_PATH |
快取目錄絕對路徑 | 預設:Windows %APPDATA%\NVIDIA\ComputeCache;Linux ~/.nv/ComputeCache |
CUDA_CACHE_MAXSIZE |
bytes;上限 4294967296 (4 GiB) | 預設桌機/伺服器 1073741824 (1 GiB)、嵌入式 268435456 (256 MiB);超大 binary 不快取 |
CUDA_FORCE_PTX_JIT / CUDA_FORCE_JIT |
1 強制 / 0 預設 |
忽略 embedded CUBIN,改 JIT 編譯 embedded PTX |
CUDA_DISABLE_PTX_JIT / CUDA_DISABLE_JIT |
1 停用 / 0 預設 |
停用 embedded PTX 的 JIT,只用相容的 embedded CUBIN |
CUDA_FORCE_PRELOAD_LIBRARIES |
1 強制 / 0 預設 |
初始化時預載 NVVM 與 JIT 所需 library |
重點說明:
CUDA_CACHE_DISABLE:停用會拉長初次執行的載入時間,但可省磁碟空間,並有助於診斷不同 driver 版本或 build flag 之間的差異。CUDA_CACHE_MAXSIZE達上限時會淘汰較舊的 binary 騰出空間。CUDA_FORCE_PTX_JIT:用來驗證 application 內確實嵌有 PTX 且其 JIT 正常運作,確保對未來架構的 forward compatibility。CUDA_FORCE_PTX_JIT覆蓋CUDA_FORCE_JIT。CUDA_DISABLE_PTX_JIT:若 kernel 沒有 embedded binary、或 binary 是為不相容架構編譯,會載入失敗;可用來驗證每個 kernel 都有相容 CUBIN。CUDA_DISABLE_PTX_JIT覆蓋CUDA_DISABLE_JIT。CUDA_FORCE_PRELOAD_LIBRARIES:=1 會增加記憶體佔用與 driver 初始化時間,但這是避免某些「多執行緒 deadlock」情境所必需。
*_PTX_JIT 版本永遠覆蓋對應的 *_JIT 版本:CUDA_FORCE_PTX_JIT > CUDA_FORCE_JIT、CUDA_DISABLE_PTX_JIT > CUDA_DISABLE_JIT。
Execution
| 變數 | 取值 / 預設 | 作用 |
|---|---|---|
CUDA_LAUNCH_BLOCKING |
1 關閉非同步 / 0 非同步(預設) |
=1 讓 GPU 工作從 CPU 視角同步執行,錯誤可對齊到觸發的那個 API 呼叫,利於除錯 |
CUDA_DEVICE_MAX_CONNECTIONS |
1–32 connections,預設 8(無 MPS) | 並行 compute 與 copy engine 的 work queue 數,兩者一起設 |
CUDA_DEVICE_MAX_COPY_CONNECTIONS |
1–32 connections,預設 8(無 MPS) | 只影響 compute capability 8.0+;只設 copy connections |
CUDA_SCALE_LAUNCH_QUEUES |
0.25x / 0.5x / 2x / 4x |
launch queue(command buffer)大小縮放;其他值一律視為 1x |
CUDA_GRAPHS_USE_NODE_PRIORITY |
0 繼承 stream(預設)/ 1 用 node |
控制 CUDA graph 執行優先序 |
CUDA_DEVICE_WAITS_ON_EXCEPTION |
0 預設 / 1 暫停 |
=1 device 端 exception 發生時暫停等待,便於 attach cuda-gdb 檢視 live GPU state |
CUDA_DEVICE_DEFAULT_PERSISTING_L2_CACHE_PERCENTAGE_LIMIT |
0–100,預設 0 | L2 cache 保留給 persisting access 的比例 |
CUDA_DISABLE_PERF_BOOST |
1 停用 / 0 預設(僅 Linux) |
不提升 device performance state,改以 heuristic 隱式選 pstate |
CUDA_AUTO_BOOST(deprecated) |
— | GPU clock auto boost;已棄用 |
重點說明:
CUDA_DEVICE_MAX_CONNECTIONS:若來自不同 CUDA stream 的獨立 kernel/copy 對應到同一 work queue,會產生 false dependency 導致 GPU 工作序列化。建議 work queue 數 ≥ 每個 context 的 active stream 數。此變數也會一併改 copy connections,除非另用CUDA_DEVICE_MAX_COPY_CONNECTIONS明設。CUDA_DEVICE_MAX_COPY_CONNECTIONS:若兩者都設,它覆蓋由CUDA_DEVICE_MAX_CONNECTIONS設定的 copy connections 值。CUDA_GRAPHS_USE_NODE_PRIORITY:覆蓋 graph 實例化時的cudaGraphInstantiateFlagUseNodePriorityflag;=1 時 runtime 把 node 層級優先序當成 ready-to-run graph node 的排程提示。CUDA_DEVICE_DEFAULT_PERSISTING_L2_CACHE_PERCENTAGE_LIMIT:僅對支援 persistent L2 的 device(compute capability 8.0+)且使用 MPS 時有意義,且必須在啟動 MPS Control Daemon(nvidia-cuda-mps-control -d)之前設定。CUDA_DISABLE_PERF_BOOST:可能降低功耗,但在動態 pstate 選擇下某些情境會有較高 latency。CUDA_AUTO_BOOST:覆蓋nvidia-smi --auto-boost-default=0,但已棄用,強烈建議改用nvidia-smi --applications-clocks=<memory,graphics>或 NVML API。
關閉非同步執行會讓程式變慢;它的價值在於「讓 CUDA API 錯誤剛好在觸發它的那個呼叫被觀察到」,平時不應開啟。
Module Loading
控制 CUDA runtime 如何載入 module(device code 的初始化時機)。
| 變數 | 取值 | 作用 |
|---|---|---|
CUDA_MODULE_LOADING |
DEFAULT(=LAZY) / LAZY / EAGER |
控制 kernel 的載入時機 |
CUDA_MODULE_DATA_LOADING |
DEFAULT(=LAZY) / LAZY / EAGER |
控制 module 資料載入;未設則繼承 CUDA_MODULE_LOADING |
CUDA_BINARY_LOADER_THREAD_COUNT |
整數,預設 0(=1 個 thread) | 載入 device binary 時使用的 CPU thread 數 |
LAZY vs EAGER
| 模式 | 載入時機 | 特性 |
|---|---|---|
LAZY |
延後到取得 function handle CUfunc(cuModuleGetFunction()/cuKernelGetFunction());CUBIN 資料在首個 kernel 載入或首個變數被存取時才載入 |
降低 startup 時間與 GPU 記憶體佔用;首次呼叫載入,之後無額外開銷 |
EAGER |
程式初始化即完整載入;CUBIN/FATBIN/PTX 的所有 kernel 與資料在對應的 cuModuleLoad* / cuLibraryLoad* 呼叫時全部載入 |
startup 時間與 GPU 記憶體佔用較高;kernel launch 開銷可預測 |
它與 kernel 導向的 CUDA_MODULE_LOADING 互補,不影響 kernel 本身的 LAZY/EAGER。未設定時,資料載入行為繼承自 CUDA_MODULE_LOADING。注意 lazy 的資料載入可能需要 context synchronization,反而拖慢 concurrent execution。
CUDA_BINARY_LOADER_THREAD_COUNT 設為 0 時,使用的 CPU thread 數採預設值 1。
CUDA Error Log Management
CUDA_LOG_FILE
指定一個位置,讓「有回傳錯誤的、受支援的 CUDA API 呼叫」在錯誤發生時印出描述性錯誤訊息。
- 取值:
stdout、stderr,或一個合法的檔案路徑(需有適當寫入權限)。
範例:以無效 grid 設定啟動 kernel(如 kernel<<<1, dim3(1,1,128)>>>(...))會失敗,cudaGetLastError() 只回傳通用的 invalid configuration argument。但若設了 CUDA_LOG_FILE,log 中會出現白話訊息:
[CUDA][E] Block Dimensions (1,1,128) include one or more values
that exceed the device limit of (1024,1024,64)
如此即可輕易判斷是 block 的 z 維度超標。
CUDA_LOG_FILE 只是「啟用」描述性 log 的入口;更完整的 log 輸出/iterator/callback API 與限制,見 04-CUDA-Features/10-Lazy-Loading-and-Error-Log。
考試/測驗重點
| 題型 | 關鍵答案 |
|---|---|
CUDA_VISIBLE_DEVICES 未設 / 設空字串? |
未設=全部可見;空字串=全部不可見 |
CUDA_VISIBLE_DEVICES 三種識別形式? |
integer index、GPU UUID(可縮寫前綴)、MIG(僅單一 instance) |
CUDA_VISIBLE_DEVICES=0,2,-1,1 哪些可見? |
只有 0 與 2;遇無效 index 即截斷,之後的都不可見 |
CUDA_VISIBLE_DEVICES=2,1 時 cudaSetDevice(0)? |
設實體 device 2(列舉最前、ordinal 0);count 只含可見 device |
CUDA_DEVICE_ORDER 預設值? |
FASTEST_FIRST(由快到慢的啟發法);另一選項 PCI_BUS_ID |
CUDA_MANAGED_FORCE_DEVICE_ALLOC 非零的前提? |
所有支援 managed memory 的 device 須 P2P 相容,否則 cudaErrorInvalidDevice |
CUDA_CACHE_DISABLE 預設與效果? |
預設 0(啟用快取);=1 每次重編 PTX→CUBIN,初次載入變慢 |
| JIT 快取預設大小與上限? | 桌機/伺服器 1 GiB、嵌入式 256 MiB;上限 4 GiB |
| JIT 快取預設路徑? | Windows %APPDATA%\NVIDIA\ComputeCache;Linux ~/.nv/ComputeCache(CUDA_CACHE_PATH 可改) |
CUDA_FORCE_PTX_JIT 與 CUDA_FORCE_JIT 誰覆蓋誰? |
CUDA_FORCE_PTX_JIT 覆蓋 CUDA_FORCE_JIT |
CUDA_DISABLE_PTX_JIT 與 CUDA_DISABLE_JIT 誰覆蓋誰? |
CUDA_DISABLE_PTX_JIT 覆蓋 CUDA_DISABLE_JIT |
CUDA_FORCE_PRELOAD_LIBRARIES=1 的用途? |
預載 NVVM/JIT library,避免某些多執行緒 deadlock;代價是記憶體與初始化時間增加 |
CUDA_LAUNCH_BLOCKING=1 何用? |
關非同步,讓錯誤對齊觸發的 API 呼叫,方便除錯;會變慢 |
CUDA_DEVICE_MAX_CONNECTIONS 範圍/預設/問題? |
1–32、預設 8;不足會因 work queue 共用造成 false dependency 序列化 |
CUDA_DEVICE_MAX_COPY_CONNECTIONS 適用對象與覆蓋關係? |
僅 compute capability 8.0+;兩者都設時覆蓋 CUDA_DEVICE_MAX_CONNECTIONS 的 copy |
CUDA_SCALE_LAUNCH_QUEUES 合法值? |
0.25x/0.5x/2x/4x;其他值一律當 1x |
CUDA_GRAPHS_USE_NODE_PRIORITY 0 vs 1? |
0 繼承 stream 優先序(預設);1 用 per-node 優先序當排程提示,並覆蓋 cudaGraphInstantiateFlagUseNodePriority |
CUDA_DEVICE_WAITS_ON_EXCEPTION=1 效果? |
device exception 時暫停,可 attach cuda-gdb 檢視 live GPU state |
| L2 persisting 限制變數的條件? | compute capability 8.0+ 且用 MPS;須在 nvidia-cuda-mps-control -d 前設;0–100,預設 0 |
CUDA_DISABLE_PERF_BOOST 平台限制? |
僅 Linux;=1 不提升 device performance state,改以 heuristic 隱式選 pstate,可能降功耗但部分情境 latency 較高 |
CUDA_AUTO_BOOST 狀態? |
已棄用;改用 nvidia-smi --applications-clocks 或 NVML |
CUDA_MODULE_LOADING 預設與差異? |
預設 LAZY;LAZY 降 startup/記憶體、首呼叫載入;EAGER 啟動全載、launch 開銷可預測 |
CUDA_MODULE_DATA_LOADING 與前者關係? |
互補的資料層設定;不影響 kernel LAZY/EAGER;未設則繼承 CUDA_MODULE_LOADING |
CUDA_BINARY_LOADER_THREAD_COUNT=0 代表? |
採預設 1 個 CPU thread |
CUDA_LOG_FILE 合法取值? |
stdout、stderr,或合法檔案路徑 |