2012-06-01 21 views
10

C'è un modo per ottenere OpenCL per fornirmi un elenco di tutti i dispositivi fisici univoci che dispongono di un'implementazione OpenCL? So come scorrere l'elenco di piattaforme/dispositivi, ma per esempio, nel mio caso, ho una piattaforma fornita da Intel che mi fornisce un'efficiente implementazione della periferica per la mia CPU e la piattaforma APP che fornisce un'implementazione rapida per la mia GPU ma un'implementazione terribile per la mia CPU.Unicità dispositivo OpenCL

C'è un modo per capire che i due dispositivi CPU sono in effetti lo stesso dispositivo fisico, così posso scegliere quello più efficiente e lavorare con quello, invece di usarli entrambi e farli contendere tra loro per calcolare il tempo sul singolo dispositivo fisico?

ho guardato CL_DEVICE_VENDOR_ID e CL_DEVICE_NAME ma non risolvere i miei problemi, la CL_DEVICE_NAME sarà lo stesso per i due dispositivi fisici separati dello stesso modello (dual GPU) e CL_DEVICE_VENDOR_ID mi dà un ID diverso per la mia CPU a seconda sulla piattaforma.

Una soluzione ideale sarebbe una sorta di ID dispositivo fisico univoco, ma sarei felice di alterare manualmente la configurazione di OpenCL per riorganizzare i dispositivi da solo (se tale cosa è possibile).

+0

Non capisco la domanda .. quindi si desidera scegliere tra due CPU con le specifiche identiche? – ardiyu07

+0

Voglio usare tutti i dispositivi fisici disponibili (per un problema facilmente parallelizzabile) - e voglio usare solo un singolo dispositivo logico per dispositivo fisico altrimenti ho contesa. – Thomas

risposta

2

Per quanto ho potuto analizzare il problema ora, non esiste una soluzione affidabile. Se tutto il lavoro è svolto all'interno di un singolo processo, è possibile utilizzare l'ordine delle voci restituite dai valori clGetDeviceIDs o cl_device (essenzialmente sono puntatori), ma le cose peggiorano se si tenta di condividere quegli identificatori tra i processi.

Vedi that guy's blog post su di esso, dicendo:

Il problema è che se si dispone di due GPU identici, non è possibile distinguere tra di loro. Se si chiama clGetDeviceIDs, l'ordine in cui vengono restituiti è in realtà non specificato, quindi se il primo processo preleva il primo dispositivo e il secondo prende il secondo dispositivo, entrambi possono finire in oversubscribing della stessa GPU e lasciare l'altro inattivo.

Tuttavia, egli osserva che nVidia e AMD forniscono le loro estensioni personalizzate, cl_amd_device_topology e cl_nv_device_attribute_query. Si può verificare se queste estensioni sono supportati dal dispositivo, e poi usarli come il seguente (il codice per autore originale):

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

o (codice da me, adattato dal post sopra linkato):

#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

"l'ordine in cui vengono restituiti in realtà non è specificato" wow! è anche peggio di quanto mi aspettassi. In ogni caso la mia domanda non riguardava tanto i processi multipli, quanto piuttosto le diverse piattaforme che esponevano lo stesso dispositivo fisico (ad esempio l'Intel SDK e l'AMD SDK che espongono la stessa CPU principale di un dispositivo logico in ciascuna delle rispettive piattaforme) ma questa estensione di topologia risolve anche quello. Grazie per la risposta! – Thomas

+0

@Thomas: siete i benvenuti! BTW, il programma 'clinfo' dovrebbe visualizzare gli identificatori di topologia per entrambi i dispositivi nVidia e AMD. Dovresti assolutamente [dare un'occhiata] (https://github.com/Oblomov/clinfo/blob/f9516865c0a47d2e2b24eb8371f0931792a23316/src/clinfo.c#L1048) come si comportano con esso, il loro codice sembra essere migliore del mio. – firegurafiku

0

comunque facciamo solo supporre che si sta tentando di tirare l'ID univoco per tutti i dispositivi, in realtà si può semplicemente interrogare con 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) 

poi verrà inserito nell'elenco delle dispositivo al * dispositivi di matrice e quindi puoi fare clGetDeviceInfo() per scoprire quale dispositivo desideri utilizzare.

+0

Voglio usarli tutti ma non voglio che nessun dispositivo fisico sia accessibile da più dispositivi logici. – Thomas

+0

Se non mi sto sbagliando, vuoi fare multithread con tutti i dispositivi in ​​esecuzione contemporaneamente? se è così allora potresti voler dare un'occhiata all'SDK Computing di CUDA per OpenCL, il codice sorgente oclMultiThreads, dove puoi dividere il lavoro manualmente e poi eseguirli in modo asincrono con i dispositivi disponibili – ardiyu07

+0

No, la mia domanda è più sottile di quella. So che potrei elencare tutti i dispositivi e multithread li. Ma il problema è che un singolo dispositivo fisico (ad esempio, la mia CPU unica) si presenta come due dispositivi logici (uno in ogni piattaforma OpenCL) - il multithreading sui due dispositivi logici causerà conflitto di risorse sulla CPU fisica univoca (questo è ancora di più vero per GPU), quindi voglio rilevare che i due dispositivi logici puntano allo stesso dispositivo fisico e ne usano solo uno. – Thomas

2
  • Se si dispone di due dispositivi della stessa identica facente parte di una piattaforma, è possibile distinguerli dal ritorno cl_device_ids associato da clGetDeviceIDs.

  • Se si dispone di dispositivi che possono essere utilizzati da due piattaforme diverse, è possibile eliminare le voci per la seconda piattaforma confrontando i nomi dei dispositivi da CL_DEVICE_NAME.

  • Se si desidera trovare la piattaforma prevista per un dispositivo, confrontare le stringhe CL_PLATFORM_VENDOR e CL_DEVICE_VENDOR rispettivamente da clGetPlatformInfo() e clGetDeviceInfo.

Si può leggere in tutte le piattaforme e tutti i loro dispositivi associati in liste specifiche della piattaforma separati e poi eliminare le doppie confrontando i nomi dei dispositivi nelle liste separate. Questo dovrebbe garantire che non si ottiene lo stesso dispositivo per piattaforme diverse.

Infine, è possibile, ad esempio, con argomenti della riga di comando o file di configurazione, fornire argomenti all'applicazione per associare dispositivi di un determinato tipo (CPU, GPU, Acceleratore) a una piattaforma specifica se esiste una scelta di piattaforme diverse per un tipo di dispositivo. Spero che questo risponda alla tua domanda.