Перейти к содержанию
Fire Monkey от А до Я
  • 0

Узнать размер видеопамяти


Mars M

Вопрос

Как можно узнать размер видеопамяти под WIN?

В инете находятся решения через реестр, с помощью DX и другие, но все сообщения старые.

Может есть какой способ узнать средствами FMX?

 

Ссылка на комментарий

Рекомендуемые сообщения

  • 0

Для Cuda тут https://github.com/nicehash/NiceHashMiner/tree/master/CudaDeviceDetection , 

для OpenCL тут https://github.com/nicehash/NiceHashMiner/tree/master/AMDOpenCLDeviceDetection

код на сях, но перевести на Delphi думаю не очень сложно.

Ссылка на комментарий
  • 0
7 минут назад, Mars M сказал:

Спасибо, ссылки в любом случае полезные. Но, если я правильно понял, там придется SDK устанавливать на клиентском компе.

Нет, ни в коем случае. Если стоят драйвера на видеокарту, то все будет работать. Можете попробовать запустить у себя бинарники и проверить, они выдают JSON на стандартный вывод, вот такой примерно:

[
    {
        "DeviceID": 0,
        "VendorID": 5208,
        "VendorName": "Gigabyte",
        "DeviceName": "GeForce GTX 960",
        "SMVersionString": "5.2",
        "SM_major": 5,
        "SM_minor": 2,
        "UUID": "GPU-f4867f81-dcc8-0f28-fbc2-b350e7927c22",
        "DeviceGlobalMemory": 4294967296,
        "pciDeviceId": 335614174,
        "pciSubSystemId": 918426712,
        "SMX": 8
    }
]

Нужный параметр DeviceGlobalMemory.

Бинарники можно взять из архива https://github.com/nicehash/NiceHashMiner/releases/tag/1.7.5.10 , называются AMDOpenCLDeviceDetection.exe и CudaDeviceDetection.exe.

Если переведете код в Delphi, буду безмерно благодарен. Сейчас в нескольких проектах (мониторинг "отваливания" карт) использую внешний вызов этих exe, что несколько неудобно.

Ссылка на комментарий
  • 1

Вместо утреннего кофе, уперся рогом и сделал получение информации через CUDA, тесовый проект прилагаю.

В режиме отладки работает отлично, вижу размер видеопамяти, но потом вылетает с access violation (при обращении к визуальным компонентам или просто при продолжении работы). В чем дело понять не могу, сначала грешил на FMX, но проект на VCL выдает те же симптомы. Очень, очень странные дела...

Код простой, используется cudaRT.pas из CUDA wraper Паскуда https://code.google.com/archive/p/pascuda/source/default/source и cudart32_65.dll идущая вместе с драйверами NVIDIA

Var CudaDeviceProp : TCudaDeviceProp;
    hDevice: Integer;
    GPUMemorySize : Cardinal;
    LMessage : String;
begin
  hDevice:=0;
  if CudaGetDeviceProperties(CudaDeviceProp, hDevice)=ceSuccess then
  begin
    GPUMemorySize:=CudaDeviceProp.TotalGlobalMem  div 1024 div 1024;
    LMessage:=Format('GPU Memory size = %d Mb', [GPUMemorySize]);
    Memo.Lines.Add(LMessage);
  end;

 

test099 Cuda Info VCL.7z

Ссылка на комментарий
  • 0
6 часов назад, Евгений Корепов сказал:

Очень, очень странные дела...

Скачал с инета cudart32_41_28.dll, с ней все нормально.

Мне кажется что запись TCudaDeviceProp в разных версиях пишется по разному.

Ссылка на комментарий
  • 0
  • Модераторы
15 минут назад, Mars M сказал:

Скачал с инета cudart32_41_28.dll, с ней все нормально.

Мне кажется что запись TCudaDeviceProp в разных версиях пишется по разному.

аналогично, все прекрасно завелось с этой либой

Ссылка на комментарий
  • 0
20 минут назад, Mars M сказал:

Скачал с инета cudart32_41_28.dll, с ней все нормально.

Мне кажется что запись TCudaDeviceProp в разных версиях пишется по разному.

Действительно. Мог бы я и сам догадаться - функция возвращает куда больший кусок памяти чем описано структурой, вот лишние данные и залезают в память выделенную под другие нужды.

Вот тут описание структуры http://docs.nvidia.com/cuda/cuda-runtime-api/structcudaDeviceProp.html#structcudaDeviceProp и видимо под каждую версию Cuda она своя.

