tl; dr: desplazarse hacia abajo.
Un determinado problema podría consistir en varios subproblemas, cada uno de los cuales podría abordarse mejor mediante diferentes esquemas de paralelización. Por lo tanto, los métodos a menudo se pueden combinar. Tenga esto en mente cuando lea lo siguiente.
GPGPU
Una GPGPU es un procesador vectorial. Eso significa que si eres capaz de vectorizar el problema, Cuda u OpenCL probablemente pueden darte una alta velocidad. Aquí hay un ejemplo ridículamente simple en pseudocódigo:
- ¿Cuáles son los últimos desarrollos en computadoras?
- ¿Puede la programación en objetivos ser una alternativa a la definición de API (de la charla de B. Victor 'El futuro de la programación)?
- ¿Cuáles son algunas cosas no técnicas que uno debe saber al comenzar a hacer un doctorado en bases de datos o sistemas distribuidos?
- ¿Qué campo de investigación en Ciencias de la Computación puede perseguir un graduado que no sea CS que trabaje en TI?
- ¿Sobre qué temas puede investigar un estudiante de informática?
matriz = [1, 2, 3, 4, .... 1000] para i en [0, 1, 2, ... 999]: matriz [i] = matriz [i] ^ 2 + 2
Claramente, la matriz ya está vectorizada, y esperaríamos que una clase de GPU pudiera entender esto:
array = piecewise_gpu_array ([1, 2, 3, 4, .... 1000]) matriz = matriz ^ 2 + 2
Si puede reescribir su código en esta forma vectorial, entonces GPGPU es el camino a seguir.
Una GPGPU está diseñada para manejar muchas operaciones numéricas simples de una sola vez. Dentro de un bucle, solo se realiza una operación a la vez. En una GPGPU, si el problema es vectorizable, puede distribuir todos los cálculos a su propia unidad de procesamiento individual. Estos realizarán los cálculos en paralelo.
En general, si puede poner su problema en forma de vector, es muy recomendable utilizar este método. Puede esperar aceleraciones locas. La G en GPU, como sabes, significa Gráfico . Buenos ejemplos de problemas de vectores son los algoritmos de trazado de rayos o enjambres de partículas, que se utilizan en la mayoría de los juegos de computadora modernos.
Para problemas simples, debería ser capaz de acelerar en cientos o incluso miles.
Un inconveniente de GPGPU es la transferencia de datos entre la CPU y la GPGPU. Esto es increíblemente lento, y podría ser una razón para no usar este enfoque. Sin embargo, si los cálculos toman mucho más tiempo que la transferencia, entonces está bien.
Como comentario: por supuesto, su GPGPU no necesariamente tiene tantas unidades de procesamiento como el tamaño de su problema, pero es un enfoque estándar para programar como si tuviera una cantidad infinita de procesadores.
Multiprocesamiento (memoria compartida)
El multiprocesamiento es probablemente el esquema de paralelización más simple que existe. Casi siempre se puede usar, pero no se escala a grandes grupos.
Tomando prestada alguna notación C ++ OpenMP, podemos paralelizar el programa desde arriba escribiendo algo ala (todavía pseudo código, por supuesto)
matriz = [1, 2, 3, 4, .... 1000] #pragma omp paralelo para para i en [0, 1, 2, ... 999]: matriz [i] = matriz [i] ^ 2 + 2
El bucle for se extiende sobre los núcleos de CPU que tenemos disponibles.
El multiprocesamiento es excelente y fácil de usar. El inconveniente está escalando. Rara vez se ve el multiprocesamiento utilizado para más de 64 núcleos debido a problemas de uso compartido de memoria.
Entonces, ¿cuándo desea usarlo? Cuando todo lo que necesita es una aceleración máxima del número de núcleos que tiene disponibles en una sola computadora .
Esta no es una técnica utilizada para redes de computadoras. Sin embargo, combinado con una técnica de red puede resultar realmente útil. Puede usar un esquema diferente para dividir el problema entre las computadoras y luego multiprocesamiento para dividir aún más entre los núcleos dentro de las computadoras.
Interfaz de paso de mensajes
Use esto cuando nada más sea suficiente. MPI es extremadamente escalable. Los grupos más grandes del mundo (con más de un millón de núcleos) usan MPI para la paralelización. El inconveniente es que requiere más tiempo para programar. La mayoría de los problemas paralelizables serán paralelizables por MPI. Entonces, las únicas preocupaciones son: ¿es fácil (suficiente) de hacer? ¿Realmente necesito esta aceleración? ¿Es mi clúster lo suficientemente grande como para que esto tenga sentido?
De nuevo, veamos el ejemplo de arriba.
si procesador == 0 matriz = [1, 2, 3, 4, .... 1000] para i en [0, 1, 2, ... 999]: envío sin bloqueo (matriz [i], procesador = i) mensaje = bloqueo_recibir (procesador = 0) envío sin bloqueo (mensaje ^ 2 + 2, procesador = 0) si procesador == 0 para i en [0, 1, 2, ... 999]: array [i] = block_receive (procesador = i)
(Esto es muy, muy pseudo-codificación. ¡Es solo para mantener el ejemplo simple! También supongo que tenemos al menos 1000 procesadores)
Con MPI tiene control total sobre qué CPU hace qué, y tiene control total sobre, por ejemplo, la ocultación de latencia. Con todo, MPI es impresionante, pero mucho más trabajo.
TL; DR
Use GPGPU si puede vectorizar el problema y la transferencia de datos a la GPU lleva menos tiempo que realizar el cálculo en sí.
Utilice el multiprocesamiento si solo necesita acelerar la cantidad de núcleos que tiene en su computadora. No utilizar para redes de computadoras.
MPI siempre se puede usar, pero es mucho más trabajo. Se escala a tantas computadoras como quieras.