学校项目有此需求,百度整合,供有缘人使用
网上资料较杂,这个版本是我从网上整合出来,经过实际项目验收,然后出于学校项目保密的性质,把这个小轮子从项目中拆出来供大家使用
//头文件 monitor.h
#include <windows.h>
#include <tchar.h>
#include<iostream>
#include <stdio.h>
#include "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\include\\nvml.h"
#define DIV 1024
#define GB(x) (((x).HighPart << 2) + ((DWORD)(x).LowPart) / 1024.0 / 1024.0 / 1024.0)
// Specify the width of the field in which to print the numbers.
// The asterisk in the format specifier "%*I64d" takes an integer
// argument and uses it to pad and right justify the number.
#define WIDTH 7
//continuous sending HeartBeat, HardwareStatus, and SoftwareStatus
typedef unsigned char byte;
class Monitor
{
public:
void getHastate(byte* cpuusage, byte* gpuusage, byte* hduusage, ushort* hdremain, byte* memusage);
private:
byte GetCpuRate_byte();
byte GetGpuRate_byte();
std::pair<byte, ushort> GetDiskRate_byte();
byte GetMemoryRate_byte();
};
//对应源文件 monitor.cpp
#include "monitor.h"
#pragma comment(lib, "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\lib\\x64\\nvml.lib")
__int64 CompareFileTime(FILETIME time1, FILETIME time2)
{
__int64 a = time1.dwHighDateTime << 32 | time1.dwLowDateTime;
__int64 b = time2.dwHighDateTime << 32 | time2.dwLowDateTime;
return (b - a);
}
byte Monitor::GetCpuRate_byte() {
HANDLE hEvent;
BOOL res;
FILETIME preidleTime;
FILETIME prekernelTime;
FILETIME preuserTime;
FILETIME idleTime;
FILETIME kernelTime;
FILETIME userTime;
res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
preidleTime = idleTime;
prekernelTime = kernelTime;
preuserTime = userTime;
hEvent = CreateEventA(NULL, FALSE, FALSE, NULL); // 初始值为 nonsignaled ,并且每次触发后自动设置为nonsignaled
WaitForSingleObject(hEvent, 1000);
res = GetSystemTimes(&idleTime, &kernelTime, &userTime);
__int64 idle = CompareFileTime(preidleTime, idleTime);
__int64 kernel = CompareFileTime(prekernelTime, kernelTime);
__int64 user = CompareFileTime(preuserTime, userTime);
__int64 cpu = (kernel + user - idle) * 100 / (kernel + user);
__int64 cpuidle = (idle) * 100 / (kernel + user);
preidleTime = idleTime;
prekernelTime = kernelTime;
preuserTime = userTime;
double cpu_use = cpu;
return cpu_use;
}
byte Monitor::GetGpuRate_byte() {
nvmlReturn_t result;
unsigned int device_count, i;
// First initialize NVML library
result = nvmlInit();
result = nvmlDeviceGetCount(&device_count);
if (NVML_SUCCESS != result)
{
std::cout << "Failed to query device count: " << nvmlErrorString(result);
}
//std::cout << "Found" << device_count << " device" << endl;
//std::cout << "Listing devices:";
for (i = 0; i < device_count; i++)
{
nvmlDevice_t device;
char name[NVML_DEVICE_NAME_BUFFER_SIZE];
nvmlPciInfo_t pci;
result = nvmlDeviceGetHandleByIndex(i, &device);
if (NVML_SUCCESS != result) {
//std::cout << "get device failed " << endl;
}
result = nvmlDeviceGetName(device, name, NVML_DEVICE_NAME_BUFFER_SIZE);
if (NVML_SUCCESS != result) {
//std::cout << "GPU name: " << name << endl;
}
//使用率
nvmlUtilization_t utilization;
result = nvmlDeviceGetUtilizationRates(device, &utilization);
if (NVML_SUCCESS == result)
{
return ((byte)utilization.gpu);
//std::cout << "----- 使用率 ----- " << endl;
//std::cout << "GPU 使用率: " << utilization.gpu << endl;
//std::cout << "显存使用率 " << utilization.memory << endl;
}
}
return 0;
}
std::pair<byte, ushort> Monitor::GetDiskRate_byte() {
ULARGE_INTEGER FreeBytesAvailableC, TotalNumberOfBytesC, TotalNumberOfFreeBytesC;
ULARGE_INTEGER FreeBytesAvailableD, TotalNumberOfBytesD, TotalNumberOfFreeBytesD;
ULARGE_INTEGER FreeBytesAvailableE, TotalNumberOfBytesE, TotalNumberOfFreeBytesE;
ULARGE_INTEGER FreeBytesAvailableF, TotalNumberOfBytesF, TotalNumberOfFreeBytesF;
GetDiskFreeSpaceEx(_T("C:"), &FreeBytesAvailableC, &TotalNumberOfBytesC, &TotalNumberOfFreeBytesC);
GetDiskFreeSpaceEx(_T("D:"), &FreeBytesAvailableD, &TotalNumberOfBytesD, &TotalNumberOfFreeBytesD);
GetDiskFreeSpaceEx(_T("E:"), &FreeBytesAvailableE, &TotalNumberOfBytesE, &TotalNumberOfFreeBytesE);
GetDiskFreeSpaceEx(_T("F:"), &FreeBytesAvailableF, &TotalNumberOfBytesF, &TotalNumberOfFreeBytesF);
float totalHardDisk = GB(TotalNumberOfBytesC) + GB(TotalNumberOfBytesD) + GB(TotalNumberOfBytesE) + GB(TotalNumberOfBytesF);
float freeHardDisk = GB(TotalNumberOfFreeBytesC) + GB(TotalNumberOfFreeBytesD) + GB(TotalNumberOfFreeBytesE) + GB(TotalNumberOfFreeBytesF);
double hardDiskUsage = (1 - freeHardDisk / totalHardDisk) * 100;
auto res = std::make_pair((byte)hardDiskUsage, ushort(freeHardDisk));
return res;
}
byte Monitor::GetMemoryRate_byte() {
MEMORYSTATUSEX statex;
statex.dwLength = sizeof(statex);
GlobalMemoryStatusEx(&statex);
double memoryUse = statex.dwMemoryLoad;
return memoryUse;
}
void Monitor::getHastate(byte* cpuusage, byte* gpuusage,
byte* hduusage, ushort* hdremain, byte* memusage)
{
*cpuusage = GetCpuRate_byte();
*gpuusage = GetGpuRate_byte();
auto hdu = GetDiskRate_byte();
*hduusage = hdu.first;
*hdremain = hdu.second;
*memusage = GetMemoryRate_byte();
}
其中需要注意的就是关于GPU相关信息的获取,涉及到英伟达显卡的头文件和那个lib在显卡的默认安装路径就可以找得到,如果不同的话直接替换一下路径即可
然后还需要注意的一点是,需要在C:\Program Files\NVIDIA Corporation\NVSMI目录下有一个nvml.dll,可能需要把这个动态库放到编译出来的可执行文件的同级目录中
关于这个操作的参考链接如下:
nvml.dll找不到怎么办
windows平台关于GPU信息的获取 C++
可能会有小错误,是因为我从整个项目里粘出来的时候误删了…
另外一份调试通过的获取GPU利用率的代码
#include <cuda_runtime.h>
#include <iostream>
#include <memory>
#include <string>
//#pragma comment(lib, "C:\\Program Files\\NVIDIA GPU Computing Toolkit\\CUDA\\v10.2\\lib\\x64\\cudart.lib")
//注释掉的东西不写也可以,在编译器中设置好引用的lib即可
void checkGpuMem() {
size_t avail;
size_t total;
cudaMemGetInfo(&avail, &total);
size_t used = total - avail;
std::cout << "=================" << std::endl;
std::cout << "Device memory used: " << used << std::endl;
std::cout << "Total memory used: " << total << std::endl;
std::cout << "=================" << std::endl;
}
int main() {
int deviceCount = 0;
cudaError_t error_id = cudaGetDeviceCount(&deviceCount);
// This function call returns 0 if there are no CUDA capable devices.
if (deviceCount == 0) {
printf("There are no available device(s) that support CUDA\n");
}
else {
printf("Detected %d CUDA Capable device(s)\n", deviceCount);
}
checkGpuMem();
getchar();
}