制分析)
分析對象OpenUCX tagv1.19.0分析日期2026-08-041. UCX v1.19.0 CUDA 依賴1.1. CUDA 編譯/運(yùn)行依賴1.1.1 啟用開關(guān)配置選項(xiàng)說明--with-cuda[DIR]啟用 CUDA 支持并指定 CUDA Toolkit 路徑默認(rèn)guess自動探測--without-cuda顯式禁用 CUDA--with-gdrcopy[DIR]啟用 GDR COPYGPUDirect RDMA 低延遲拷貝支持--with-iodemo-cuda為io_demo測試程序添加 CUDA 支持1.1.2 configure 檢查項(xiàng)config/m4/cuda.m4中的UCX_CHECK_CUDA會依次檢查組件頭文件庫符號檢查是否必須CUDA Drivercuda.hlibcudacuDeviceGetUuid是CUDA Runtimecuda_runtime.hlibcudartcudaGetDeviceCount是NVMLnvml.hlibnvidia-mlnvmlInit是NVCC—nvcc可執(zhí)行文件否僅影響部分測試/示例編譯CUDA Static Runtime—libcudart_static否注意NVML 是硬性要求。若顯式使用--with-cuda但找不到nvml.h或libnvidia-mlconfigure會直接報(bào)錯。1.1.3 構(gòu)建產(chǎn)物模塊產(chǎn)物路徑UCT CUDAlibuct_cuda.sosrc/uct/cuda/UCM CUDAlibucm_cuda.sosrc/ucm/cuda/perftest CUDAlibucx_perftest_cuda.sosrc/tools/perf/cuda/GDR COPYlibuct_cuda_gdrcopy.sosrc/uct/cuda/gdr_copy/CUDA 傳輸組件包括cuda_copyHost?Device、Device?Device 數(shù)據(jù)拷貝cuda_ipc同一節(jié)點(diǎn) GPU 間通過 CUDA IPC 共享內(nèi)存gdr_copyGPUDirect RDMA 低延遲拷貝需單獨(dú)安裝 gdrcopy1.1.4 最低 CUDA 版本推斷源碼中多處使用CUDA_VERSION/CUDART_VERSION做條件編譯特性宏檢查所需 CUDA 版本cudaMallocAsync/cuMemAllocAsync鉤子CUDA_VERSION 11020/CUDART_VERSION 11020CUDA 11.2cudaTypedefs.h、部分 fabric handle 類型CUDA_VERSION 11070CUDA 11.7cuCtxGetId上下文有效性檢查CUDA_VERSION 12000CUDA 12.0nvmlDeviceGetGpuFabricInfo新 API測試CUDA_VERSION 12050CUDA 12.5結(jié)論UCX v1.19.0 的核心 CUDA 代碼可在較老版本 CUDA 上編譯但新特性CUDA Fabric Handle / MNNVL / Grace 主機(jī)內(nèi)存需要CUDA 11.7部分功能需CUDA 12.0 / 12.5。官方 CI 腳本buildlib/az-helpers.sh顯示當(dāng)前使用CUDA 12.8進(jìn)行驗(yàn)證。1.1.5 包依賴RPMucx.spec.in中ucx-cuda子包包含libuct_cuda.so.*、libucm_cuda.so.*、libucx_perftest_cuda.so.*ucx-gdrcopy依賴ucx-cuda。DEBdebian/ucx-cuda.install、debian/ucx-gdrcopy.install包含對應(yīng)模塊。1.1.6 常用構(gòu)建命令# 自動探測 CUDA默認(rèn)./contrib/configure-release--prefix/opt/ucx# 顯式啟用并指定 CUDA 路徑./contrib/configure-release--prefix/opt/ucx\--with-cuda/usr/local/cuda\--with-gdrcopy/usr/local/gdrcopy# 完全禁用 CUDA./contrib/configure-release--prefix/opt/ucx --without-cuda1.2. UCX v1.19.0 是否仍會 Hook CUDA 庫結(jié)論是的UCX v1.19.0 仍然會通過 UCMUnified Communication Memory對 CUDA Driver API 和 CUDA Runtime API 進(jìn)行 Hook。1.2.1 Hook 實(shí)現(xiàn)位置核心實(shí)現(xiàn)文件src/ucm/cuda/cudamem.csrc/ucm/cuda/cudamem.h1.2.2 被 Hook 的 CUDA 函數(shù)CUDA Driver API分配類釋放類cuMemAlloccuMemFreecuMemAlloc_v2cuMemFree_v2cuMemAllocManagedcuMemFreeHostcuMemAllocPitchcuMemFreeHost_v2cuMemAllocPitch_v2cuMemUnmapcuMemMapcuMemFreeAsyncCUDA 11.2cuMemAllocAsyncCUDA 11.2cuMemAllocFromPoolAsyncCUDA 11.2cuModuleGetGlobal_v2CUDA Runtime API分配類釋放類cudaMalloccudaFreecudaMallocManagedcudaFreeHostcudaMallocPitchcudaFreeAsyncCUDA 11.2cudaMallocAsyncCUDA 11.2cudaMallocFromPoolAsyncCUDA 11.2cudaGetSymbolAddress1.2.3 Hook 機(jī)制ucm_cudamem_install()會依次嘗試兩種 Hook 方式Bistro二進(jìn)制指令級插樁用于 CUDA Driver API通過ucm_bistro_patch()修改目標(biāo)函數(shù)入口指令即使 CUDA Runtime 被靜態(tài)鏈接到應(yīng)用中也能攔截 Runtime 對 Driver API 的調(diào)用RelocELF 重定位表修改用于 CUDA Driver API 和 CUDA Runtime API通過ucm_reloc_modify()修改動態(tài)鏈接重定位表如果應(yīng)用靜態(tài)鏈接了 CUDA Runtime可能會漏掉部分內(nèi)存事件默認(rèn)啟用策略src/ucm/util/sys.c.cuda_hook_modes#ifUCM_BISTRO_HOOKSUCS_BIT(UCM_MMAP_HOOK_BISTRO)|#endifUCS_BIT(UCM_MMAP_HOOK_RELOC),即如果平臺支持 Bistro則同時啟用 Bistro Reloc否則只啟用 Reloc。1.2.4 運(yùn)行時配置通過環(huán)境變量UCX_MEM_CUDA_HOOK_MODE可以控制 Hook 模式src/ucs/config/ucm_opts.c模式說明none不設(shè)置 CUDA Hookreloc通過 ELF 重定位表設(shè)置 Hook對靜態(tài)鏈接 CUDA Runtime 的應(yīng)用可能漏事件bistro通過二進(jìn)制指令級插樁設(shè)置 Hook可攔截靜態(tài)鏈接應(yīng)用對 Driver API 的調(diào)用UCX_MEM_CUDA_HOOK_MODE是位圖類型可同時指定多個模式例如UCX_MEM_CUDA_HOOK_MODEbistro,reloc。1.2.5 Hook 觸發(fā)的事件CUDA 內(nèi)存 Hook 會向上層派發(fā)兩類 UCM 事件UCM_EVENT_MEM_TYPE_ALLOCCUDA 內(nèi)存分配事件UCM_EVENT_MEM_TYPE_FREECUDA 內(nèi)存釋放事件這些事件被 UCS 內(nèi)存類型緩存memtype cache等模塊消費(fèi)用于自動識別指針是否為 GPU 內(nèi)存避免重復(fù)的內(nèi)存屬性查詢支持 RMA / Rendezvous 協(xié)議正確選擇傳輸路徑1.2.6 歷史背景與兼容性UCX 早期版本曾因 CUDA Hook 導(dǎo)致部分 NVIDIA GPU 應(yīng)用出現(xiàn)兼容性問題尤其是應(yīng)用靜態(tài)鏈接 CUDA Runtime 時。從后續(xù)版本開始UCX 引入了Bistro Reloc 雙模式以及UCX_MEM_CUDA_HOOK_MODE配置項(xiàng)允許用戶按需關(guān)閉或調(diào)整 Hook 行為。在 v1.19.0 中相關(guān)代碼仍然完整保留并默認(rèn)啟用說明 CUDA Hook 仍是 UCX GPU 內(nèi)存感知的核心機(jī)制。1.3. 綜合結(jié)論UCX v1.19.0 構(gòu)建 CUDA 支持需要CUDA Toolkitcuda.h、cuda_runtime.h、-lcuda、-lcudart以及 NVIDIA 驅(qū)動的 NVMLnvml.h、-lnvidia-ml。UCX v1.19.0 仍然 Hook CUDA 庫通過src/ucm/cuda/cudamem.c對 CUDA Driver API 和 CUDA Runtime API 的內(nèi)存分配/釋放函數(shù)進(jìn)行 Hook默認(rèn)啟用 Bistro Reloc 雙模式。Hook 可被關(guān)閉或調(diào)整通過環(huán)境變量UCX_MEM_CUDA_HOOK_MODEnone可完全禁用使用reloc或bistro可單獨(dú)選擇模式。2. UCX v1.19.0 x86 平臺下 Bistro 與 Reloc CUDA Hook 對比分析分析對象OpenUCX tagv1.19.0分析日期2026-08-04問題在 x86 平臺上UCX v1.19.0 默認(rèn)對 CUDA 內(nèi)存分配/釋放同時使用Bistro和Reloc兩種 Hook 模式。問題是否可以只啟用Reloc關(guān)閉Bistro如果關(guān)閉 Bistro僅使用 Reloc能否達(dá)到與兩者同時啟用相同的目的簡短結(jié)論問題結(jié)論能否只啟用 Reloc可以。通過環(huán)境變量UCX_MEM_CUDA_HOOK_MODEreloc即可。是否能達(dá)到相同目的不能 100% 等價(jià)。對動態(tài)鏈接 CUDA Runtime 的應(yīng)用基本等價(jià)但對靜態(tài)鏈接 CUDA Runtime的應(yīng)用Reloc 可能漏掉部分 CUDA 內(nèi)存事件。2.1. 兩種 Hook 模式的實(shí)現(xiàn)機(jī)制2.1.1 Bistro二進(jìn)制指令級插樁實(shí)現(xiàn)文件src/ucm/bistro/bistro_x86_64.c原理直接修改目標(biāo)函數(shù)入口處的機(jī)器指令插入一條跳轉(zhuǎn)到 Hook 函數(shù)的指令。特點(diǎn)不依賴 ELF 重定位表。只要調(diào)用者執(zhí)行到被 Hook 函數(shù)的入口地址就會被攔截。即使 CUDA Runtime 被靜態(tài)鏈接進(jìn)應(yīng)用只要它調(diào)用的是動態(tài)庫libcuda.so中的 Driver API 函數(shù)入口就能被攔截。x86_64 補(bǔ)丁形式優(yōu)先使用 5 字節(jié)的相對跳轉(zhuǎn)JMP rel32。若 Hook 函數(shù)距離超過 32 位范圍則使用 12 字節(jié)的movabs %rax, addr; jmp *%rax。2.1.2 RelocELF 重定位表修改實(shí)現(xiàn)文件src/ucm/util/reloc.c原理修改動態(tài)庫的.got/.plt等重定位表將對外部符號如cuMemAlloc的解析結(jié)果指向 Hook 函數(shù)。特點(diǎn)只影響通過動態(tài)鏈接解析的符號引用。對動態(tài)鏈接的libcudart.so和libcuda.so有效。若 CUDA Runtime 被靜態(tài)鏈接到應(yīng)用中且應(yīng)用繞過動態(tài)重定位直接調(diào)用 Driver API例如通過dlsym或鏈接時解析的地址則可能無法被攔截。2.2. 默認(rèn)行為與配置方式2.2.1 默認(rèn)啟用策略src/ucm/util/sys.cucm_global_config_tucm_global_opts{....cuda_hook_modes#ifUCM_BISTRO_HOOKSUCS_BIT(UCM_MMAP_HOOK_BISTRO)|#endifUCS_BIT(UCM_MMAP_HOOK_RELOC),...};在 x86 Linux 上config/m4/ucm.m4會檢查SYS_mmap等系統(tǒng)調(diào)用號。只要這些宏存在就會定義UCM_BISTRO_HOOKS1。因此x86 平臺默認(rèn)同時啟用 Bistro Reloc。2.2.2 運(yùn)行時關(guān)閉 Bistro 的方法通過環(huán)境變量UCX_MEM_CUDA_HOOK_MODE控制src/ucs/config/ucm_opts.c# 僅使用 Reloc關(guān)閉 BistroUCX_MEM_CUDA_HOOK_MODEreloc# 僅使用 BistroUCX_MEM_CUDA_HOOK_MODEbistro# 兩者都啟用默認(rèn)UCX_MEM_CUDA_HOOK_MODEbistro,reloc# 完全關(guān)閉 CUDA HookUCX_MEM_CUDA_HOOK_MODEnone2.2.3 編譯時徹底禁用 Bistro如果希望編譯出的 UCX 根本不包含 Bistro 代碼可以在不支持 Bistro 的平臺上編譯或手動修改config/m4/ucm.m4的判定邏輯。但在普通 x86 Linux 上無法通過 configure 選項(xiàng)直接關(guān)閉因?yàn)閁CM_BISTRO_HOOKS是自動根據(jù)系統(tǒng)調(diào)用是否存在來決定的。2.3. 關(guān)閉 Bistro 后的影響2.3.1 CUDA Driver API 的 Hooksrc/ucm/cuda/cudamem.c中安裝 Driver API Hook 的邏輯statusucm_cuda_install_hooks(ucm_cuda_driver_funcs,driver,UCM_MMAP_HOOK_BISTRO,driver_api_hooks);...statusucm_cuda_install_hooks(ucm_cuda_driver_funcs,driver,UCM_MMAP_HOOK_RELOC,driver_api_hooks);默認(rèn)先嘗試 Bistro再嘗試 Reloc。若設(shè)置UCX_MEM_CUDA_HOOK_MODEreloc則 Bistro 步驟會被跳過僅執(zhí)行 Reloc。結(jié)果對動態(tài)鏈接 CUDA Runtime 的應(yīng)用通常仍然可以正常工作因?yàn)閘ibcudart.so調(diào)用libcuda.so時會經(jīng)過重定位表。對靜態(tài)鏈接 CUDA Runtime 的應(yīng)用可能漏掉部分內(nèi)存分配/釋放事件。2.3.2 CUDA Runtime API 的 Hooksrc/ucm/cuda/cudamem.cstatusucm_cuda_install_hooks(ucm_cuda_runtime_funcs,runtime,UCM_MMAP_HOOK_RELOC,runtime_api_hooks);Runtime API只使用 Reloc從不用 Bistro。因此關(guān)閉 Bistro 對 Runtime API 的 Hook 沒有影響。2.3.3 文檔中的明確說明src/ucs/config/ucm_opts.c中對兩種模式的描述reloc - Use ELF relocation table to set hooks. In this mode, if any part of the application is linked with Cuda runtime statically, some memory events may be missed and not reported. bistro - Use binary instrumentation to set hooks. In this mode, its possible to intercept calls from the Cuda runtime library to Cuda driver APIs, so memory events are reported properly even for statically-linked applications.這已經(jīng)明確說明Reloc 無法完全替代 Bistro 在靜態(tài)鏈接場景下的能力。2.4. 實(shí)際使用建議2.4.1 何時可以安全地只使用 Reloc如果你的應(yīng)用滿足以下條件可以只啟用 Reloc應(yīng)用使用動態(tài)鏈接的 CUDA Runtimelibcudart.so。沒有通過dlsym(RTLD_NEXT, cuMemAlloc)等方式繞過 PLT/GOT 直接調(diào)用 Driver API。對 CUDA 內(nèi)存事件的完整性要求不極端允許偶發(fā)漏報(bào)。2.4.2 何時必須保留 Bistro以下情況建議保留 Bistro默認(rèn)應(yīng)用靜態(tài)鏈接了 CUDA Runtime。應(yīng)用或某些第三方庫通過dlsym動態(tài)獲取 CUDA Driver API 地址。需要確保所有 CUDA 內(nèi)存分配/釋放事件都被 UCX 感知以支持 GPU 內(nèi)存的 RMA/Rendezvous 協(xié)議。2.4.3 如果 Bistro 導(dǎo)致兼容性問題在某些環(huán)境中Bistro 可能因?yàn)橐韵略蚴∧繕?biāo)函數(shù)前幾條指令無法被ucm_bistro_relocate_one()識別。多線程競爭導(dǎo)致補(bǔ)丁應(yīng)用失敗。某些安全機(jī)制如 SELinux、PaX、某些容器環(huán)境禁止修改只讀代碼頁。此時可以嘗試UCX_MEM_CUDA_HOOK_MODEreloc如果 Reloc 也不能滿足需求可以完全關(guān)閉UCX_MEM_CUDA_HOOK_MODEnone但關(guān)閉后 UCX 將無法自動追蹤 CUDA 內(nèi)存可能影響 GPU 內(nèi)存的傳輸優(yōu)化。2.5. 總結(jié)對比項(xiàng)BistroReloc攔截層級函數(shù)入口機(jī)器指令ELF 重定位表是否需要動態(tài)鏈接否是靜態(tài)鏈接 CUDA Runtime可有效攔截 Driver API 調(diào)用可能漏事件x86 默認(rèn)是否啟用是是單獨(dú)使用是否可行是是能否完全替代兩者—不能完全替代 Bistro最終答案在 x86 平臺上可以通過UCX_MEM_CUDA_HOOK_MODEreloc只啟用 Reloc、關(guān)閉 Bistro。但這不等價(jià)于默認(rèn)的 Bistro Reloc對動態(tài)鏈接 CUDA Runtime 的應(yīng)用基本足夠?qū)o態(tài)鏈接 CUDA Runtime 的應(yīng)用可能丟失部分 CUDA 內(nèi)存事件。如果應(yīng)用沒有靜態(tài)鏈接 CUDA Runtime 且沒有繞過 PLT/GOT 調(diào)用 Driver API則只使用 Reloc 通??梢赃_(dá)到相同目的。