Уникалност на OpenCL устройството

Има ли начин да накарам OpenCL да ми даде списък с всички уникални физически устройства, които имат налична реализация на OpenCL? Знам как да преминавам през списъка с платформа/устройство, но например в моя случай имам една предоставена от Intel платформа, която ми дава ефективна реализация на устройство за моя CPU, и платформата APP, която осигурява бърза реализация за моя GPU, но ужасно изпълнение за моя процесор.

Има ли начин да разбера, че двете CPU устройства всъщност са едно и също физическо устройство, така че да мога да избера най-ефективното и да работя с него, вместо да използвам и двете и да ги карам да се борят едно с друго за изчислително време на едно физическо устройство?

Разгледах CL_DEVICE_VENDOR_ID и CL_DEVICE_NAME, но те не решават проблемите ми, CL_DEVICE_NAME ще бъде един и същ за две отделни физически устройства от един и същ модел (двоен графичен процесор), а CL_DEVICE_VENDOR_ID ми дава различен идентификатор за моя процесор в зависимост от платформата.

Идеалното решение би било някакъв уникален идентификатор на физическо устройство, но бих се радвал да променя ръчно конфигурацията на OpenCL, за да пренаредя сам устройствата (ако такова нещо е възможно).


person Thomas    schedule 01.06.2012    source източник
comment
не разбирам въпроса.. значи искате да изберете между два процесора с еднакви спецификации?   -  person ardiyu07    schedule 02.06.2012
comment
Искам да използвам всички налични физически устройства (за лесно успоредим проблем) - и искам да използвам само едно логическо устройство по физическо устройство, в противен случай получавам конкуренция.   -  person Thomas    schedule 02.06.2012


Отговори (4)


Доколкото мога да проуча проблема сега, няма надеждно решение. Ако цялата ви работа се извършва в рамките на един процес, можете да използвате реда на записите, върнати от самите clGetDeviceIDs или cl_device стойности (по същество те са указатели), но нещата се влошават, ако се опитате да споделите тези идентификатори между процесите.

Вижте публикацията в блога на този човек за това, която казва:

Проблемът е, че ако имате два идентични графични процесора, не можете да ги разграничите. Ако извикате clGetDeviceIDs, редът, в който те се връщат, всъщност е неуточнен, така че ако първият процес избере първото устройство, а вторият вземе второто устройство, и двата може да преувеличат абонамента за същия графичен процесор и да оставят другия неактивен.

Той обаче отбелязва, че nVidia и AMD предоставят своите персонализирани разширения, cl_amd_device_topology и cl_nv_device_attribute_query. Можете да проверите дали тези разширения се поддържат от вашето устройство и след това да ги използвате по следния начин (кодът е от оригиналния автор):

// This cl_ext is provided as part of the AMD APP SDK
#include <CL/cl_ext.h>

cl_device_topology_amd topology;
status = clGetDeviceInfo (devices[i], CL_DEVICE_TOPOLOGY_AMD,
    sizeof(cl_device_topology_amd), &topology, NULL);

if(status != CL_SUCCESS) {
    // Handle error
}

if (topology.raw.type == CL_DEVICE_TOPOLOGY_TYPE_PCIE_AMD) {
    std::cout << "INFO: Topology: " << "PCI[ B#" << (int)topology.pcie.bus
        << ", D#" << (int)topology.pcie.device << ", F#"
        << (int)topology.pcie.function << " ]" << std::endl;
}

или (код от мен, адаптиран от свързаната по-горе публикация):

#define CL_DEVICE_PCI_BUS_ID_NV  0x4008
#define CL_DEVICE_PCI_SLOT_ID_NV 0x4009

cl_int bus_id;
cl_int slot_id;

status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
    sizeof(cl_int), &bus_id, NULL);
if (status != CL_SUCCESS) {
    // Handle error.
}

status = clGetDeviceInfo (devices[i], CL_DEVICE_PCI_BUS_ID_NV,
    sizeof(cl_int), &slot_id, NULL);
if (status != CL_SUCCESS) {
    // Handle error.
}

std::cout << "Topology = [" << bus_id <<
                         ":"<< slot_id << "]" << std::endl;
