Python3用WMI读取GPU显存错误,如何获取N卡/AMD/Intel卡正确显存?
问题根因
Win32_VideoController的AdapterRAM字段存在先天设计缺陷,它使用32位无符号整数存储显存大小,最大值仅为4294967296字节(即4GB),只要显存超过4GB就会返回错误值,和显卡品牌无关,是WMI接口本身的问题。
兼容全厂商的解决方案
Windows环境下直接调用原生DXGI接口是最优方案,该接口是Windows官方提供的图形设备枚举接口,所有NVIDIA、AMD、Intel显卡都原生支持,返回的显存数值和任务管理器、dxdiag完全一致。
方案1:仅用Python标准库实现(无额外依赖)
通过ctypes直接调用DXGI接口,无需安装第三方包:
import ctypes from ctypes import wintypes class LUID(ctypes.Structure): _fields_ = [ ("LowPart", wintypes.DWORD), ("HighPart", wintypes.LONG), ] class DXGI_ADAPTER_DESC(ctypes.Structure): _fields_ = [ ("Description", wintypes.WCHAR * 128), ("VendorId", wintypes.UINT), ("DeviceId", wintypes.UINT), ("SubSysId", wintypes.UINT), ("Revision", wintypes.UINT), ("DedicatedVideoMemory", wintypes.SIZE_T), ("DedicatedSystemMemory", wintypes.SIZE_T), ("SharedSystemMemory", wintypes.SIZE_T), ("AdapterLuid", LUID), ] dxgi = ctypes.WinDLL("dxgi.dll") dxgi.CreateDXGIFactory.argtypes = [ctypes.POINTER(wintypes.GUID), ctypes.POINTER(ctypes.c_void_p)] dxgi.CreateDXGIFactory.restype = wintypes.HRESULT IID_IDXGIFactory = wintypes.GUID("{7b7166ec-21c7-44ae-b21a-c9ae321ae369}") def get_gpu_memory(): gpu_list = [] factory = ctypes.c_void_p() hr = dxgi.CreateDXGIFactory(ctypes.byref(IID_IDXGIFactory), ctypes.byref(factory)) if hr < 0: return gpu_list i = 0 while True: adapter = ctypes.c_void_p() enum_adapters = ctypes.cast(factory, ctypes.POINTER(ctypes.c_void_p))[0] enum_adapters = ctypes.cast(enum_adapters + 3 * ctypes.sizeof(ctypes.c_void_p), ctypes.POINTER(ctypes.CFUNCTYPE(wintypes.HRESULT, ctypes.c_void_p, wintypes.UINT, ctypes.POINTER(ctypes.c_void_p))))[0] hr = enum_adapters(factory, i, ctypes.byref(adapter)) if hr < 0: break get_desc = ctypes.cast(adapter, ctypes.POINTER(ctypes.c_void_p))[0] get_desc = ctypes.cast(get_desc + 8 * ctypes.sizeof(ctypes.c_void_p), ctypes.POINTER(ctypes.CFUNCTYPE(wintypes.HRESULT, ctypes.c_void_p, ctypes.POINTER(DXGI_ADAPTER_DESC))))[0] desc = DXGI_ADAPTER_DESC() hr = get_desc(adapter, ctypes.byref(desc)) if hr >= 0: gpu_list.append({ "name": desc.Description, "dedicated_vram_bytes": desc.DedicatedVideoMemory, "dedicated_vram_gb": round(desc.DedicatedVideoMemory / (1024**3), 2) }) release = ctypes.cast(adapter, ctypes.POINTER(ctypes.c_void_p))[0] release = ctypes.cast(release + 2 * ctypes.sizeof(ctypes.c_void_p), ctypes.POINTER(ctypes.CFUNCTYPE(wintypes.ULONG, ctypes.c_void_p)))[0] release(adapter) i += 1 release = ctypes.cast(factory, ctypes.POINTER(ctypes.c_void_p))[0] release = ctypes.cast(release + 2 * ctypes.sizeof(ctypes.c_void_p), ctypes.POINTER(ctypes.CFUNCTYPE(wintypes.ULONG, ctypes.c_void_p)))[0] release(factory) return gpu_list if __name__ == "__main__": gpus = get_gpu_memory() for gpu in gpus: print(f"显卡名称:{gpu['name']}") print(f"独立显存大小:{gpu['dedicated_vram_gb']} GB\n")
方案2:使用封装好的第三方库简化调用
如果可以安装第三方依赖,直接用封装好的dxgi库即可,代码更简洁:
- 先安装依赖:
pip install dxgi - 调用代码:
from dxgi import DXGI dxgi = DXGI() for adapter in dxgi.enum_adapters(): desc = adapter.get_desc() print(f"显卡名称:{desc.description}") print(f"独立显存大小:{round(desc.dedicated_video_memory / 1024**3, 2)} GB\n")
注意事项
- 以上方案仅适用于Windows系统,DXGI是Windows独有的图形接口
- 如果需要跨Linux、Windows平台适配,Linux下可以通过读取
/sys/class/drm/节点获取显存信息,同样兼容全厂商显卡
内容的提问来源于stack exchange,提问作者Olaf Zhang
相关产品推荐
相关产品推荐

