windows上可用dxgi获取gpu显存占用,通过idxgiadapter::getdesc1()获总量,windows 10 1809+支持getvideomemoryinfo()查实时用量,兼容nv/amd/intel,但无法区分显存用途。

Windows 上用 DXGI 获取 GPU 显存占用(NV/AMD/Intel 通用)
DXGI 是 Windows 原生支持的最轻量、最兼容的接口,不依赖驱动私有 SDK,适用于绝大多数桌面 GPU。它只能查到“当前显存总用量”和“可用显存”,不能区分显存用途(如纹理 vs 渲染目标),但足够应付监控类需求。
- 必须启用
D3D11_CREATE_DEVICE_DISABLE_GPU_TIMEOUT创建设备,否则 DXGI 查询可能因 GPU 忙碌而超时失败 - 调用
IDXGIAdapter::GetDesc1()后,Desc.DedicatedVideoMemory是显卡独占显存总量,Desc.DedicatedSystemMemory和Desc.SharedSystemMemory一般为 0(集成显卡才可能非零) - 实时用量要靠
IDXGIAdapter::CheckAccess()+IDXGIAdapter::GetVideoMemoryInfo()(Windows 10 1809+ 才支持),旧系统只能估算:用IDXGIDevice::QueryInterface(__uuidof(IDXGIAdapter), ...)拿到 adapter 后轮询Desc1并结合 D3D11 设备内存分配日志反推(不推荐)
Linux 上通过 sysfs 读取 NVIDIA GPU 显存(nvidia-smi 不是 API)
nvidia-smi 是命令行工具,不是可链接的库;真正能写进 C++ 程序的是 /proc/driver/nvidia/gpus/*/information 和 /sys/class/nvme/*/device/device/vendor 这类路径,但显存用量只暴露在 /proc/driver/nvidia/gpus/*/information 里——它只返回静态信息。真实动态用量得走 /proc/driver/nvidia/gpus/*/hwmon/hwmon*/device/power_usage_uw(功耗)或 /proc/driver/nvidia/gpus/*/information(型号)这类间接指标,不可靠。
- 正确路径是
/proc/driver/nvidia/gpus/*/information→ 只含 GPU 名称、PCI 地址,不含用量 - 显存用量实际藏在
/proc/driver/nvidia/gpus/*/information的同级目录/proc/driver/nvidia/gpus/*/hwmon/hwmon*/device/name下的mem_info_total和mem_info_used—— 但这些文件仅在驱动开启 NVML 支持且内核模块加载后存在(通常需要nvidia-persistenced运行) - 更稳妥做法是调用 NVIDIA 提供的
libnvidia-ml.so(即 NVML 库),用nvmlDeviceGetMemoryInfo();需链接-lnvidia-ml,头文件nvml.h随 CUDA Toolkit 或单独下载
跨平台统一方案:用 NVML(仅限 NVIDIA)或 ROCm(仅限 AMD)?
没有真正跨厂商的 C++ 接口。NVML 强制绑定 NVIDIA 驱动,ROCm 的 rocm_smi_lib 只支持 AMD RDNA/RDNA2+,Intel 则要用 intel_gpu_top 或 libdrm + ioctl 调用 DRM_IOCTL_I915_QUERY,三者 ABI 完全不兼容。
- NVML 最稳:初始化用
nvmlInit(),查设备用nvmlDeviceGetHandleByIndex(0),获取用量用nvmlDeviceGetMemoryInfo()返回结构体里的used和total字段 - AMD ROCm 需确认
rocm-smi已安装且/opt/rocm/bin/rocm-smi可执行;C++ 调用需dlopen("librocm_smi.so")+dlsym,函数名如rocm_smi_get_mem_info()(注意命名随版本变化) - Intel GPU 在 Linux 上建议用
libdrm+drmIoctl(fd, DRM_IOCTL_I915_QUERY, &query),参数query.data_ptr指向struct drm_i915_query_item,type 设为DRM_I915_QUERY_MEMORY_REGIONS;Windows 上 Intel 仍走 DXGI
为什么 GetProcessMemoryInfo() 或 GlobalMemoryStatusEx() 完全无效
这两个 API 查的是 CPU 内存,跟 GPU 显存物理隔离。GPU 显存地址空间不映射到进程虚拟内存,也不参与 Windows 的内存分页管理。即使你用 cudaMalloc() 或 vkAllocateMemory() 分配了显存,GetProcessMemoryInfo() 的 WorkingSetSize 也只反映 CPU 端的驱动缓冲区开销,不是显存真实用量。
-
GetProcessMemoryInfo()返回的PagefileUsage和WorkingSetSize全部属于系统 RAM,与 GPU VRAM 无关 - 试图用
VirtualQueryEx()扫描进程地址空间找 GPU 显存地址——失败,因为现代驱动(WDDM/KMD)把显存地址做了虚拟化,用户态根本看不到物理帧缓冲地址 - 唯一例外是 Linux 上用
cudaHostAlloc()分配的 pinned memory,它会出现在/proc/[pid]/maps中,但这仍是系统内存,不是显存
显存监控本质是硬件驱动层行为,必须走厂商提供的专用接口或 OS 抽象层(DXGI / sysfs / ioctl),绕不开驱动配合。别指望一个通用 Windows API 能跨厂商解决这事。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











