最近为项目编写基准性能测试,需要在日志中收集运行环境的硬件信息。这里将分别介绍在 Windows 和 Linux 环境中,如何使用 C++ 获取 CPU 型号、GPU 型号、物理内存(RAM)大小以及显存(VRAM)大小。值得注意的是,无法直接通过 C++ 标准库获取这些底层硬件信息,因此需要依赖于操作系统提供的 API 或特定的第三方库。
获取 CPU 信息 在 Windows 环境下,一般使用 __cpuid 内联函数,通过直接调用 CPU 的 cpuid 指令来获取信息。这种方法需要包含 <intrin.h> 头文件。这个头文件的核心功能是为开发者提供“内联函数”(Intrinsics)的访问接口。这些内联函数允许程序员在 C/C++ 代码中直接使用特定的处理器指令,而无需编写汇编代码。编译器在编译时会将这些函数调用替换为相应的、高度优化的汇编指令。需要注意的是,<intrin.h>是由 MSVC 实现的头文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <array> int main () { std::array<int , 4> cpuInfo; char cpuBrandString[0x41 ]; memset (cpuBrandString, 0 , sizeof (cpuBrandString)); for (unsigned int i = 0x80000002 ; i <= 0x80000004 ; ++i) { __cpuid(cpuInfo.data (), i); memcpy (cpuBrandString + (i - 0x80000002 ) * 16 , cpuInfo.data (), 16 ); } std::cout << "CPU Model: " << cpuBrandString << std::endl; return 0 ; }
在 Linux 环境中,获取 CPU 信息通常通过解析 /proc/cpuinfo 这个文件来实现。此文件包含了关于 CPU 的详细信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <fstream> #include <string> int main () { std::ifstream cpuinfo ("/proc/cpuinfo" ) ; std::string line; std::string modelName; if (cpuinfo.is_open ()) { while (getline (cpuinfo, line)) { if (line.find ("model name" ) != std::string::npos) { modelName = line.substr (line.find (":" ) + 2 ); break ; } } cpuinfo.close (); } if (!modelName.empty ()) { std::cout << "CPU Model: " << modelName << std::endl; } else { std::cerr << "Could not retrieve CPU model." << std::endl; } return 0 ; }
获取物理内存(RAM)大小 Windows API 提供了 GlobalMemoryStatusEx 函数,可以获取当前环境的内存状况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #include <iostream> #include <windows.h> int main () { MEMORYSTATUSEX statex; statex.dwLength = sizeof (statex); if (GlobalMemoryStatusEx (&statex)) { std::cout << "Total Physical Memory: " << statex.ullTotalPhys / (1024 * 1024 ) << " MB" << std::endl; } else { std::cerr << "Failed to retrieve memory information." << std::endl; } return 0 ; }
在Linux上,可以通过解析 /proc/meminfo 文件来获取内存大小。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 #include <iostream> #include <fstream> #include <string> int main () { std::ifstream meminfo ("/proc/meminfo" ) ; std::string line; long long memTotal = 0 ; if (meminfo.is_open ()) { while (getline (meminfo, line)) { if (line.find ("MemTotal" ) != std::string::npos) { memTotal = std::stoll (line.substr (line.find (":" ) + 1 )); break ; } } meminfo.close (); } if (memTotal > 0 ) { std::cout << "Total Physical Memory: " << memTotal / 1024 << " MB" << std::endl; } else { std::cerr << "Could not retrieve memory information." << std::endl; } return 0 ; }
获取 GPU 信息和显存容量 GPU 信息的获取需要配合图形 API(OpenGL/Vulkan)。应用程序需要初始化相应的图形 API 才能查询到这些信息。
使用 OpenGL 获取 GPU 型号相对直接,但获取显存容量则依赖于厂商的特定扩展。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 #include <iostream> #include <GL/glew.h> #include <GLFW/glfw3.h> int main () { if (!glfwInit ()) { return -1 ; } GLFWwindow* window = glfwCreateWindow (640 , 480 , "Hardware Info" , NULL , NULL ); if (!window) { glfwTerminate (); return -1 ; } glfwMakeContextCurrent (window); glewInit (); const GLubyte* renderer = glGetString (GL_RENDERER); const GLubyte* vendor = glGetString (GL_VENDOR); std::cout << "GPU Vendor: " << vendor << std::endl; std::cout << "GPU Model: " << renderer << std::endl; GLint total_mem_kb = 0 ; if (glewIsSupported ("GL_NVX_gpu_memory_info" )) { glGetIntegerv (GL_GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, &total_mem_kb); } else if (glewIsSupported ("GL_ATI_meminfo" )) { GLint mem_info[4 ]; glGetIntegerv (GL_TEXTURE_FREE_MEMORY_ATI, mem_info); total_mem_kb = mem_info[0 ]; } if (total_mem_kb > 0 ) { std::cout << "VRAM Size: " << total_mem_kb / 1024 << " MB" << std::endl; } else { std::cout << "VRAM size could not be determined via standard OpenGL extensions." << std::endl; } glfwDestroyWindow (window); glfwTerminate (); return 0 ; }
Vulkan 提供了详细的物理设备属性查询功能且为核心特性,因此平台无关。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <vulkan/vulkan.h> int main () { VkInstance instance; uint32_t deviceCount = 0 ; vkEnumeratePhysicalDevices (instance, &deviceCount, nullptr ); std::vector<VkPhysicalDevice> devices (deviceCount) ; vkEnumeratePhysicalDevices (instance, &deviceCount, devices.data ()); if (deviceCount > 0 ) { VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties (devices[0 ], &deviceProperties); std::cout << "GPU: " << deviceProperties.deviceName << std::endl; VkPhysicalDeviceMemoryProperties memProperties; vkGetPhysicalDeviceMemoryProperties (devices[0 ], &memProperties); VkDeviceSize vramSize = 0 ; for (uint32_t i = 0 ; i < memProperties.memoryHeapCount; ++i) { if (memProperties.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { vramSize += memProperties.memoryHeaps[i].size; } } std::cout << "VRAM Size: " << vramSize / (1024 * 1024 ) << " MB" << std::endl; } return 0 ; }
Author:
Floraison
Permalink:
https://floraison.io/2025/09/17/
License:
Copyright (c) 2019 CC-BY-NC-4.0 LICENSE