windows需用idxgiadapter3::queryvideomemoryinfo获取实时显存占用,仅支持wddm 2.0+设备;linux下nvidia gpu必须用nvml库,amd无稳定用户态接口;跨平台无统一方案,须按平台条件编译。

Windows 上用 DXGI 获取 GPU 显存占用(仅限集成显卡/部分独显)
DXGI 本身不提供显存“已用/总容量”的直接读数,它只能通过 IDXGIAdapter::GetDesc() 拿到显存总量(Desc.DedicatedVideoMemory),但这个值是静态的硬件规格,不是实时占用。真正能反映“当前被驱动分配出去的显存”只有 IDXGIAdapter3::QueryVideoMemoryInfo() —— 它要求 Windows 10 1607+、WDDM 驱动,并且只对支持 WDDM 2.0+ 的设备有效(多数 GTX 10 系列之后、RX 400 之后的独显 + 所有 Intel 核显基本都支持)。
常见错误现象:QueryVideoMemoryInfo 返回 E_NOINTERFACE 或 E_FAIL,说明驱动没暴露该接口,不是代码写错;返回 S_OK 但 CurrentUsage 始终为 0,大概率是驱动未启用内存统计(如某些旧版 AMD 驱动或禁用了 WDDM 的 Tesla 卡)。
- 必须用
IDXGIAdapter3(而非IDXGIAdapter或IDXGIAdapter1) - 调用前需先
QueryInterface(__uuidof(IDXGIAdapter3), ...) -
QueryVideoMemoryInfo(0, &info)中第一个参数是节点索引,单 GPU 设备填 0 即可 -
info.CurrentUsage是当前被驱动管理器分配出的显存字节数(含系统保留部分),不是 GPU 核心实际读写的活跃量
Linux 上用 NVML 获取 NVIDIA GPU 显存占用(需驱动和库)
NVML(NVIDIA Management Library)是唯一稳定、低开销、官方支持的方案,但它只对 NVIDIA GPU 有效,且依赖 libnvidia-ml.so(随驱动安装,通常位于 /usr/lib/x86_64-linux-gnu/ 或 /usr/lib64/)。不装驱动或只装开源 nouveau 驱动时,nvmlInit() 会直接失败。
典型错误:链接时提示 undefined reference to `nvmlDeviceGetHandleByIndex',说明没加 -lnvidia-ml;运行时报 NVML_ERROR_DRIVER_NOT_LOADED,说明驱动模块 nvidia 没加载(lsmod | grep nvidia 可确认)。
- 初始化后必须调用
nvmlDeviceGetHandleByIndex(0, &device)获取第 0 块卡句柄 - 用
nvmlDeviceGetMemoryInfo(device, &mem)获取mem.used和mem.total(单位字节) - 不要在循环里反复调用
nvmlInit()/nvmlShutdown(),初始化一次即可,频繁调用会显著拖慢性能 - 若程序需支持多卡,
nvmlDeviceGetCount(&count)可查数量,再逐个索引获取
Linux 上读取 /proc/driver/nvidia/gpus/*/information 不行,别试了
这个路径下只有 GPU 型号、PCI ID、温度(如果驱动支持)等静态信息,没有显存占用字段。有人误以为 /proc/driver/nvidia/gpus/0000:01:00.0/information 里会有 “memory usage”,实际上它从不输出用量数据。类似地,/sys/class/drm/card0/device/mem_info_vram_used 这类 sysfs 节点只存在于极少数定制内核或旧版驱动中,主线内核和标准 NVIDIA 驱动均不提供。
更常见的坑是试图解析 nvidia-smi -q -d MEMORY 的文本输出:它确实能拿到用量,但启动子进程开销大(每次约 5–15ms),且输出格式可能随驱动版本微调(比如字段名大小写、单位缩写),不适合高频采集或嵌入式场景。
- 所有基于
/proc或/sys的纯文件读取方式,在标准 Linux + NVIDIA 驱动组合下,无法获得实时显存占用 -
nvidia-smi是调试好用,但不是编程接口;它的 JSON 输出模式(-q -d MEMORY -x)仍属外部命令调用,稳定性不如 NVML C API - AMD GPU 在 Linux 下目前无等效于 NVML 的用户态稳定接口;ROCm 提供的
rocm-smi工具底层走的是 ioctl,但官方未开放 C 库,自行解析风险高
跨平台统一?不存在的,别硬凑
没有一套 C++ 代码能同时在 Windows/Linux/macOS 上可靠获取 GPU 显存占用。macOS 从 macOS 12 开始移除了 OpenGL 和部分 Metal 接口的显存统计能力,Metal API 本身不暴露用量;Windows 的 DXGI 和 Linux 的 NVML 是完全不同的抽象层,连错误码定义都不兼容。
最现实的做法是按平台条件编译,或封装成三个独立函数入口:
- Windows:优先用
QueryVideoMemoryInfo,失败则 fallback 到GetDesc().DedicatedVideoMemory(仅总量) - Linux + NVIDIA:强制依赖 NVML,编译时检查
nvml.h和链接库 - Linux + AMD / 其他:明确返回错误(
ENOTSUP),或退回到 CPU 内存监控(因为很多 AMD 场景下 GPU 显存与系统内存共享,用量意义已不同)
最易被忽略的一点:GPU 显存占用本身是个模糊概念——驱动分配了、CUDA malloc 了、但 kernel 还没执行,这块内存算“占用”吗?NVML 和 DXGI 统计口径其实也不一致。别把它当成和 top 里 RSS 那样精确的指标来用。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











