Modernización de lenguajes de programación para un mundo paralelo - Calendae | Informática, Electrónica, CMS, Ciberseguridad

Modernización de lenguajes de programación para un mundo paralelo

Hola, un placer verte por aquí. Yo soy Simón Sánchez y hoy hablaremos sobre Modernización de lenguajes de programación para un mundo paralelo

Los lenguajes de programación de computadoras más utilizados en la actualidad no fueron diseñados como lenguajes de programación paralelos. Pero la adaptación de los lenguajes de programación existentes para la programación paralela está en marcha. Podemos comparar y contrastar las modificaciones al examinar cuatro características clave, cinco cualidades clave y varios enfoques de implementación.

En este artículo, me centro en las características y cualidades, dejando los furiosos debates sobre los mejores enfoques (lenguaje vs biblioteca vs directivas y abstracto y portátil vs bajo nivel con muchos controles) para otro día para otro día.

Cuatro características que necesitamos

Capacidades que cualquier solución de programación paralela, incluidas las actualizaciones, debe incluir un modelo de memoria definido, sincronización, actividad y paralelismo de datos.

Modelo de memoria

Definir cómo los cambios en los datos compartidos son observables a partir de diferentes tareas ha sido un problema subestimado. Hans-J. Boehm escribió un informe en 2004, titulado Los subprocesos no se pueden implementar como una biblioteca, lo que explica estos problemas. Tener un orden bien definido entre los accesos a distintas variables y permitir la independencia de las actualizaciones para distintas variables es tan importante que se han abordado en Java, C11 y C ++ 11. Sin estas actualizaciones, cada programa paralelo está en un arruinado.

Sincronización

La necesidad de una sincronización portátil y eficiente es sustancial. Actualice sus bibliotecas, Intel Subprocesamiento de bloques de construcción (TBB) e OpenMP ofrecen soluciones ampliamente utilizadas. C ++ 11 y C11 ahora ofrecen soporte. Además de estos, el concepto de transacción es un tema que vale la pena explorar en un artículo futuro. La actualización de sincronización ayuda a la portabilidad. Quedan importantes oportunidades para ayudar a la eficiencia.

Actividades, no hilos

La programación debe ser un ejercicio de escritura de tareas que puedan ejecutarse simultáneamente, sin que el programador especifique la asignación precisa de tareas a los subprocesos de hardware. Una introducción a este desafío es El problema con los hilos por Edward A. Lee.

El mapeo debe ser el trabajo de herramientas, incluidos los programadores de tiempo de ejecución, no la programación explícita. Esta filosofía está bien respaldada por actualizaciones como OpenMP, TBB, Cilk Plus, Microsoft Biblioteca de modelos paralelos (PPL) y Apple Despacho de Grand Central (GCD). La necesidad de afirmar cierto control sobre el mapeo entre las tareas y los subprocesos para maximizar el rendimiento todavía está presente cuando se utilizan estos sistemas en la actualidad, pero no siempre es compatible.

Sin embargo, programar directamente en subprocesos nativos (por ejemplo, pthreads) en aplicaciones es algo que debe evitarse por completo. Hoy en día, las modificaciones son suficientes para que los activos sean el método de elección.

Soporte de datos paralelos

Debería ser razonablemente fácil escribir un programa portátil que aproveche el hardware de datos en paralelo. Idealmente, el portador de datos paralelo debería poder utilizar la funcionalidad de actividad y vector paralelo sin que un programador tenga que codificar explícitamente la división entre los dos.

Desafortunadamente, ninguna solución de este tipo se usa ampliamente hoy en día, incluso para la vectorización solamente. La auto-paralelización efectiva depende en gran medida de compiladores altamente optimizados. Código de bloque intrínseco del compilador en un ancho de vector particular (MMX = 64, SSE = 128, AVX = 256, etc.). Las funciones elementales en CUDA, OpenCL y Cilk Plus ofrecen un vistazo a las posibles modificaciones. Intel propone adoptar los beneficios de la vectorización de las notaciones de matriz Fortran 90 en C y C ++ como parte del proyecto Cilk Plus.

El hardware vectorial es cada vez más importante en procesadores, GPU y coprocesadores. OpenCL y OpenMP luchan hoy sobre cómo adoptar el hardware de datos en paralelo y qué tan estrechamente la programación estará ligada a él. Microsoft C ++ AMP tiene desafíos similares en lo que respecta al mercado con el próximo Microsoft Visual Studio. ¡Buscaban soluciones estándar, abstractas, portátiles y efectivas!

Cinco cualidades que deberíamos querer

Las cinco cualidades clave que son deseables para la programación paralela incluyen componibilidad, razonamiento secuencial, minimización de la comunicación, portabilidad del rendimiento y seguridad.

Todas estas cualidades son inalcanzables, en un sentido absoluto, ya sea como adaptación a un idioma antiguo o con borrón y cuenta nueva y un nuevo idioma. Por eso no podemos llamarlas funciones. Cuantas más de estas cualidades obtengamos, mejores seremos. Esto hace que sea muy importante tenerlos en cuenta.

Modularidad

La capacidad de composición es un concepto bien conocido en programación, que ofrece reglas para combinar diferentes cosas (funciones, objetos, módulos, etc.) para que sea fácil de componer (piense: combinar de formas inesperadas). Es importante pensar en la modularidad en términos de corrección y rendimiento.

