unit ProcessorUsage; |
{=====================================================================} |
{**** Моделирование 3D течений, переноса тепла и деформаций дна. ****} |
{==== Модуль определения загрузки CPU (общей и процессом) и GPU ====} |
{========= Прокофьев В.А. АО "ВНИИГ им. Б.Е.Веденеева" ========} |
{========= 01.2018 С.Петербург. e-mail: Prok12@Rambler.ru ========} |
{=====================================================================} |
interface |
|
uses Windows, SysUtils, Dialogs; |
|
// В начале 1 раз вызвать с параметром Initialize = True |
procedure CPUusage(const Initialize : Boolean; |
out Total, MyProcess, TotalMemory, ProcessMemory : Integer); |
//... Температуры выдаются в град.С, частоты- в MHz, ... |
//... потребляемая мощность- в Ваттах, остальное- в % ... |
procedure GPUusageInitialize; // Запустить 1 раз в начале |
procedure GPUusageNVIDIA(const GPU_num : Byte; |
out GPU_usage, MemoryController, Memory, Temperature, |
GPU_freq, MEM_freq, FanSpeed, Power : Integer); |
procedure GPUusageAMD(const GPU_num : Byte; |
out GPU_usage, Temperature, GPU_freq, Mem_freq, FanSpeed : Integer); |
procedure GPUusageShutdown; // Запустить 1 раз в конце |
// |
type TypeGPU = (gpuNO = 0, gpuNVIDIA = 1, gpuAMD = 2); |
// |
var Initialize_NVIDIA_OK : Boolean = False; |
Initialize_AMD_OK : Boolean = False; |
// |
//===================================================================== |
implementation |
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
//++++++++++++++++ Сначала работаем с загрузкой CPU +++++++++++++++++++ |
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
var OldIdleTime64, OldSysTime64, OldProcT64 : Int64; |
// |
{==== Определение размера выделенной приложению памяти (в Байтах) ====} |
function MyGetAllocatedMemory: UInt64; |
var St: TMemoryManagerState; Sb: TSmallBlockTypeState; |
begin |
GetMemoryManagerState(St); |
Result := St.TotalAllocatedMediumBlockSize + |
St.TotalAllocatedLargeBlockSize; |
For Sb in St.SmallBlockTypeStates do |
Result := Result + Sb.UseableBlockSize * Sb.AllocatedBlockCount; |
end; |
|
//===================================================================== |
//========== Определение загрузки CPU (в процентах 0..100) ============ |
//===================================================================== |
procedure CPUusage(const Initialize : Boolean; |
out Total, MyProcess, TotalMemory, ProcessMemory : Integer); |
var IdleTime, CreationTime, ExitTime, KernelTime, UserTime : TFileTime; |
IdleTime64, KernelTime64, UserTime64, NewProcT64, DIdle, Dsum : Int64; |
MemStatusCPU: TMemoryStatus; |
begin |
Try |
Dsum := 1; //... только чтобы не было Warning |
//=== 1) Определим загрузку CPU всеми процессами в системе (Total) ==== |
GetSystemTimes(IdleTime, KernelTime, UserTime); |
// См. https://www.codeproject.com/Articles/9113/ |
// Get-CPU-Usage-with-GetSystemTimes |
Move(IdleTime, IdleTime64, 8); |
Move(KernelTime, KernelTime64, 8); Move(UserTime, UserTime64, 8); |
If Initialize then Total := 0 else begin |
DIdle := IdleTime64 - OldIdleTime64; |
Dsum := KernelTime64 + UserTime64 - OldSysTime64; |
If Dsum <= 0 then DSum := 1; |
// KernelTime включает в себя и IdleTime ! |
Total := Round(100.0 * (Dsum - Didle) / Dsum); |
If Total < 0 then Total := 0; |
If Total > 100 then Total := 100; |
end; |
OldIdleTime64 := IdleTime64; // Время простоя CPU |
// Общее время, включая простой |
OldSysTime64 := KernelTime64 + UserTime64; |
// |
//=== 2) Определим загрузку CPU только нашим процессом (MyProcess) ==== |
GetProcessTimes(GetCurrentProcess, CreationTime, |
ExitTime, KernelTime, UserTime); |
Move(KernelTime, KernelTime64, 8); Move(UserTime, UserTime64, 8); |
NewProcT64 := KernelTime64 + UserTime64; |
// Dsum- интервал астрономического времени между 2-мя вызовами CPUusage |
If Initialize then MyProcess := 0 else |
MyProcess := Round(100.0 * (NewProcT64 - OldProcT64) / Dsum); |
If MyProcess < 0 then MyProcess := 0; |
If MyProcess > 100 then MyProcess := 100; |
OldProcT64 := NewProcT64; |
// |
//=============== 3) Определим загрузку памяти CPU ==================== |
MemStatusCPU.dwLength := SizeOf(MemStatusCPU); |
GlobalMemoryStatus(MemStatusCPU); |
TotalMemory := MemStatusCPU.dwMemoryLoad; // Всего занято процентов |
ProcessMemory := Round(100 * MyGetAllocatedMemory / |
MemStatusCPU.dwTotalPhys); // Только нашим процессом, в процентах |
except |
Total := 0; MyProcess := 0; |
TotalMemory := 0; ProcessMemory := 0; |
end; |
end; |
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
//+++++++++++ Далее работаем с имеющимися в системе GPU +++++++++++++++ |
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
type Empty_Record = record end; // По аналогии с OpenCL Headers |
nvmlDevice_t = ^Empty_Record; // в Header-файле для MS C++ также |
p_nvmlDevice_t = ^nvmlDevice_t; |
nvmlReturn_t = Integer; |
//..... Для определения загрузки GPU и контроллера памяти NVIDIA ...... |
nvmlUtilization_t = packed record |
GPU, Mem : UInt; |
end; |
p_nvmlUtilization_t = ^nvmlUtilization_t; |
//......... Для определения процентной загрузки памяти NVIDIA ......... |
nvmlMemory_t = packed record |
Total, Free, Used : UInt64; |
end; |
p_nvmlMemory_t = ^nvmlMemory_t; |
// |
//~~~~ Clock types (для определения частот GPU и Memory у NVIDIA) ~~~~~ |
const NVML_CLOCK_GRAPHICS = 0; // Graphics clock domain |
NVML_CLOCK_MEM = 2; // Memory clock domain |
|
var // Описываем прототипы вызываемых из nvml.dll функций |
nvmlInit : function() : nvmlReturn_t; stdcall; |
nvmlShutdown : function() : nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetCount : function(pDevCount: pUInt) : |
nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetHandleByIndex : function (GPUnum : UInt; |
pHandle: p_nvmlDevice_t) : nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetUtilizationRates : function (GPU_Handle1 : nvmlDevice_t; |
pUtilization: p_nvmlUtilization_t) : nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetMemoryInfo : function(GPU_Handle1 : nvmlDevice_t; |
pDeviceMem: p_nvmlMemory_t) : nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetTemperature : function(GPU_Handle1 : nvmlDevice_t; |
SensorType : Integer; pTemp : pUInt) : nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetClockInfo : function(GPU_Handle1 : nvmlDevice_t; |
ClockType: Integer; Clock : pUInt) : nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetFanSpeed : function(GPU_Handle1 : nvmlDevice_t; |
speed: pUInt) : nvmlReturn_t; stdcall; |
//..................................................................... |
nvmlDeviceGetPowerUsage : function(GPU_Handle1 : nvmlDevice_t; |
pPower : pUint) : nvmlReturn_t; stdcall; |
// |
// |
//+++++++++++ Типы для библиотечных функций atiadlxx.dll ++++++++++++++ |
// (AMD - GPU) |
// MyMALLOC подсмотрел здесь : http://www.delphipraxis.net/ |
// 131660-uebersetzung-c-pascal-callback-zugriffsverletzung.html |
type tADL_MAIN_MALLOC_CALLBACK = function(iSize : Integer) : |
Pointer; stdcall; |
pADL_MAIN_MALLOC_CALLBACK = ^tADL_MAIN_MALLOC_CALLBACK; |
// Указатель на эту ф-ю выделения памяти передаётся в инициализацию AMD |
function MyMALLOC(iSize : Integer) : Pointer; stdcall; |
begin |
Result := AllocMem(iSize); |
end; |
|
//...... Для получении информации о загрузке GPU-AMD и частотах ....... |
type ADLPMActivity = packed record |
iSize : Integer; // Must be set to the size of the structure |
iEngineClock : Integer; // Current engine frequency [in 10KHz] |
iMemoryClock : Integer; // Current memory frequency [in 10KHz] |
iVddc : Integer; // Current core voltage. |
iActivityPercent : Integer; // GPU utilization. |
iCurrentPerformanceLevel : Integer; //Performance level index. |
iCurrentBusSpeed : Integer; // Current PCIE bus speed. |
iCurrentBusLanes : Integer; // Number of PCIE bus lanes. |
iMaximumBusLanes : Integer; // Maximum number of PCIE bus lanes. |
iReserved : Integer; // Reserved for future purposes. |
end; |
pADLPMActivity = ^ADLPMActivity; |
|
//........ Для получении информации о температуре GPU-AMD ............. |
type ADLTemperature = packed record |
iSize : Integer; // Must be set to the size of the structure |
iTemperature : Integer; // Temperature in millidegrees Celsius |
end; |
pADLTemperature = ^ADLTemperature; |
|
//.......... Для получении информации о памяти на борту AMD ........... |
type ADLMemoryInfo = packed record |
iMemorySize : Int64; // Memory size in bytes |
// Только AnsiChar позволяет прочитать тип памяти из следующей строки |
strMemoryType: array[0..255] of AnsiChar; |
iMemoryBandwidth : Int64; // Memory bandwidth in Mbytes/s. |
end; |
pADLMemoryInfo = ^ADLMemoryInfo; |
|
//........ Для получении информации о скорости вентилятора AMD ........ |
const ADL_DL_FANCTRL_SPEED_TYPE_PERCENT = 1; |
ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED = 1; |
|
type ADLFanSpeedValue = packed record |
iSize : Integer; // Must be set to the size of the structure |
// Possible values: ADL_DL_FANCTRL_SPEED_TYPE_PERCENT or |
// ADL_DL_FANCTRL_SPEED_TYPE_RPM |
iSpeedType : Integer; |
iFanSpeed : Integer; // Fan speed value |
// The only flag for now is: ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED |
iFlags : Integer; |
end; |
pADLFanSpeedValue = ^ADLFanSpeedValue; |
// |
//=== Функции Overdrive6 работают не на всех системах => Overdrive5 === |
var // Описываем прототипы вызываемых из atiadlxx.dll функций |
ADL_Main_Control_Create : function( |
callback : pADL_MAIN_MALLOC_CALLBACK; |
iEnumConnectedAdapters : Integer) : nvmlReturn_t; stdcall; |
//..................................................................... |
ADL_Main_Control_Destroy: function() : nvmlReturn_t; stdcall; |
//..................................................................... |
ADL_Overdrive5_CurrentActivity_Get: function(iAdapterIndex : Integer; |
pActivity : pADLPMActivity) : nvmlReturn_t; stdcall; |
//..................................................................... |
ADL_Adapter_NumberOfAdapters_Get : function(pNumAdapters : pInt) : |
nvmlReturn_t; stdcall; |
//..................................................................... |
ADL_Adapter_Active_Get : function(iAdapterIndex : Integer; |
pStatus : pInt) : nvmlReturn_t; stdcall; |
//..................................................................... |
ADL_Overdrive5_Temperature_Get : function(iAdapterIndex : Integer; |
iThermalControllerIndex : Integer; |
pTemperature : pADLTemperature) : nvmlReturn_t; stdcall; |
//..................................................................... |
ADL_Overdrive5_FanSpeed_Get : function(iAdapterIndex : Integer; |
iThermalControllerIndex : Integer; |
pFanSpeedValue : pADLFanSpeedValue) : nvmlReturn_t; stdcall; |
//..................................................................... |
ADL_Adapter_MemoryInfo_Get : function(iAdapterIndex : Integer; |
pMemoryInfo: pADLMemoryInfo) : nvmlReturn_t; stdcall; |
//..................................................................... |
|
var GPU_count_NVIDIA, GPU_count_AMD: Integer; //UInt; |
LibHandleNV, LibHandleAMD: hModule; |
ShowMessageAMD : Boolean; |
// |
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
//++++ Инициализация функций из библиотек nvml.dll и atiadlxx.dll +++++ |
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
procedure GPUusageInitializeNVIDIA; forward; |
procedure GPUusageInitializeAMD; forward; |
// |
procedure GPUusageInitialize; |
begin |
GPUusageInitializeNVIDIA; |
GPUusageInitializeAMD; |
end; |
// |
//===================================================================== |
//==== Сначала пытаемся инициализировать библиотеку для NVIDIA ====== |
//===================================================================== |
procedure GPUusageInitializeNVIDIA; |
//.... По умолчанию устанавливается только версия библиотеки 64bit .... |
// См. https://devtalk.nvidia.com/default/topic/525514/ |
// can-39-t-find-nvml-dll-in-display-drivers/ |
const nvml_Lib : WideString = |
'C:\Program Files\NVIDIA Corporation\NVSMI\nvml.dll'; |
//..................................................................... |
procedure ProcNV(var Fun: Pointer; const FunName: WideString); |
begin |
FreeAndNil(Fun); |
// Здесь 2-ой параметр м.б. либо ANSI, либо Unicode=WideChar - overload |
Fun := GetProcAddress(LibHandleNV, PWideChar(FunName)); |
end; |
//..................................................................... |
begin |
If not Initialize_NVIDIA_OK then try |
// Проверим, существует ли по указанному пути файл библиотеки nvml.dll |
If not FileExists(nvml_Lib) then raise EAbort.Create(''); |
// Лучше конкретно писать LoadLibraryW : работаем с Unicode = PWideChar |
LibHandleNV := LoadLibraryW(PWideChar(nvml_Lib)); |
// Если не удалось загрузить библиотеку nvml.dll |
If LibHandleNV = 0 then raise EAbort.Create(''); |
// Определяем адреса всех необходимых процедур из библиотеки NVIDIA |
ProcNV(@nvmlInit, 'nvmlInit'); |
ProcNV(@nvmlShutdown, 'nvmlShutdown'); |
ProcNV(@nvmlDeviceGetCount, 'nvmlDeviceGetCount'); |
ProcNV(@nvmlDeviceGetHandleByIndex, 'nvmlDeviceGetHandleByIndex'); |
ProcNV(@nvmlDeviceGetUtilizationRates, |
'nvmlDeviceGetUtilizationRates'); |
ProcNV(@nvmlDeviceGetMemoryInfo, 'nvmlDeviceGetMemoryInfo'); |
ProcNV(@nvmlDeviceGetTemperature, 'nvmlDeviceGetTemperature'); |
ProcNV(@nvmlDeviceGetClockInfo, 'nvmlDeviceGetClockInfo'); |
ProcNV(@nvmlDeviceGetFanSpeed, 'nvmlDeviceGetFanSpeed'); |
ProcNV(@nvmlDeviceGetPowerUsage, 'nvmlDeviceGetPowerUsage'); |
// Инициализация функций библиотеки nvml.dll |
If nvmlInit() <> 0 then raise EAbort.Create(''); |
// Определение кол-ва GPU в конкретной системе : только для контроля |
If nvmlDeviceGetCount(@GPU_count_NVIDIA) <> 0 then |
raise EAbort.Create(''); |
Initialize_NVIDIA_OK := True; |
except |
Initialize_NVIDIA_OK := False; FreeLibrary(LibHandleNV); |
end; |
end; |
// |
//===================================================================== |
//====== Далее пытаемся инициализировать библиотеку для AMD ========= |
//===================================================================== |
procedure GPUusageInitializeAMD; |
var MaxAMD, iAdapterAMD, StatusAMD : Integer; |
//..................................................................... |
procedure ProcAMD(var Fun: Pointer; const FunName: WideString); |
begin |
FreeAndNil(Fun); |
// Здесь 2-ой параметр м.б. либо ANSI, либо Unicode(WideChar)- overload |
Fun := GetProcAddress(LibHandleAMD, PWideChar(FunName)); |
end; |
//..................................................................... |
begin |
ShowMessageAMD := True; |
If not Initialize_AMD_OK then try |
LibHandleAMD := LoadLibraryW(PWideChar(WideString('atiadlxx.dll'))); |
// Если не удалось загрузить библиотеку atiadlxx.dll |
If LibHandleAMD = 0 then raise EAbort.Create(''); |
// Определяем адреса всех необходимых процедур из библиотеки AMD |
ProcAMD(@ADL_Main_Control_Create, 'ADL_Main_Control_Create'); |
ProcAMD(@ADL_Main_Control_Destroy, 'ADL_Main_Control_Destroy'); |
ProcAMD(@ADL_Overdrive5_CurrentActivity_Get, |
'ADL_Overdrive5_CurrentActivity_Get'); |
ProcAMD(@ADL_Adapter_NumberOfAdapters_Get, |
'ADL_Adapter_NumberOfAdapters_Get'); |
ProcAMD(@ADL_Adapter_Active_Get, 'ADL_Adapter_Active_Get'); |
ProcAMD(@ADL_Overdrive5_Temperature_Get, |
'ADL_Overdrive5_Temperature_Get'); |
ProcAMD(@ADL_Overdrive5_FanSpeed_Get, |
'ADL_Overdrive5_FanSpeed_Get'); |
ProcAMD(@ADL_Adapter_MemoryInfo_Get, |
'ADL_Adapter_MemoryInfo_Get'); |
// |
//....... Определяем GPU_HandleAMD (инициализация функций AMD) ........ |
// 2-ой парметр = 0 : значит, что для всех доступных AMD-устройств |
If ADL_Main_Control_Create(@MyMALLOC, 0) <> 0 |
then raise EAbort.Create(''); |
// |
//=====> Получаем информацию об общем количестве адаптеров AMD <======= |
If ADL_Adapter_NumberOfAdapters_Get(@MaxAMD) <> 0 |
then raise EAbort.Create(''); |
//......... Подсчитаем количество активных адаптеров AMD .............. |
GPU_count_AMD := 0; // На моноблоке ASUS ET2702i вышло MaxAMD = 6 ! |
For iAdapterAMD := 0 to MaxAMD - 1 do begin |
If ADL_Adapter_Active_Get(iAdapterAMD, @StatusAMD) <> 0 |
then raise EAbort.Create(''); |
If StatusAMD <> 0 then Inc(GPU_count_AMD); |
end; |
//..................................................................... |
Initialize_AMD_OK := True; |
except |
Initialize_AMD_OK := False; FreeLibrary(LibHandleAMD); |
end; |
end; |
// |
procedure NVIDIA_Shutdown; forward; |
//===================================================================== |
//===== Определение загрузки NVIDIA-GPU с номером GPU_num (от 0) ====== |
//===================================================================== |
procedure GPUusageNVIDIA(const GPU_num : Byte; |
out GPU_usage, MemoryController, Memory, // Всё в процентах |
Temperature, // degrees C |
GPU_freq, MEM_freq, // MHz |
FanSpeed, // Скорость вентилятора в процентах |
Power : Integer); // Потребляемая мощность в Ваттах |
var GPU_Handle : nvmlDevice_t; UtilGPU : nvmlUtilization_t; |
MemGPU : nvmlMemory_t; nvmlValue : UInt; |
begin |
//!!! Значение -1 -это признак, что параметр не удалось определить !!!! |
GPU_usage := -1; MemoryController := -1; Memory := -1; |
GPU_freq := -1; MEM_freq := -1; |
Temperature := -1; FanSpeed := -1; Power := -1; |
If Initialize_NVIDIA_OK and (GPU_num < GPU_count_NVIDIA) then try |
// |
//=============> Определение Handle для выбранного GPU <=============== |
If nvmlDeviceGetHandleByIndex(GPU_num, @GPU_Handle) <> 0 |
then raise EAbort.Create(''); |
// След. вызовы будут с ошибками, если nvml.dll от другой видеокарты!! |
// |
//====> Получаем информацию о загрузке потоковых процессоров GPU <===== |
If nvmlDeviceGetUtilizationRates(GPU_Handle, @UtilGPU) = 0 |
then begin |
GPU_usage := UtilGPU.GPU; MemoryController := UtilGPU.Mem; |
end; |
// |
//=======> Получаем информацию об использовании памяти GPU <=========== |
If nvmlDeviceGetMemoryInfo(GPU_Handle, @MemGPU) = 0 |
then Memory := Round( 100 * MemGPU.Used / MemGPU.Total ); |
// |
//=========> Получаем информацию о температуре NVIDIA-GPU <============ |
If nvmlDeviceGetTemperature(GPU_Handle, 0, @nvmlValue) = 0 |
then Temperature := nvmlValue; |
// |
//=====> Получаем информацию о частотах процессора и памяти GPU <====== |
If nvmlDeviceGetClockInfo(GPU_Handle, NVML_CLOCK_GRAPHICS, |
@nvmlValue) = 0 then GPU_freq := nvmlValue; |
If nvmlDeviceGetClockInfo(GPU_Handle, NVML_CLOCK_MEM, |
@nvmlValue) = 0 then MEM_freq := nvmlValue; |
// |
//=====> Получаем информацию о скорости вентилятора NVIDIA-GPU <======= |
If nvmlDeviceGetFanSpeed(GPU_Handle, @nvmlValue) = 0 |
then FanSpeed := nvmlValue; //...в процентах, а не в RPM |
// |
//=====> Получаем информацию о потребляемой мощности NVIDIA-GPU <====== |
If nvmlDeviceGetPowerUsage(GPU_Handle, @nvmlValue) = 0 |
then Power := Round(1E-3 * nvmlValue); //...миллиВатты в Ватты |
// |
except |
NVIDIA_Shutdown; |
end; |
// Если не удалось определить ни одного параметра, отключаем библиотеку |
If GPU_usage + MemoryController + Memory + GPU_freq + MEM_freq + |
Temperature + FanSpeed + Power = -8 then NVIDIA_Shutdown; |
end; |
// |
procedure AMD_Shutdown; forward; |
//===================================================================== |
//======= Определение загрузки AMD-GPU с номером GPU_num (от 0) ======= |
//===================================================================== |
procedure GPUusageAMD(const GPU_num : Byte; |
out GPU_usage, Temperature, GPU_freq, Mem_freq, FanSpeed : Integer); |
var MemoryInfo : ADLMemoryInfo; MemoryType : String; |
MyFanSpeed : ADLFanSpeedValue; MyActivity : ADLPMActivity; |
MyTemp : ADLTemperature; |
const CRLF = #13#10; // Переход на новую строку для ShowMessage |
begin |
//!!! Значение -1 -это признак, что параметр не удалось определить !!!! |
GPU_usage := -1; GPU_freq := -1; MEM_freq := -1; |
Temperature := -1; FanSpeed := -1; |
If Initialize_AMD_OK and (GPU_num < GPU_count_AMD) then try |
// |
//====> Получаем информацию о загрузке потоковых процессоров GPU <===== |
MyActivity.iSize := SizeOf(ADLPMActivity); |
If ADL_Overdrive5_CurrentActivity_Get(GPU_num, @MyActivity) = 0 |
then begin |
GPU_usage := MyActivity.iActivityPercent; |
GPU_freq := Round(0.01 * MyActivity.iEngineClock); |
MEM_freq := Round(0.01 * MyActivity.iMemoryClock); |
end; |
// |
//===========> Получаем информацию о температуре AMD-GPU <============= |
MyTemp.iSize := SizeOf(ADLTemperature); |
If ADL_Overdrive5_Temperature_Get(GPU_num, 0, @MyTemp) = 0 then |
// Температура была в милли-градусах C |
Temperature := Round(0.001 * MyTemp.iTemperature); |
// |
//======> Получаем информацию о скорости вентилятора AMD-GPU <========= |
MyFanSpeed.iSize := SizeOf(ADLFanSpeedValue); |
MyFanSpeed.iFlags := ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED; |
MyFanSpeed.iSpeedType := ADL_DL_FANCTRL_SPEED_TYPE_PERCENT; |
If ADL_Overdrive5_FanSpeed_Get(GPU_num, 0, @MyFanSpeed) = 0 |
then FanSpeed := MyFanSpeed.iFanSpeed; |
// |
//...... Один раз покажем информацию о памяти на борту AMD-GPU ........ |
If ShowMessageAMD then begin |
ShowMessageAMD := False; |
//===> Получаем информацию об общем количестве памяти на борту GPU <=== |
If ADL_Adapter_MemoryInfo_Get(GPU_num, @MemoryInfo) = 0 |
then begin |
// Переводим AnsiString --> String , контролируем длину строки |
MemoryType := String(MemoryInfo.strMemoryType); |
ShowMessage('Active GPU_count_AMD = ' + |
IntToStr(GPU_count_AMD) + CRLF + |
'Memory (' + MemoryType + ') = ' + |
IntToStr(Round(MemoryInfo.iMemorySize / (1024*1024))) + |
' MBytes' + CRLF + 'MemoryType string Length = ' + |
IntToStr(Length(MemoryType)) + CRLF + 'Memory Bandwidth= ' + |
IntToStr(MemoryInfo.iMemoryBandwidth) + ' MBytes/s'); |
end; |
end; |
except |
AMD_Shutdown; |
end; |
// Если не удалось определить ни одного параметра, отключаем библиотеку |
If GPU_usage + GPU_freq + MEM_freq + |
Temperature + FanSpeed = -5 then AMD_Shutdown; |
end; |
// |
//--------------------------------------------------------------------- |
//----------- Отключение библиотек nvml.dll и atiadlxx.dll ------------ |
//--------------------------------------------------------------------- |
procedure NVIDIA_Shutdown; |
begin |
If Initialize_NVIDIA_OK then try |
Initialize_NVIDIA_OK := False; nvmlShutdown(); |
finally |
FreeLibrary(LibHandleNV); |
end; |
end; |
//..................................................................... |
procedure AMD_Shutdown; |
begin |
If Initialize_AMD_OK then try |
Initialize_AMD_OK := False; ADL_Main_Control_Destroy(); |
finally |
FreeLibrary(LibHandleAMD); |
end; |
end; |
//..................................................................... |
procedure GPUusageShutdown; |
begin |
NVIDIA_Shutdown; AMD_Shutdown; |
end; |
|
end. |