Или таскать именно cudart32_41_28.dll с приложением.

Изменено пользователем Евгений Корепов
Ссылка на комментарий
  • 0

Вот так вот вроде работает:

Скрытый текст

  TCudaDeviceProp = packed record
    Name: array[0..256 - 1] of AnsiChar;
    TotalGlobalMem: Cardinal;
    SharedMemPerBlock: Cardinal;
    RegsPerBlock: Integer;
    WarpSize: Integer;
    MemPitch: Cardinal;
    MaxThreadsPerBlock: Integer;
    MaxThreadsDim: array[0..3 - 1] of Integer;
    MaxGridSize: array[0..3 - 1] of Integer;
    ClockRate: Integer;
    TotalConstMem: Cardinal;
    Major: Integer;
    Minor: Integer;
    TextureAlignment: Cardinal;
    texturePitchAlignment: Cardinal;
    DeviceOverlap: Integer;
    MultiProcessorCount: Integer;
    kernelExecTimeoutEnabled: Integer;
    integrated: Integer;
    canMapHostMemory: Integer;
    computeMode: Integer;
    maxTexture1D: Integer;
    maxTexture1DMipmap: Integer;
    maxTexture1DLinear: Integer;
    maxTexture2D: array[0..2 - 1] of Integer;
    maxTexture2DMipmap: array[0..1] of integer;
    maxTexture2DLinear: array[0..3 - 1] of Integer;
    maxTexture2DGather: array[0..2 - 1] of Integer;
    maxTexture3D: array[0..3 - 1] of Integer;
    maxTexture3DAlt: array[0..2] of integer;
    maxTextureCubemap: Integer;
    maxTexture1DLayered: array[0..2 - 1] of Integer;
    maxTexture2DLayered: array[0..3 - 1] of Integer;
    maxTextureCubemapLayered: array[0..2 - 1] of Integer;
    maxSurface1D: Integer;
    maxSurface2D: array[0..2 - 1] of Integer;
    maxSurface3D: array[0..3 - 1] of Integer;
    maxSurface1DLayered: array[0..2 - 1] of Integer;
    maxSurface2DLayered: array[0..3 - 1] of Integer;
    maxSurfaceCubemap: Integer;
    maxSurfaceCubemapLayered: array[0..2 - 1] of Integer;
    surfaceAlignment: Cardinal;
    concurrentKernels: Integer;
    ECCEnabled: Integer;
    pciBusID: Integer;
    pciDeviceID: Integer;
    pciDomainID: Integer;
    tccDriver: Integer;
    asyncEngineCount: Integer;
    unifiedAddressing: Integer;
    memoryClockRate: Integer;
    memoryBusWidth: Integer;
    l2CacheSize: Integer;
    maxThreadsPerMultiProcessor: Integer;
    streamPrioritiesSupported: Integer;
    globalL1CacheSupported: Integer;
    localL1CacheSupported: Integer;
    sharedMemPerMultiprocessor: Cardinal;
    regsPerMultiprocessor: Integer;
    managedMemory: integer;
    isMultiGpuBoard: integer;
    multiGpuBoardGroupID: Integer;
  end;

 

Только нужно будет закомментировать строчку

assert(sizeof(TCudaDeviceProp) = 540, 'sizeof(TCudaDeviceProp) <> 540');

 

Ссылка на комментарий
  • 0

Подниму тему. CUDA конечно хорош(а?), но только для nvidia.

Наткнулся тут на работу с OpenCL в делфи http://www.delphisources.ru/forum/showthread.php?t=28188

Там по ссылке в первом сообщение в принципе все есть что нужно. Кому оттуда не удобно перезалил все файлы https://yadi.sk/d/t3mPqlJT3HnfiX

Вот пример использования https://yadi.sk/d/bmDKXZ0k3Hnfny

Проверял на картах nvidia и ati, конечно же карты должны поддерживать OpenCL.

Если в MyOpenCL.pas чего то не хватает, можно взять это в CL.pas из GLScene https://sourceforge.net/p/glscene/code/HEAD/tree/trunk/Source/ParallelAPIs/

Я например добавил константу   CL_DEVICE_LOCAL_MEM_SIZEэ

А можно использовать родные CL.pas и CL_Platform.pas, в первом архиве есть пример использования.

