2012-06-01 13 views
10

¿Hay alguna forma de que OpenCL me proporcione una lista de todos los dispositivos físicos únicos que tienen una implementación OpenCL disponible? Sé cómo iterar a través de la plataforma/lista de dispositivos pero, por ejemplo, en mi caso, tengo una plataforma provista por Intel que me da una implementación eficiente de dispositivos para mi CPU, y la plataforma APP que proporciona una implementación rápida para mi GPU pero una terrible implementación para mi CPU.Exclusividad del dispositivo OpenCL

Hay una forma de averiguar que los dos dispositivos de la CPU son de hecho el mismo dispositivo físico, de modo que pueda elegir el más eficiente y trabajar con eso, en lugar de usar ambos y hacer que compitan entre sí por calcular el tiempo en el único dispositivo físico?

He mirado CL_DEVICE_VENDOR_ID y CL_DEVICE_NAME pero no solucionan mis problemas, la CL_DEVICE_NAME será el mismo para los dos dispositivos físicos separados del mismo modelo (GPU dual) y CL_DEVICE_VENDOR_ID me da un ID diferente para mi CPU dependiendo en la plataforma.

Una solución ideal sería algún tipo de ID de dispositivo físico único, pero estaría encantado de alterar manualmente la configuración de OpenCL para reorganizar los dispositivos yo mismo (si eso es posible).

+0

no entiendo la pregunta .. por lo que desea elegir entre dos CPU con las mismas especificaciones? – ardiyu07

+0

Quiero usar todos los dispositivos físicos disponibles (para un problema fácilmente paralelizable), y solo quiero usar un único dispositivo lógico por dispositivo físico, de lo contrario, tendré conflictos. – Thomas

Respuesta

2

Por lo que pude investigar el problema ahora, no hay una solución confiable. Si todo su trabajo se realiza en un solo proceso, puede usar el orden de las entradas devueltas por los valores clGetDeviceIDs o cl_device (básicamente son punteros), pero las cosas empeoran si intenta compartir esos identificadores entre los procesos.

Ver that guy's blog post al respecto, diciendo:

La cuestión es que si usted tiene dos GPU idénticos, no se puede distinguir entre ellos. Si llama clGetDeviceIDs, el orden en que se devuelven es en realidad no especificada, por lo que si el primer proceso recoge el primer dispositivo y el segundo toma el segundo dispositivo, que tanto puede terminar la suscripción por exceso el mismo GPU y dejando el otro inactivo.

Sin embargo, señala que Nvidia y AMD proporcionan sus extensiones personalizadas, cl_amd_device_topology y cl_nv_device_attribute_query. Es posible comprobar si estas extensiones son compatibles con su dispositivo, y luego usarlos como las siguientes (el código por el autor original):

// 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 (código por mí, adaptado del poste vinculado anteriormente):

#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

"el orden en el que se devuelven no está especificado" wow! eso es incluso peor de lo que esperaba. De todos modos, mi pregunta no era tanto sobre procesos múltiples sino sobre diferentes plataformas que exponen el mismo dispositivo físico (por ejemplo, el SDK de Intel y el SDK de AMD exponiendo la misma CPU principal como un dispositivo lógico en cada una de sus respectivas plataformas) pero esta extensión de topología lo resuelve también. ¡Gracias por la respuesta! – Thomas

+0

@Thomas: ¡eres bienvenido! Por cierto, el programa 'clinfo' debe mostrar identificadores de topología para los dispositivos nVidia y AMD. Definitivamente debe [echarle un vistazo] (https://github.com/Oblomov/clinfo/blob/f9516865c0a47d2e2b24eb8371f0931792a23316/src/clinfo.c#L1048) cómo lo manejan, su código parece ser mejor que el mío. – firegurafiku

0

todos modos vamos a suponer que usted está tratando de tirar de la identificación única para todos los dispositivos, en realidad simplemente puede consultar 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) 

continuación, se insertará su lista de equipos a los dispositivos serie * , y luego puede hacer clGetDeviceInfo() para averiguar qué dispositivo le gustaría usar.

+0

Quiero usar todos ellos, pero no quiero que ningún dispositivo físico sea accedido por múltiples dispositivos lógicos. – Thomas

+0

Si no me estoy equivocando, ¿quieres hacer multielaborados con todos los dispositivos funcionando al mismo tiempo? si es así, es posible que quieras echar un vistazo a Computing SDK de CUDA para OpenCL, el código fuente oclMultiThreads, donde se puede dividir el trabajo manual y luego ejecutarlos de forma asíncrona con los dispositivos disponibles – ardiyu07

+0

No, mi pregunta es más sutil que eso. Sé que podría hacer una lista de todos los dispositivos y multiprocesarlos. Pero el problema es que un único dispositivo físico (por ejemplo, mi única CPU) aparece como dos dispositivos lógicos (uno en cada plataforma OpenCL): el multihilo sobre los dos dispositivos lógicos causará la contención de recursos sobre la única CPU física (esto es aún más cierto para GPU) así que quiero detectar que los dos dispositivos lógicos apuntan al mismo dispositivo físico y solo usan uno de ellos. – Thomas

2
  • Si tiene dos dispositivos de la misma especie que pertenece a una plataforma, puede distinguirlos por el retorno cl_device_ids asociado por clGetDeviceIDs.

  • Si tiene dispositivos que pueden ser utilizados por dos plataformas diferentes, puede eliminar las entradas de la segunda plataforma comparando los nombres de dispositivo de CL_DEVICE_NAME.

  • Si desea encontrar la plataforma prevista para un dispositivo, compare las cadenas CL_PLATFORM_VENDOR y CL_DEVICE_VENDOR de clGetPlatformInfo() y clGetDeviceInfo, respectivamente.

se puede leer en todas las plataformas y todos sus dispositivos asociados en listas específicas de la plataforma por separado y luego eliminar los dobles comparando los nombres de los dispositivos en las listas separadas. Esto debería garantizar que no obtenga el mismo dispositivo para diferentes plataformas.

Finalmente, puede, por argumentos de línea de comando o archivo de configuración, dar argumentos a su aplicación para asociar dispositivos de un cierto tipo (CPU, GPU, Acelerador) con una plataforma específica si existe una opción de diferentes plataformas para un tipo de dispositivo. Espero que esto responda tu pregunta.