Empuje para la programación de GPU

10

Soy muy nuevo en la programación GPGPU, así que perdónenme si la pregunta no es particularmente apropiada. Por lo que entiendo, la programación de GPU es un trabajo de ingeniería muy complejo en comparación con la programación habitual de CPU. Hay que tener mucho cuidado con los problemas de divergencia, el mosaico, la asignación de memoria anclada y la superposición de la comunicación / dispositivo del dispositivo host.

Después de investigar un poco, encontré la biblioteca de empuje que parece intentar imitar C ++ STL. Esto es muy lindo Sin embargo, en base a mi experiencia muy limitada y al haber visto toda la microgestión necesaria para obtener un buen rendimiento, soy un poco escéptico sobre el rendimiento. ¿Puede empujar eficientemente manejar internamente toda la parte intrincada de programación? Algunas bibliotecas muy conocidas, como PETSc, parecen usar este paquete, lo que me hace creer que de alguna manera debería hacerlo.

Me preguntaba si las personas con más experiencia en CUDA y empuje podrían decir una o dos palabras sobre el rendimiento del paquete en comparación con la programación de bajo nivel de CUDA. ¿Cuándo puedo usar el empuje y cuándo debo volver a cambiar a CUDA?

GradGuy
fuente
¿Has considerado ArrayFire?
arrayfire

Respuestas:

2

No tengo experiencia personal con empuje, pero sí uso ViennaCL, que es otra biblioteca de GPU de alto nivel que oculta casi todos los detalles. Desde mi propia evaluación comparativa personal puedo ver aceleraciones de 2x - 40x en el cálculo real si ignoras el tiempo que lleva mover la memoria.

Cuando debe usar la CPU vs. empuje vs. CUDA todo depende del problema que esté resolviendo, su habilidad y el tiempo que tenga disponible. Recomendaría comenzar resolviendo problemas simples con los 3 métodos para ver su rendimiento relativo. Luego, puede escribir su software real de manera rápida, compararlo y aplicar el método de gpu apropiado en las áreas que necesitan acelerar, en lugar de perder su tiempo escribiendo software CUDA que solo le dará un par de minutos de tiempo de ejecución .

Vidente de Godric
fuente
Eso tiene mucho sentido para mí. Uno siempre tiene que perfilarse primero. Entonces, en su ejemplo, la aceleración que obtuvo fue al usar ViennaCL. ¿Has probado OpenCL directo para comprobar la diferencia?
GradGuy
No, como tú, soy nuevo en la informática de GPU. Planeo para el próximo año o dos expandir lentamente mis habilidades para incluir CUDA y OpenCL, pero actualmente solo uso la biblioteca. La documentación de ViennaCL afirma que sería posible acelerar aún más con una implementación de openCL sintonizada que probablemente sería del orden de otros 2x-10x, sin embargo, he aprendido que el ancho de banda de la memoria es el gorila de 900 libras en la sala que realmente define su rendimiento.
Godric Seer
5

He usado Thrust en mi proyecto de expansión de clúster vinculado. Dependiendo de la situación, Thrust puede funcionar tan bien o mejor que una implementación de bajo nivel que usted implementa (en particular, el reducekernel ha funcionado bastante bien para mí). Sin embargo, la naturaleza y flexibilidad genéricas de Thrust significa que a veces tiene que hacer muchas copias adicionales, relleno de matriz, etc., lo que puede ralentizarlo un poco en algunos casos extremos desagradables. La última vez que lo usé sortfue bastante lento en comparación con otras bibliotecas como b40c o mgpu. Sin embargo, NVIDIA ha estado trabajando para mejorar el rendimiento algorítmico de Thrust, por lo que puede ser un problema menor en el futuro.

Debería intentar escribir su código usando Thrust y CUDA y luego usar el Visual Profiler para determinar cuál es mejor para la tarea específica que le interesa. Si es probable que la transferencia de memoria tome más tiempo de ejecución de su programa y usted no No quiero tener que preocuparme por optimizar sus propios núcleos para conflictos bancarios, recuento de instrucciones, etc., entonces usaría Thrust. También tiene el beneficio adicional de hacer que su código sea mucho menos detallado y más fácil de leer para las personas que no están familiarizadas con la programación de GPU.

limas
fuente
3

El objetivo del impulso (como la mayoría de las bibliotecas de plantillas) es proporcionar una abstracción de alto nivel, al tiempo que se conserva un rendimiento bueno o incluso excelente.

Sugeriría no preocuparse demasiado por el rendimiento, sino preguntarse si

  • su aplicación puede describirse en términos de los algoritmos implementados en empuje, y si

  • le gusta la posibilidad de escribir código paralelo "genérico", sin la necesidad de entrar en los detalles sangrientos de encontrar una asignación eficiente a la arquitectura de hardware / software dada.

Si responde positivamente a ambas preguntas, debería poder implementar su programa con menos esfuerzo con respecto a una implementación solo de CUDA. Luego puede perfilar su aplicación y decidir si vale la pena intentar mejorar el rendimiento.

Dicho esto, tengo que confesar que no me gusta la programación "genérica", porque estoy dispuesto a aprender algo nuevo cuando escribo un programa. Seguiría otra ruta: escribir una implementación de prototipo en python + numpy + scipy, luego agregar kernels CUDA para ese 1% - 2% del código que realmente necesita optimización y es adecuado para ejecutarse en una GPU. Por supuesto, al hacerlo, necesita algún tipo de pre-ciencia, ya que una decisión incorrecta en la fase de creación de prototipos (por ejemplo, una estructura de datos inadecuada para los núcleos CUDA) puede tener resultados terribles en el rendimiento. Por lo general, se necesitan más iteraciones para obtener un buen código y no hay garantía de hacerlo mejor que el empuje.

Stefano M
fuente