OpenCL, principalmente porque es menos abstracto, tiene poca capacidad de composición en ambas cuentas. OpenMP y OpenCL tienen una capacidad de composición de rendimiento muy seria a menos que se utilicen con mucho cuidado. Las modificaciones nuevas y abstractas (TBB, Cilk, PPL, GCD) son mucho más tolerantes y pueden proporcionar una alta capacidad de composición.

La auto-modularidad es un primer paso esencial, pero la capacidad de componer múltiples adaptaciones juntas también es esencial a largo plazo. Concurrency Runtime de Microsoft, una solución bienvenida para los proveedores de herramientas, ha permitido que las modificaciones de varios proveedores coexistan con una mayor capacidad de composición. La programación en paralelo sin la capacidad de mezclar y combinar libremente es indeseable y contraproducente.

La modularidad merece más atención de la que recibe.

Razonamiento secuencial

El razonamiento secuencial, la norma para leer una implementación en serie, se puede aplicar con un programa paralelo expresado adecuadamente. OpenMP usa sugerencias para crear el uso de paralelismo en lugar de cambios de código. Esto permite que la intención de un programa permanezca evidente en el código. TBB y PPL enfatizan la semántica secuencial relajada para proporcionar paralelismo como acelerador sin que sea obligatorio para la corrección. Se permite y se anima a escribir un programa de forma coherente y secuencial.

Un objetivo explícito de Cilk Plus es ofrecer semántica secuencial para distinguirlo de otras modificaciones. La elisión en serie (o C elisión) de un programa Cilk se promociona en los documentos del MIT. Se elogió la programación que conserva la semántica secuencial por ser más fácil de aprender y usar. Las funciones elementales en OpenCL, CUDA y Cilk Plus tienen objetivos similares.

Es justo decir que programar de una manera que requiera comprender la semántica paralela para comprender la intención es impopular y desactualizado en la actualidad. Este paralelismo obligatorio es más difícil de comprender y depurar.

El razonamiento secuencial también se puede extender a los depuradores. Un área interesante para observar aquí son los depuradores que trabajan para presentar una experiencia de depuración más como experiencias secuenciales, con características como las capacidades de reproducción de Rogue Wave en el depurador de Totalview.

En lugar de considerar el razonamiento secuencial como una modificación, es más preciso pensar en el razonamiento secuencial como a menudo se busca y se conserva intencionalmente en un mundo paralelo.

Minimización de la comunicación

La optimización del rendimiento en sistemas paralelos a menudo se centra en garantizar que los datos sean locales cuando se utilizan y en minimizar la necesidad de moverlos. El movimiento de datos significa comunicación de algún tipo, y la comunicación es generalmente cara. Las decisiones en el diseño y la implementación de actualizaciones, así como la programación de la aplicación en sí, a menudo tienen un impacto significativo en el rendimiento. Los algoritmos de recuperación de actividad de TBB, Cilk, PPL y GCD tienen muy presente la reutilización de caché en sus proyectos. Las modificaciones para ayudar, con la minimización de la comunicación, son un negocio complicado y pueden necesitar más atención.

Portabilidad del rendimiento

El objetivo aquí es que un programa ajustado a una pieza de hardware funcione razonablemente bien en otra pieza de hardware. Es deseable poder describir los datos y las actividades de tal manera que el rendimiento se escala a medida que aumenta el paralelismo (número de núcleos o tamaño de vector o tamaño de caché, etc.). Nada es completamente portátil desde el rendimiento, pero las modificaciones más abstractas tienden a resistir mejor.

Desafortunadamente, las implementaciones de abstracción pueden tener dificultades para ofrecer el máximo rendimiento. Los compiladores tardaron años en ofrecer un rendimiento MMX o SSE competitivo con programación en lenguaje ensamblador. El uso de algoritmos independientes de la memoria caché generalmente aumenta la portabilidad del rendimiento. Hoy en día, competir por el rendimiento con código CUDA y OpenCL cuidadosamente elaborado puede ser difícil porque la codificación es lo suficientemente baja como para fomentar, o incluso requerir, que la estructura del programa coincida con el hardware. A menudo se demuestra la falta de portabilidad del rendimiento de dicho código, pero se siguen desarrollando alternativas eficaces. El diseño del lenguaje, las opciones de algoritmos y el estilo de programación pueden tener un gran impacto en la portabilidad del rendimiento.

La seguridad

La ausencia de puntos muertos y las condiciones de carrera puede ser lo más difícil de proporcionar mediante una actualización. Ningún método para agregar seguridad completa a C o C ++ ha ganado gran popularidad. La seguridad no se incorporó fácilmente a los lenguajes no gestionados, a pesar de algunos valientes esfuerzos para hacerlo.

Para que un idioma sea seguro, los indicadores deben eliminarse o restringirse severamente. Mientras tanto, las herramientas están madurando para ayudarnos a lidiar con la seguridad a pesar de la falta de soporte lingüístico directo, y un estilo de codificación más seguro y adaptaciones más seguras también parecen ayudar. Quizás la seguridad provenga de una combinación de «suficientemente bueno» y «podemos hacerlo usando las herramientas».

Un viaje hacia adelante, juntos

Hay al menos cuatro problemas clave de programación que cualquier solución de programación paralela debe abordar, y cinco cualidades clave que pueden hacer que un modelo de programación, retroadaptado o no, sea más deseable. La evolución del hardware también ayudará.

—–

Acerca de

James Reinders ha ayudado a desarrollar supercomputadoras, microprocesadores y herramientas de software durante 25 años. Es ingeniero senior de Intel en Hillsboro, Oregon.

Puedes compartir en una historia de tu Instagram para que tus amigos lo disfruten

??? ? ? ???

Comparte