В 03.05.2017 в 20:29, Евгений Корепов сказал:

Хоть и не в тему топика, но хочу какие нибудь вычисления замонстрячить!

В архиве как раз есть рабочий пример вычислений :)

Изменено пользователем Mars M
Ссылка на комментарий
  • 1
В 07.05.2017 в 10:00, Mars M сказал:

Наткнулся тут на работу с OpenCL в делфи http://www.delphisources.ru/forum/showthread.php?t=28188

Это я этот пример выложил более года назад. Пример проверяет вашу конфигурацию на наличие разл. GPU (выдаёт их списком), инициализирует всё что необходимо на видео-акселераторе, создаёт массивы памяти на GPU, закачивает в них исходные данные из памяти CPU. Главное не забудьте, что рядом с файлом *.exe должны лежать текстовые файлы *.cpp (они при запуске передаются видеодрайверу на компиляцию). Если в них - в коде для GPU (Kernel, текстовом файле) на языке C99 есть ошибки - они будут показаны в "чёрном" окне. Потом выполняются в цикле несложные, но длительные операции.

Причём это делается и на GPU (с контролем времени), и на CPU: чтобы убедиться в корректности вычислений. Папка со словом Slow в названии - это пример использования Atomic-функций (например, если надо найти среднее по большому массиву данных). В своих научных программах Atomic-функции стараюсь избегать: замедляют расчёты, "фирменные" atomic работают только с целыми. Использую вместо них barrier.

Месяца 3 назад NVIDIA наконец-то начала переход со стандарта OpenCL1.2 на 2.0. Жаль, что такие интересные возможности OpenCL 2.0, как Pipes (трубы для обмена данными между модулями) NVIDIA (как и их любимая CUDA) пока не поддерживают... Только AMD даёт полноценную поддержку OpenCL 2.0 (только при размере видеопамяти более 2Gb!), а NVIDIA полностью совместима только с версией 1.2.

В общем, будут вопросы - пишите: работаю только в связке Delphi/OpenCL уже давно. Кстати, в среде RAD Studio очень удобно редактировать одновременно и код Delphi-pascal, и C-код для OpenCL.

 

=====

Дополню (конец декабря 2017). Внутри той же  ссылки для скачивания добавил папку:

OpenCL_Demo2017 Barrier and Local_Memory REDUCT


В ней новый пример под Delphi XE8 64bit (работает и при компиляции в Delphi под Win32, но с ограничениями, о которых будет сказано ниже). Отличия:

  1. Добавлен пример простейшей редукции с использованием barrier и LocalMemory с обилием комментариев внутри Kernel-файла ProgramGPU1.cpp
  2. Показано, как внутри Kernel создать а-ля динамический массив (стандарт языка OpenCL 1.2 этого не позволяет).
  3. Главное. На форме добавлены Gauge-компоненты, показывающие:

    • общую загрузку CPU ;
    • загрузку CPU данной задачей ;
    • загрузку GPU (общую);
    • загрузку контроллера памяти GPU ;
    • проценты использованной памяти GPU ;
    • температуру GPU (в текстовом виде).

Для определения загрузки GPU используется nvml.dll  (мануал 2017), так что последние 4 параметра определяются только для карт NVIDIA, и при компиляции в Delphi под 64bit. Эта динамич. библиотека для каждой карты NVIDIA - своя, обычно при установке драйвера карты она попадает в папку

C:\Program Files\NVIDIA Corporation\NVSMI\nvml.dll (этот путь прямо прописан в прилагаемом примере по ссылке).

Всё что связано с определением загрузки CPU-GPU находится в отдельном модуле ProcessorUsage.pas, который может быть применён и для других программ (без OpenCL).

  1. Если есть желание попробовать OpenCL не только на видеокартах, но и на процессорах INTEL, надо поставить драйвер
  2. Ещё раз напоминаю, что при запуске *.exe рядом с ним должны лежать два текстовых файла *.cpp - они будут отправлены на компиляцию драйверу видеокарты!

