2012-06-01 11 views
10

Czy istnieje sposób na uzyskanie OpenCL, aby uzyskać listę wszystkich unikalnych urządzeń fizycznych, które mają implementację OpenCL? Wiem, jak przejrzeć listę platform/urządzeń, ale na przykład w moim przypadku mam jedną platformę dostarczoną przez firmę Intel, która zapewnia wydajną implementację urządzenia dla mojego procesora oraz platformę APP, która zapewnia szybką implementację dla mojego GPU, ale straszna implementacja mojego procesora.Unikalność urządzenia OpenCL

Czy istnieje sposób sprawdzenia, czy te dwa urządzenia CPU są w rzeczywistości tym samym urządzeniem fizycznym, tak że mogę wybrać najbardziej wydajny i pracować z nim, zamiast używać obu tych urządzeń i mieć ze sobą rywalizację czas obliczeń na pojedynczym urządzeniu fizycznym?

Mam spojrzał na CL_DEVICE_VENDOR_ID i CL_DEVICE_NAME ale nie rozwiąże moich problemów program CL_DEVICE_NAME będzie taka sama dla dwóch oddzielnych urządzeń fizycznych tego samego modelu (dual GPU) i CL_DEVICE_VENDOR_ID daje mi inny identyfikator dla mojego procesora w zależności na platformie.

Idealnym rozwiązaniem byłby jakiś unikalny identyfikator urządzenia fizycznego, ale byłbym zadowolony z ręcznej zmiany konfiguracji OpenCL, aby samemu zmienić układ urządzeń (jeśli takie rzeczy są możliwe).

+0

Nie otrzymuję pytania .. więc chcesz wybrać pomiędzy dwoma procesorami z identycznymi specyfikacjami? – ardiyu07

+0

Chcę używać wszystkich dostępnych urządzeń fizycznych (w celu łatwego zrównoleglenia) - i chcę używać tylko jednego urządzenia logicznego przez fizyczne urządzenie, w przeciwnym razie dostanę rywalizację. – Thomas

Odpowiedz

2

O ile mogę teraz zbadać problem, nie ma niezawodnego rozwiązania. Jeśli cała twoja praca jest wykonywana w ramach jednego procesu, możesz użyć kolejności wpisów zwróconych przez same wartości (zasadniczo są to wskaźniki), ale rzeczy się pogarszają, jeśli spróbujesz udostępnić te identyfikatory między procesami.

Zobacz that guy's blog post o nim, mówiąc:

Problem jest, że jeśli masz dwa identyczne układy GPU, nie można ich odróżnić. Jeśli zadzwonisz pod numer clGetDeviceIDs, kolejność, w jakiej są one zwracane, jest w rzeczywistości nieokreślona, ​​więc jeśli pierwszy proces wybierze pierwsze urządzenie, a drugi zabierze drugie urządzenie, obaj mogą skończyć z nadpisywaniem subskrypcji tego samego GPU i pozostawieniem drugiego bezczynności.

Jednakże, zauważa, że ​​nVidia i AMD zapewniają ich rozszerzenia niestandardowe cl_amd_device_topology i cl_nv_device_attribute_query. Można sprawdzić, czy te rozszerzenia są obsługiwane przez urządzenie, a następnie wykorzystać je jako następujące (kodu przez oryginalnego autora):

// 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; 
} 

lub (kod przeze mnie, zaadaptowany z powyższym połączonego post):

#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; 
+0

"kolejność, w jakiej są one zwracane, jest w rzeczywistości nieokreślona" wow! to nawet gorsze, niż się spodziewałem. W każdym razie moje pytanie dotyczyło nie tyle wielu procesów, ale więcej różnych platform odsłaniających to samo fizyczne urządzenie (np. Intel SDK i AMD SDK, które eksponują ten sam główny procesor, co urządzenie logiczne w każdej z ich platform), ale to rozszerzenie topologii rozwiązuje to również. Dziękuję za odpowiedź! – Thomas

+0

@Thomas: Witaj! BTW, program 'clinfo' powinien wyświetlać identyfikatory topologii dla urządzeń nVidia i AMD. Zdecydowanie powinieneś [rzucić okiem] (https://github.com/Oblomov/clinfo/blob/f9516865c0a47d2e2b24eb8371f0931792a23316/src/clinfo.c#L1048) jak sobie z tym radzić, ich kod wydaje się lepszy niż mój. – firegurafiku

0

mimo to niech po prostu założyć, że próbujesz wyciągnąć unikatowy identyfikator dla wszystkich urządzeń, w rzeczywistości można po prostu zapytać o 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) 

wówczas lista urządzeniu zostanie wstawiony do * Urządzenia tablicy , a następnie możesz zrobić clGetDeviceInfo(), aby dowiedzieć się, które urządzenie chcesz użyć.

+0

Chcę używać ich wszystkich, ale nie chcę, aby dostęp do fizycznego urządzenia był możliwy przez wiele urządzeń logicznych. – Thomas

+0

Jeśli się nie mylę, chcesz robić wielowątkowe ze wszystkimi urządzeniami działającymi w tym samym czasie? jeśli tak, to możesz chcieć rzucić okiem na CUDA's Computing SDK dla OpenCL, kodu źródłowego oclMultiThreads, gdzie możesz podzielić pracę ręcznie, a następnie uruchomić je asynchronicznie z dostępnymi urządzeniami – ardiyu07

+0

Nie, moje pytanie jest bardziej subtelne. Wiem, że mogłem wymienić wszystkie urządzenia i wielowątkowe. Problem polega jednak na tym, że pojedyncze urządzenie fizyczne (na przykład mój unikalny procesor) pojawia się jako dwa urządzenia logiczne (jeden na każdej platformie OpenCL) - wielowątkowość w stosunku do dwóch urządzeń logicznych spowoduje rywalizację o zasoby z unikatowym fizycznym procesorem (jest to jeszcze więcej prawda dla GPU), więc chcę wykryć, że te dwa urządzenia logiczne wskazują to samo fizyczne urządzenie i używają tylko jednego z nich. – Thomas

2
  • Jeśli masz dwa urządzenia z dokładnie tego samego rodzaju należących do platformy, można odróżnić je od siebie przez związanego cl_device_ids zwrotu przez clGetDeviceIDs.

  • Jeśli masz urządzenia, które mogą być używane przez dwie różne platformy, możesz wyeliminować wpisy dla drugiej platformy, porównując nazwy urządzeń z CL_DEVICE_NAME.

  • Jeśli chcesz znaleźć planowaną platformę dla urządzenia, porównaj łańcuchy CL_PLATFORM_VENDOR i CL_DEVICE_VENDOR odpowiednio z clGetPlatformInfo() i clGetDeviceInfo.

Możesz czytać na wszystkich platformach i wszystkich powiązanych z nimi urządzeniach na oddzielnych listach specyficznych dla platformy, a następnie eliminować podwójne, porównując nazwy urządzeń na oddzielnych listach. To powinno zapewnić, że nie otrzymasz tego samego urządzenia dla różnych platform.

Na koniec, za pomocą argumentów wiersza poleceń lub pliku konfiguracyjnego można na przykład podać argumenty do aplikacji, aby powiązać urządzenia określonego typu (procesor, GPU, akcelerator) z określoną platformą, jeśli istnieje wybór różnych platform dla typ urządzenia. Mam nadzieję, że to odpowie na twoje pytanie.