person firegurafiku    schedule 15.03.2016
comment
редът, в който се връщат, всъщност е неопределен уау! това е дори по-лошо, отколкото очаквах. Във всеки случай въпросът ми не беше толкова за множество процеси, а повече за различни платформи, излагащи едно и също физическо устройство (напр. intel SDK и AMD SDK, и двата излагащи един и същ основен процесор като логическо устройство във всяка от съответните им платформи), но това разширение на топология разрешава и това. Благодаря за отговора! - person Thomas; 16.03.2016
comment
@Thomas: Няма за какво! Между другото, програмата clinfo трябва да показва топологични идентификатори както за nVidia, така и за AMD устройства. Определено трябва да разгледате как се справят с това, техният код изглежда е по-добър от моя. - person firegurafiku; 16.03.2016

  • Ако имате две устройства от абсолютно същия вид, принадлежащи към платформа, можете да ги различите по свързаните cl_device_ids, върнати от clGetDeviceIDs.

  • Ако имате устройства, които могат да се използват от две различни платформи, можете да премахнете записите за втората платформа, като сравните имената на устройствата от CL_DEVICE_NAME.

  • Ако искате да намерите желаната платформа за дадено устройство, сравнете низовете CL_PLATFORM_VENDOR и CL_DEVICE_VENDOR съответно от clGetPlatformInfo() и clGetDeviceInfo.

Можете да четете във всички платформи и всички свързани с тях устройства в отделни списъци, специфични за платформата, и след това да елиминирате двойките, като сравнявате имената на устройствата в отделните списъци. Това трябва да гарантира, че няма да получите едно и също устройство за различни платформи.

Накрая можете, например чрез аргументи на командния ред или конфигурационен файл, да дадете аргументи на вашето приложение, за да асоциирате устройства от определен тип (CPU, GPU, Accelerator) с конкретна платформа, ако има избор от различни платформи за тип устройство. Надяваме се, че това ще отговори на въпроса ви.

person Steinin    schedule 07.11.2013

както и да е, нека просто приемем, че се опитвате да изтеглите уникалния идентификатор за всички устройства, всъщност можете просто да направите заявка с clGetDeviceIDs:

cl_int clGetDeviceIDs(cl_platform_id platform,
                      cl_device_type device_type,
                      cl_uint num_entries,
                      cl_device_id *devices,
                      cl_uint *num_devices)

тогава вашият списък с устройства ще бъде вмъкнат в масива *devices и след това можете да направите clGetDeviceInfo(), за да разберете кое устройство искате да използвате.

person ardiyu07    schedule 02.06.2012
comment
Искам да използвам всички тях, но не искам всяко физическо устройство да бъде достъпно от множество логически устройства. - person Thomas; 02.06.2012
comment
Ако не разбирам погрешно, искате ли да направите многопотоци с всички устройства, работещи едновременно? ако е така, тогава може да искате да разгледате Computing SDK на CUDA за OpenCL, изходния код на oclMultiThreads, където можете да разделите работата ръчно и след това да ги стартирате асинхронно с наличните устройства - person ardiyu07; 02.06.2012
comment
Не, въпросът ми е по-фин от това. Знам, че мога да изброя всички устройства и да ги направя многонишково. Но проблемът е, че едно физическо устройство (да речем, моят уникален CPU) се появява като две логически устройства (по едно във всяка OpenCL платформа) - многонишковостта на двете логически устройства ще доведе до конкуренция за ресурси за уникалния физически CPU (това е дори повече вярно за GPU), така че искам да открия, че двете логически устройства сочат към едно и също физическо устройство и използват само едно от тях. - person Thomas; 02.06.2012
comment
Виждам, че най-накрая разбрах въпроса ви. Не знам как сте разделили устройството си и сте им казали да изпълняват една и съща програма opencl, но има и начин да разделите устройството на подустройства с разширение OpenCL и можете да погледнете описанието тук: khronos.org/registry/cl/extensions/ext/ . Мисля, че поддържа Intel и AMD, но не гарантирам, че е съвместим с вашата среда. - person ardiyu07; 02.06.2012

Комбинирайки отговорите по-горе, моето решение беше:

long bus = 0; // leave it 0 for Intel
// update bus for NVIDIA/AMD ...
// ...
long uid = (bus << 5) | device_type;

Променлива bus беше изчислена според специфични за NVIDIA/AMD устройства информационни заявки, както беше споменато firegurafiku, променлива device_type беше резултат от clGetDeviceInfo(clDevice, CL_DEVICE_TYPE, sizeof(cl_device_type), &device_type, nullptr) извикване на API , както предложи Steinin.

Подобен подход реши проблема с еднакъв уникален идентификатор за Intel CPU с интегриран GPU. Сега и двете устройства имат уникални идентификатори, благодарение на различните CL_DEVICE_TYPE.

Изненадващо, в случай на изпълнение на код на Oclgrind-емулирано устройство, Oclgrind simulator устройството също получава уникален идентификатор 15, различен от всеки друг в моята система.

Единственият случай, когато предложеният подход може да се провали - няколко процесора от един и същи модел на една дънна платка.

person Mykyta Kozlov    schedule 30.04.2019