2011-12-25 18 views
9

Los gráficos son uno de esos problemas "embarazosamente paralelos". Se supone que Haskell es realmente, realmente bueno para el procesamiento paralelo. Así que mi pregunta es:Procesamiento de gráficos paralelos en Haskell

  1. ¿Cuál es la mejor manera de tirar tantos núcleos de CPU como sea posible a un problema de representación?

  2. ¿Es posible hacer que la GPU realice la tarea?

Por "renderizado problema", me refiero a problemas tales como:

  • color de cada píxel es una pura función de sus coordenadas.

  • Comenzamos con una imagen de "entrada" existente, y cada color de "salida" del píxel es una función pura del píxel de entrada correspondiente, o tal vez un pequeño vecindario de dichos píxeles.


Respecto # 1: Esto parece que es trivial, pero en realidad no lo es. Hay varias opciones posibles de estructura de datos para almacenar los píxeles calculados (lo que influye en cómo puede acceder a él, y con qué facilidad puede volcar el resultado en un disco o pantalla). Hay varias formas de ejecutar en múltiples núcleos. Y así.

Me parece que Data Parallel Haskell sería una opción ideal para este tipo de cosas. Sin embargo, la última vez que revisé, DPH aún no funciona. Entonces eso es eso Incluso suponiendo que funcionó, es de suponer que crearía una matriz paralela para contener los píxeles, y luego tendría que copiar los píxeles para mostrarlos en la pantalla o escribirlos en el disco.

Intentaré encender cada píxel, pero probablemente sea demasiado refinado. Podría hacer que los píxeles sean una lista y usar una de las estrategias de listas paralelas. ¿O podría convertirlo en una matriz inmutable (¿sin caja?) Y escribir un código manual para iniciar las chispas. O podría ir con hilos explícitos y matrices mutables. O podría hacer que un grupo de subprocesos de trabajo transmitan valores de píxel a través de un canal a un hilo maestro que coloque los resultados en el lugar correcto. O ...

En resumen, hay un sorprendente número de posibilidades aquí, y no estoy seguro de cuál es la mejor.


Respecto # 2: Es evidente que este tipo de problema es la única razón de que existen GPU en el primer lugar. Claramente, la GPU es ideal para atacar este tipo de problemas. Mi pregunta es más "¿es difícil hacerlo de Haskell?"

+1

No creo que pueda apuntar a GPU todavía, pero el objetivo de Data Parallel Haskell es poder hacer este tipo de cosas. –

Respuesta

7

Si eres capaz de mezclar idiomas, entonces OpenCL es muy versátil. Aunque el lenguaje OpenCL está muy cerca de ser C (así que definitivamente no Haskell), puede escribir el código de su kernel en un estilo más o menos funcional y pensar en ello como mapear ese núcleo en coordenadas espaciales. Una ventaja de hacer las cosas con un marco de programación paralelo común como OpenCL es que puede apoyarse en el creciente volumen de conocimiento que HPC y la gente de gráficos acumularon a través de los años en muchos dominios de aplicaciones. La reorientación entre la CPU y la GPU es indolora, pero deberá tener en cuenta las consideraciones sobre los tipos de datos (por ejemplo, algunas GPU no son compatibles con la precisión doble).

Escribí a tutorial on calling into OpenCL from Haskell. Se basa en los enlaces relativamente nuevos OpenCL (hay varios enlaces OpenCL en hackage, no puedo dar fe de su calidad relativa).

+0

Supongo que realmente estaba haciendo dos preguntas aquí: cómo usar de manera eficiente la CPU y cómo usar la GPU de manera eficiente. La entrada de blog vinculada hace un trabajo bastante decente de explicar cómo usar la GPU, ya sea con OpenCL o OpenGL. Estoy aceptando esto como una respuesta a toda la pregunta. – MathematicalOrchid

5

Hay raw OpenCL bindings, pero si quieres algo que ayuda a ejecutar código de alto nivel - pliegues y las cremalleras y los mapas y así sucesivamente - en la GPU de hoy, echar un vistazo a accelerate (CUDA back-end) y GPipe (OpenGL backend , para el trabajo de gráficos, un poco bitrotten hoy en día, por desgracia).

En cuanto a estructuras para representar una imagen renderizada, una matriz sin caja es probablemente la mejor opción: es la más adecuada para el hardware, y generalmente no se realizan actualizaciones "incrementales" en una representación.

2

La respuesta corta a la pregunta 1, en ausencia de más detalle, es:

  1. escribir el código de forma normal, usando una biblioteca de vector o matriz de procesamiento.

  2. Si la biblioteca aún no lo hace por usted, inserte las llamadas par 'apropiadas' o los combinadores basados ​​en él para generar cómputos en múltiples CPU.

+2

Observe el uso de Repa para sus vectores: es fácil hacer que las operaciones de Repa usen N CPU. –

Cuestiones relacionadas