Показать сообщение отдельно
  #2  
Старый 03.01.2018, 17:20
Prok186 Prok186 вне форума
Прохожий
 
Регистрация: 19.06.2011
Сообщения: 22
Репутация: 10
Подмигивание GPU usage NVIDIA & AMD

Определение загрузки и температуры GPU типа AMD добавил в пример (ранее всё было только для NVIDIA). Использовал библиотеку atiadlxx.dll. Эта библиотека устанавливается автоматически при установке драйверов видео-карты AMD (у меня это простенькая Radeon M275x). Пример перезалил в ту же папку для скачивания http://gofile.me/2Zesj/C0f3wb1o , в ту же уже ранее добавленную под-папку:
OpenCL_Demo2017 Barrier and Local_Memory REDUCT
Но вот как определить, сколько памяти на GPU именно AMD уже занято - не разобрался. В стандартных утилитах типа GPU-z 2.5.0 это как-то делается и для AMD тоже : значит, способ есть . Может кто-то подсказать?
Ниже дублирую Delphi XE8 код для определения загрузки CPU - GPU-NVIDIA-AMD (компиляция под Win64 !)
Код:
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 : Integer);
//... Температуры выдаются в град.С, частоты- в MHz, остальное- в % ...
procedure GPUusageInitialize; // Запустить 1 раз в начале
procedure GPUusageNVIDIA(const GPU_num : Byte;
  out GPU_usage, MemoryController, Memory,
  Temperature,  GPU_freq,  MEM_freq, FanSpeed : 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;
//
//========== Определение загрузки CPU (в процентах 0..100) ============
procedure CPUusage(const Initialize : Boolean;
  out Total, MyProcess : Integer);
var IdleTime, CreationTime, ExitTime, KernelTime, UserTime : TFileTime;
 IdleTime64, KernelTime64, UserTime64, NewProcT64, DIdle, Dsum : Int64;
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;
   except
   Total := 0;   MyProcess := 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;
//
//
//+++++++++++ Типы для библиотечных функций 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;
//
Ответить с цитированием