制分析)
分析對(duì)象OpenUCX tagv1.19.0分析日期2026-08-041. UCX v1.19.0 CUDA 依賴1.1. CUDA 編譯/運(yùn)行依賴1.1.1 啟用開(kāi)關(guān)配置選項(xiàng)說(shuō)明--with-cuda[DIR]啟用 CUDA 支持并指定 CUDA Toolkit 路徑默認(rèn)guess自動(dòng)探測(cè)--without-cuda顯式禁用 CUDA--with-gdrcopy[DIR]啟用 GDR COPYGPUDirect RDMA 低延遲拷貝支持--with-iodemo-cuda為io_demo測(cè)試程序添加 CUDA 支持1.1.2 configure 檢查項(xiàng)config/m4/cuda.m4中的UCX_CHECK_CUDA會(huì)依次檢查組件頭文件庫(kù)符號(hào)檢查是否必須CUDA Drivercuda.hlibcudacuDeviceGetUuid是CUDA Runtimecuda_runtime.hlibcudartcudaGetDeviceCount是NVMLnvml.hlibnvidia-mlnvmlInit是NVCC—nvcc可執(zhí)行文件否僅影響部分測(cè)試/示例編譯CUDA Static Runtime—libcudart_static否注意NVML 是硬性要求。若顯式使用--with-cuda但找不到nvml.h或libnvidia-mlconfigure會(huì)直接報(bào)錯(cuò)。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 間通過(guò) 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測(cè)試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包含對(duì)應(yīng)模塊。1.1.6 常用構(gòu)建命令# 自動(dòng)探測(cè) 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 是否仍會(huì) Hook CUDA 庫(kù)結(jié)論是的UCX v1.19.0 仍然會(huì)通過(guò) UCMUnified Communication Memory對(duì) 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()會(huì)依次嘗試兩種 Hook 方式Bistro二進(jìn)制指令級(jí)插樁用于 CUDA Driver API通過(guò)ucm_bistro_patch()修改目標(biāo)函數(shù)入口指令即使 CUDA Runtime 被靜態(tài)鏈接到應(yīng)用中也能攔截 Runtime 對(duì) Driver API 的調(diào)用RelocELF 重定位表修改用于 CUDA Driver API 和 CUDA Runtime API通過(guò)ucm_reloc_modify()修改動(dòng)態(tài)鏈接重定位表如果應(yīng)用靜態(tài)鏈接了 CUDA Runtime可能會(huì)漏掉部分內(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),即如果平臺(tái)支持 Bistro則同時(shí)啟用 Bistro Reloc否則只啟用 Reloc。1.2.4 運(yùn)行時(shí)配置通過(guò)環(huán)境變量UCX_MEM_CUDA_HOOK_MODE可以控制 Hook 模式src/ucs/config/ucm_opts.c模式說(shuō)明none不設(shè)置 CUDA Hookreloc通過(guò) ELF 重定位表設(shè)置 Hook對(duì)靜態(tài)鏈接 CUDA Runtime 的應(yīng)用可能漏事件bistro通過(guò)二進(jìn)制指令級(jí)插樁設(shè)置 Hook可攔截靜態(tài)鏈接應(yīng)用對(duì) Driver API 的調(diào)用UCX_MEM_CUDA_HOOK_MODE是位圖類型可同時(shí)指定多個(gè)模式例如UCX_MEM_CUDA_HOOK_MODEbistro,reloc。1.2.5 Hook 觸發(fā)的事件CUDA 內(nèi)存 Hook 會(huì)向上層派發(fā)兩類 UCM 事件UCM_EVENT_MEM_TYPE_ALLOCCUDA 內(nèi)存分配事件UCM_EVENT_MEM_TYPE_FREECUDA 內(nèi)存釋放事件這些事件被 UCS 內(nèi)存類型緩存memtype cache等模塊消費(fèi)用于自動(dòng)識(shí)別指針是否為 GPU 內(nèi)存避免重復(fù)的內(nèi)存屬性查詢支持 RMA / Rendezvous 協(xié)議正確選擇傳輸路徑1.2.6 歷史背景與兼容性UCX 早期版本曾因 CUDA Hook 導(dǎo)致部分 NVIDIA GPU 應(yīng)用出現(xiàn)兼容性問(wèn)題尤其是應(yīng)用靜態(tài)鏈接 CUDA Runtime 時(shí)。從后續(xù)版本開(kāi)始UCX 引入了Bistro Reloc 雙模式以及UCX_MEM_CUDA_HOOK_MODE配置項(xiàng)允許用戶按需關(guān)閉或調(diào)整 Hook 行為。在 v1.19.0 中相關(guān)代碼仍然完整保留并默認(rèn)啟用說(shuō)明 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ū)動(dòng)的 NVMLnvml.h、-lnvidia-ml。UCX v1.19.0 仍然 Hook CUDA 庫(kù)通過(guò)src/ucm/cuda/cudamem.c對(duì) CUDA Driver API 和 CUDA Runtime API 的內(nèi)存分配/釋放函數(shù)進(jìn)行 Hook默認(rèn)啟用 Bistro Reloc 雙模式。Hook 可被關(guān)閉或調(diào)整通過(guò)環(huán)境變量UCX_MEM_CUDA_HOOK_MODEnone可完全禁用使用reloc或bistro可單獨(dú)選擇模式。2. UCX v1.19.0 x86 平臺(tái)下 Bistro 與 Reloc CUDA Hook 對(duì)比分析分析對(duì)象OpenUCX tagv1.19.0分析日期2026-08-04問(wèn)題在 x86 平臺(tái)上UCX v1.19.0 默認(rèn)對(duì) CUDA 內(nèi)存分配/釋放同時(shí)使用Bistro和Reloc兩種 Hook 模式。問(wèn)題是否可以只啟用Reloc關(guān)閉Bistro如果關(guān)閉 Bistro僅使用 Reloc能否達(dá)到與兩者同時(shí)啟用相同的目的簡(jiǎn)短結(jié)論問(wèn)題結(jié)論能否只啟用 Reloc可以。通過(guò)環(huán)境變量UCX_MEM_CUDA_HOOK_MODEreloc即可。是否能達(dá)到相同目的不能 100% 等價(jià)。對(duì)動(dòng)態(tài)鏈接 CUDA Runtime 的應(yīng)用基本等價(jià)但對(duì)靜態(tài)鏈接 CUDA Runtime的應(yīng)用Reloc 可能漏掉部分 CUDA 內(nèi)存事件。2.1. 兩種 Hook 模式的實(shí)現(xiàn)機(jī)制2.1.1 Bistro二進(jìn)制指令級(jí)插樁實(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ù)的入口地址就會(huì)被攔截。即使 CUDA Runtime 被靜態(tài)鏈接進(jìn)應(yīng)用只要它調(diào)用的是動(dòng)態(tài)庫(kù)libcuda.so中的 Driver API 函數(shù)入口就能被攔截。x86_64 補(bǔ)丁形式優(yōu)先使用 5 字節(jié)的相對(duì)跳轉(zhuǎn)JMP rel32。若 Hook 函數(shù)距離超過(guò) 32 位范圍則使用 12 字節(jié)的movabs %rax, addr; jmp *%rax。2.1.2 RelocELF 重定位表修改實(shí)現(xiàn)文件src/ucm/util/reloc.c原理修改動(dòng)態(tài)庫(kù)的.got/.plt等重定位表將對(duì)外部符號(hào)如cuMemAlloc的解析結(jié)果指向 Hook 函數(shù)。特點(diǎn)只影響通過(guò)動(dòng)態(tài)鏈接解析的符號(hào)引用。對(duì)動(dòng)態(tài)鏈接的libcudart.so和libcuda.so有效。若 CUDA Runtime 被靜態(tài)鏈接到應(yīng)用中且應(yīng)用繞過(guò)動(dòng)態(tài)重定位直接調(diào)用 Driver API例如通過(guò)dlsym或鏈接時(shí)解析的地址則可能無(wú)法被攔截。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會(huì)檢查SYS_mmap等系統(tǒng)調(diào)用號(hào)。只要這些宏存在就會(huì)定義UCM_BISTRO_HOOKS1。因此x86 平臺(tái)默認(rèn)同時(shí)啟用 Bistro Reloc。2.2.2 運(yùn)行時(shí)關(guān)閉 Bistro 的方法通過(guò)環(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 編譯時(shí)徹底禁用 Bistro如果希望編譯出的 UCX 根本不包含 Bistro 代碼可以在不支持 Bistro 的平臺(tái)上編譯或手動(dòng)修改config/m4/ucm.m4的判定邏輯。但在普通 x86 Linux 上無(wú)法通過(guò) configure 選項(xiàng)直接關(guān)閉因?yàn)閁CM_BISTRO_HOOKS是自動(dòng)根據(jù)系統(tǒng)調(diào)用是否存在來(lái)決定的。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 步驟會(huì)被跳過(guò)僅執(zhí)行 Reloc。結(jié)果對(duì)動(dòng)態(tài)鏈接 CUDA Runtime 的應(yīng)用通常仍然可以正常工作因?yàn)閘ibcudart.so調(diào)用libcuda.so時(shí)會(huì)經(jīng)過(guò)重定位表。對(duì)靜態(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 對(duì) Runtime API 的 Hook 沒(méi)有影響。2.3.3 文檔中的明確說(shuō)明src/ucs/config/ucm_opts.c中對(duì)兩種模式的描述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)明確說(shuō)明Reloc 無(wú)法完全替代 Bistro 在靜態(tài)鏈接場(chǎng)景下的能力。2.4. 實(shí)際使用建議2.4.1 何時(shí)可以安全地只使用 Reloc如果你的應(yīng)用滿足以下條件可以只啟用 Reloc應(yīng)用使用動(dòng)態(tài)鏈接的 CUDA Runtimelibcudart.so。沒(méi)有通過(guò)dlsym(RTLD_NEXT, cuMemAlloc)等方式繞過(guò) PLT/GOT 直接調(diào)用 Driver API。對(duì) CUDA 內(nèi)存事件的完整性要求不極端允許偶發(fā)漏報(bào)。2.4.2 何時(shí)必須保留 Bistro以下情況建議保留 Bistro默認(rèn)應(yīng)用靜態(tài)鏈接了 CUDA Runtime。應(yīng)用或某些第三方庫(kù)通過(guò)dlsym動(dòng)態(tài)獲取 CUDA Driver API 地址。需要確保所有 CUDA 內(nèi)存分配/釋放事件都被 UCX 感知以支持 GPU 內(nèi)存的 RMA/Rendezvous 協(xié)議。2.4.3 如果 Bistro 導(dǎo)致兼容性問(wèn)題在某些環(huán)境中Bistro 可能因?yàn)橐韵略蚴∧繕?biāo)函數(shù)前幾條指令無(wú)法被ucm_bistro_relocate_one()識(shí)別。多線程競(jìng)爭(zhēng)導(dǎo)致補(bǔ)丁應(yīng)用失敗。某些安全機(jī)制如 SELinux、PaX、某些容器環(huán)境禁止修改只讀代碼頁(yè)。此時(shí)可以嘗試UCX_MEM_CUDA_HOOK_MODEreloc如果 Reloc 也不能滿足需求可以完全關(guān)閉UCX_MEM_CUDA_HOOK_MODEnone但關(guān)閉后 UCX 將無(wú)法自動(dòng)追蹤 CUDA 內(nèi)存可能影響 GPU 內(nèi)存的傳輸優(yōu)化。2.5. 總結(jié)對(duì)比項(xiàng)BistroReloc攔截層級(jí)函數(shù)入口機(jī)器指令ELF 重定位表是否需要?jiǎng)討B(tài)鏈接否是靜態(tài)鏈接 CUDA Runtime可有效攔截 Driver API 調(diào)用可能漏事件x86 默認(rèn)是否啟用是是單獨(dú)使用是否可行是是能否完全替代兩者—不能完全替代 Bistro最終答案在 x86 平臺(tái)上可以通過(guò)UCX_MEM_CUDA_HOOK_MODEreloc只啟用 Reloc、關(guān)閉 Bistro。但這不等價(jià)于默認(rèn)的 Bistro Reloc對(duì)動(dòng)態(tài)鏈接 CUDA Runtime 的應(yīng)用基本足夠?qū)o態(tài)鏈接 CUDA Runtime 的應(yīng)用可能丟失部分 CUDA 內(nèi)存事件。如果應(yīng)用沒(méi)有靜態(tài)鏈接 CUDA Runtime 且沒(méi)有繞過(guò) PLT/GOT 調(diào)用 Driver API則只使用 Reloc 通??梢赃_(dá)到相同目的。