Буду весьма признателен, если кто-то подскажет способ измерения загрузки памяти GPU от AMD (загрузку GPU, его температуру, скорость FAN и т.д. уже знаю, как программно определить и для AMD тоже: использую atiadlxx.dll . Есть похожая DLL или иной способ определения свободной/использованной памяти именно для AMD?


Всех с наступающим Новым годом!!

Изменено пользователем Vladimir PRO
Добавка в текст
Ссылка на комментарий
  • 0
В 06.06.2019 в 16:53, Vladimir PRO сказал:

Обновлённая ссылка на DEMO:
http://gofile.me/2Zesj/fbsharing-C0f3wb1o
Последняя версия в папке:
OpenCL_Demo2018 Barrier and Local_Memory REDUCT Delphi Tokyo 10.2.2 !! LAST !!

Владимир огромное спасибо! Ваш код очень помог мне в одном проекте.

А есть ли путь для решения проблемы не совпадения нумерации GPU?
У меня на разных стендах абсолютно разные результаты, каждый раз создавать SlotGPU.txt с соответствиями очень не хочется.

Бывает что нумерации совсем безумные, типа

4
5
2
3
1
0

И определить их можно только нагружая один из GPU и наблюдая результат выдаваемый nvmlDeviceGetMemoryInfo

Я пытаюсь определить соответствие получая CL_DEVICE_PCI_BUS_ID_NV и CL_DEVICE_PCI_SLOT_ID_NV 

PlatformID 0 | DeviceID 0 | DeviceNum 0 | PCI Bus 5 Slot 0 | NVIDIA GeForce RTX 3070 | GPU_usage 11 % | Temperature 51 | FanSpeed 40 % | Power 41
PlatformID 0 | DeviceID 1 | DeviceNum 1 | PCI Bus 7 Slot 0 | NVIDIA GeForce RTX 3070 | GPU_usage 100 % | Temperature 76 | FanSpeed 82 % | Power 239
PlatformID 0 | DeviceID 2 | DeviceNum 2 | PCI Bus 3 Slot 0 | NVIDIA GeForce RTX 2070 SUPER | GPU_usage 100 % | Temperature 62 | FanSpeed 71 % | Power 148
PlatformID 0 | DeviceID 3 | DeviceNum 3 | PCI Bus 2 Slot 0 | NVIDIA GeForce GTX 960 | GPU_usage 100 % | Temperature 63 | FanSpeed 72 % | Power 148

Но у меня не хватает мозгов правильно импортировать функцию nvmlDeviceGetHandleByPciBusId_v2 ( const char* pciBusId, nvmlDevice_t* device )(https://docs.nvidia.com/deploy/nvml-api/group__nvmlDeviceQueries.html#group__nvmlDeviceQueries)

То ли я параметры не правильно перевожу в pascal, то ли еще что - при вызове получаю только NVML_ERROR_INVALID_ARGUMENT

Буду безмерно благодарен за помощь! )

Ссылка на комментарий
  • 0

Разобрался с помощью коллег из https://t.me/fmx_flood, спасибо kami!

Определение:

 nvmlDeviceGetHandleByPciBusId_v2 : function (const pciBusId : PAnsiChar; pHandle: p_nvmlDevice_t) :  nvmlReturn_t;  stdcall;

Импорт:

  function ProcNV(var Fun: Pointer;  const FunName: WideString) : boolean;
  begin
    Fun := nil;
    Fun := GetProcAddress(LibHandleNV, PWideChar(FunName));
    Result := Assigned(Fun);
  end;
...
  ProcNV(@nvmlDeviceGetHandleByPciBusId_v2, 'nvmlDeviceGetHandleByPciBusId_v2');

Использование:

В функцию GPUusageNVIDIA надо вместо GPU ID передавать PCI BUS ID.

PCI BUS ID получаем так

  clStatus := clGetDeviceInfo(PlatformDevices[DevN], CL_DEVICE_PCI_BUS_ID_NV, SizeOf(AValueCardinal), @AValueCardinal, @Returned_Size);
  if (clStatus = CL_SUCCESS) and (Returned_Size = 4) then
    ADevicesOpenCL[NumDevicesOpenCL].DevicePCIBusID := AValueCardinal;

Ну и получение GPU_Handle :

var
  ABusIDText : String;
...
  ABusIDText := '00000000:' + PCIBusID.ToString.PadLeft(2, '0') + ':00.0';
  AnvmlReturn := nvmlDeviceGetHandleByPciBusId_v2(PAnsiChar(AnsiString(ABusIDText)), @GPU_Handle);
  If AnvmlReturn <> 0 then
    raise EAbort.Create('');

В nvmlDeviceGetHandleByPciBusId_v2 передается pciBusId, параметр должен быть вида domain:bus:device.function, к примеру '00000000:08:00.0' 

Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить на вопрос...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...