¿Cómo se comparan CUDA y OpenCL entre sí a fines de 2013 desde la perspectiva de un programador? Mi grupo está pensando en tratar de hacer uso de la informática GPU. ¿Nos limitaríamos significativamente al elegir hardware que solo sea compatible con OpenCL pero no con CUDA?
Para ser un poco más específico, ¿son correctos los siguientes supuestos?
Todo lo que es posible en CUDA también es posible en OpenCL
Mientras no usemos bibliotecas, una tarea determinada no es significativamente más fácil (o más difícil) de realizar en ninguna de ellas
La principal ventaja de CUDA es la disponibilidad de bibliotecas.
Ambos tienen un buen soporte para las tres plataformas principales (Win / OSX / Linux)
Respuestas:
Trataré de resumir mis experiencias obtenidas en el desarrollo de ViennaCL, donde tenemos backends CUDA y OpenCL con la mayoría de las traducciones 1: 1 de muchos núcleos informáticos. A partir de su pregunta, también supondré que estamos tomando principalmente GPU aquí.
Portabilidad de rendimiento.En primer lugar, no existen los núcleos portátiles de rendimiento en el sentido de que escribes un núcleo una vez y se ejecutará de manera eficiente en cada hardware. No en OpenCL, donde es más evidente debido a la gama más amplia de hardware compatible, pero tampoco en CUDA. En CUDA es menos evidente debido a la menor gama de hardware admitido, pero incluso aquí tenemos que distinguir al menos tres arquitecturas de hardware (pre-Fermi, Fermi, Kepler). Estas fluctuaciones de rendimiento pueden resultar fácilmente en una variación de rendimiento del 20 por ciento dependiendo de cómo orquesta los hilos y qué tamaños de grupo de trabajo elige, incluso si el núcleo es tan simple como una copia de búfer. Probablemente también valga la pena mencionar que en las GPU anteriores a Fermi y Fermi era posible escribir núcleos de multiplicación matriz-matriz rápidos directamente en CUDA, mientras que para las últimas GPU Kepler parece que hay que ir al lenguaje de pseudoensamblaje PTX para acercarse al rendimiento de CUBLAS. Por lo tanto, incluso un lenguaje controlado por el proveedor como CUDA parece tener problemas para mantener el ritmo de los desarrollos de hardware. Además, todo el código CUDA se compila estáticamente cuando ejecuta nvcc, lo que requiere un acto de equilibrio a través del indicador -arch, mientras que los núcleos de OpenCL se compilan en tiempo de ejecución desde el compilador justo a tiempo, por lo que, en principio, puede adaptar los núcleos hasta los detalles de un dispositivo informático en particular. Sin embargo, este último es bastante complicado y generalmente solo se convierte en una opción muy atractiva a medida que su código madura y a medida que se acumula su experiencia. El precio a pagar es el tiempo O (1) requerido para la compilación justo a tiempo, que puede ser un problema en ciertas situaciones. OpenCL 2.
Depuración y perfilado. Las herramientas de depuración y creación de perfiles de CUDA son las mejores disponibles para GPGPU. Las herramientas de AMD tampoco son malas, pero no incluyen gemas como cuda-gdb o cuda-memcheck. Además, todavía hoy NVIDIA proporciona los controladores y SDK más robustos para GPGPU, los bloqueos del sistema debido a núcleos defectuosos son realmente la excepción, no la regla, tanto con OpenCL como con CUDA. Por razones que probablemente no necesito explicar aquí, NVIDIA ya no ofrece depuración y creación de perfiles para OpenCL con CUDA 5.0 y superior.
Accesibilidad y conveniencia. Es mucho más fácil poner en funcionamiento los primeros códigos CUDA, sobre todo porque el código CUDA se integra bastante bien con el código de host. (Discutiré el precio a pagar más adelante). Hay muchos tutoriales en la web, así como guías de optimización y algunas bibliotecas. Con OpenCL, debe pasar por un buen código de inicialización y escribir sus núcleos en cadenas, por lo que solo encontrará errores de compilación durante la ejecución al alimentar las fuentes al compilador jit. Por lo tanto, lleva más tiempo pasar por un ciclo de código / compilación / depuración con OpenCL, por lo que su productividad suele ser menor durante esta etapa de desarrollo inicial.
Aspectos de la biblioteca de software. Si bien los elementos anteriores estaban a favor de CUDA, la integración en otro software es una gran ventaja para OpenCL. Puede usar OpenCL simplemente vinculándose con la biblioteca OpenCL compartida y listo, mientras que con CUDA debe tener disponible toda la cadena de herramientas CUDA. Peor aún, debe usar los compiladores de host correctos para que nvcc funcione. Si alguna vez trató de usar, por ejemplo, CUDA 4.2 con GCC 4.6 o más reciente, tendrá dificultades para hacer que las cosas funcionen. En general, si tiene un compilador en uso que es más nuevo que el SDK de CUDA, es probable que ocurran problemas. La integración en sistemas de compilación como CMake es otra fuente de dolor de cabeza (también puede encontrar una amplia evidencia sobre, por ejemplo, el PETSclistas de correo). Esto puede no ser un problema en su propia máquina, donde tiene el control total, pero tan pronto como distribuya su código, se encontrará con situaciones en las que los usuarios están algo restringidos en su pila de software. En otras palabras, con CUDA ya no eres libre de elegir tu compilador de host favorito, pero NVIDIA dicta qué compiladores puedes usar.
Otros aspectos. CUDA está un poco más cerca del hardware (por ejemplo, warps), pero mi experiencia con el álgebra lineal es que rara vez obtienes un beneficio significativo de él. Existen algunas bibliotecas de software más para CUDA, pero cada vez más bibliotecas usan múltiples backends de cómputo. ViennaCL , VexCL o Paralution son compatibles con los backends de OpenCL y CUDA mientras tanto, se puede ver una tendencia similar con las bibliotecas en otras áreas.
GPGPU no es una bala de plata. Se ha demostrado que GPGPU proporciona un buen rendimiento para operaciones estructuradas y tareas de cómputo limitado. Sin embargo, para algoritmos con una porción no despreciable de procesamiento secuencial, GPGPU no puede superar mágicamente la Ley de Amdahl . En tales situaciones, es mejor usar una buena implementación de CPU del mejor algoritmo disponible en lugar de intentar lanzar un algoritmo paralelo pero menos adecuado a su problema. Además, PCI-Express es un serio cuello de botella, por lo que debe verificar con anticipación si los ahorros de las GPU pueden compensar la sobrecarga de mover datos de un lado a otro.
Mi recomendación. Considere CUDA y OpenCL en lugar de CUDA oOpenCL. No es necesario restringirse innecesariamente a una plataforma, sino sacar lo mejor de ambos mundos. Lo que funciona bien para mí es configurar una implementación inicial en CUDA, depurarla, perfilarla y luego transferirla a OpenCL mediante simples sustituciones de cadenas (incluso puede parametrizar sus rutinas de generación de cadenas del núcleo OpenCL para que tenga cierta flexibilidad para ajustar el hardware de destino). Este esfuerzo de transferencia usualmente consumirá menos del 10 por ciento de su tiempo, pero también le brinda la capacidad de ejecutar en otro hardware. Es posible que se sorprenda de lo bien que puede funcionar el hardware que no sea NVIDIA en ciertas situaciones. Sobre todo, considere la reutilización de la funcionalidad en las bibliotecas en la mayor medida posible. Mientras que un rápido y La reimplementación sucia de algunas funciones a menudo funciona aceptable para la ejecución de un solo subproceso en una CPU, a menudo le dará un bajo rendimiento en hardware masivamente paralelo. Idealmente, incluso puede descargar todo a las bibliotecas y nunca tener que preocuparse por si usan CUDA, OpenCL o ambos internamente. Personalmente, nunca me atrevería a escribir código bloqueado por el proveedor para algo en lo que quiero confiar en varios años a partir de ahora, pero este aspecto ideológico debería entrar en una discusión por separado.
fuente