Articulo de referencia

Modelo de ejecución

En informática , un lenguaje de programación consta de una sintaxis y un modelo de ejecución . El modelo de ejecución especifica el comportamiento de los elementos del lenguaje....

En informática , un lenguaje de programación consta de una sintaxis y un modelo de ejecución . El modelo de ejecución especifica el comportamiento de los elementos del lenguaje. Al aplicar el modelo de ejecución, se puede deducir el comportamiento de un programa escrito en dicho lenguaje. Por ejemplo, cuando un programador "lee" código, mentalmente analiza la función de cada línea. En efecto, simula el comportamiento en su mente. Lo que hace el programador es aplicar el modelo de ejecución al código, lo que da como resultado el comportamiento del mismo.

Cada lenguaje de programación tiene un modelo de ejecución, que determina la forma en que se programan las unidades de trabajo (indicadas por la sintaxis del programa) para su ejecución . Ejemplos detallados de la especificación de modelos de ejecución de algunos lenguajes populares incluyen los de Python , [ 1 ] el modelo de ejecución del lenguaje de programación Unified Parallel C (UPC), [ 2 ] una discusión sobre varias clases de modelos de ejecución, como para lenguajes imperativos frente a lenguajes funcionales , [ 3 ] y un artículo que analiza los modelos de ejecución para lenguajes embebidos en tiempo real . [ 4 ]

Detalles de un modelo de ejecución

La semántica operacional es un método para especificar el modelo de ejecución de un lenguaje. El comportamiento observado de un programa en ejecución debe coincidir con el comportamiento derivado de la semántica operacional (que define el modelo de ejecución del lenguaje).

Un modelo de ejecución abarca aspectos como qué constituye una unidad de trabajo indivisible y cuáles son las restricciones sobre el orden en que pueden realizarse dichas unidades. Por ejemplo, la operación de suma es una unidad de trabajo indivisible en muchos lenguajes, y en los lenguajes secuenciales, dichas unidades de trabajo deben ejecutarse una tras otra.

Para ilustrar esto, consideremos el lenguaje de programación C , tal como se describe en el libro de Kernighan y Richie. [ 5 ] C tiene un concepto llamado instrucción. La especificación del lenguaje define una instrucción como un bloque de sintaxis que termina con un punto y coma (;). La especificación del lenguaje luego dice que "la ejecución del programa procede una instrucción tras otra, en secuencia". Estas palabras: "la ejecución del programa procede una instrucción tras otra, en secuencia" son una parte del modelo de ejecución de C. Estas palabras nos dicen que las instrucciones son unidades de trabajo indivisibles y que proceden en el mismo orden que su aparición sintáctica en el código (excepto cuando una instrucción de control como IF o FOR modifica el orden). Al afirmar que "la ejecución del programa procede una instrucción tras otra, en secuencia", el modelo de programación ha establecido restricciones sobre el orden en que se realizan las unidades de trabajo.

El lenguaje C cuenta con un nivel adicional en su modelo de ejecución: el orden de precedencia. Este orden establece las reglas para la secuencia de operaciones dentro de una misma instrucción. El orden de precedencia puede interpretarse como las restricciones para la ejecución de las unidades de trabajo dentro de una instrucción. Así, los operadores ";", "IF" y "WHILE" establecen restricciones sobre el orden de las instrucciones, mientras que el orden de precedencia establece restricciones sobre el trabajo dentro de una instrucción. Por lo tanto, estas partes de la especificación del lenguaje C también forman parte de su modelo de ejecución.

Los modelos de ejecución también pueden existir independientemente de los lenguajes de programación; ejemplos de ello son la biblioteca POSIX Threads y el modelo de programación Map-Reduce de Hadoop . La implementación de un modelo de ejecución puede realizarse mediante un compilador o un intérprete , y a menudo incluye un sistema de tiempo de ejecución .

La implementación de un modelo de ejecución controla el orden en que se realizan las tareas durante la ejecución. Este orden puede elegirse de antemano, en algunos casos, o determinarse dinámicamente a medida que avanza la ejecución. La mayoría de los modelos de ejecución permiten diferentes grados de ambas opciones. Por ejemplo, el lenguaje C fija el orden de las tareas dentro de una instrucción y el orden de todas las instrucciones, excepto aquellas que incluyen una instrucción IF o un bucle. Por lo tanto, la mayor parte del orden de ejecución puede elegirse de forma estática, antes de que comience la ejecución, pero una pequeña parte debe elegirse dinámicamente a medida que avanza la ejecución.

Las decisiones estáticas se implementan con mayor frecuencia dentro de un compilador , en cuyo caso el orden de ejecución viene representado por el orden en que las instrucciones se insertan en el binario ejecutable. Las decisiones dinámicas se implementan entonces dentro del sistema de ejecución del lenguaje . El sistema de ejecución puede ser una biblioteca, a la que llaman las instrucciones insertadas por el compilador , o puede estar integrado directamente en el ejecutable , por ejemplo, insertando instrucciones de salto, que toman decisiones dinámicas sobre qué trabajo realizar a continuación.

Sin embargo, también se puede construir un intérprete para cualquier idioma, en cuyo caso todas las decisiones sobre el orden de ejecución son dinámicas. Un intérprete puede considerarse en parte traductor y en parte implementación de un modelo de ejecución.

Modelo de ejecución en lenguaje ensamblador frente a implementación mediante microarquitecturas

Los lenguajes ensamblador también tienen modelos de ejecución, al igual que cualquier otro lenguaje. Dicho modelo de ejecución es implementado por una microarquitectura de CPU. Por ejemplo, tanto una arquitectura de procesamiento en orden de 5 etapas como una CPU de procesamiento fuera de orden implementan el mismo modelo de ejecución de lenguaje ensamblador. El modelo de ejecución define el comportamiento, por lo que todas las implementaciones, ya sean en orden, fuera de orden, interpretadas o compiladas en tiempo real (JIT), etc., deben producir exactamente el mismo resultado, y ese resultado está definido por el modelo de ejecución.

Modelos de ejecución paralela

En la actualidad, la programación paralela es un tema cada vez más importante. Los modelos de ejecución paralela suelen ser complejos debido a que involucran múltiples líneas de tiempo. Estos modelos necesariamente incluyen el comportamiento de las estructuras de sincronización . Una estructura de sincronización establece un orden entre las actividades de una línea de tiempo con respecto a las de otra.

Por ejemplo, una construcción de sincronización común es el bloqueo. Consideremos una línea de tiempo. La línea de tiempo tiene un punto en el que ejecuta la construcción de sincronización "obtener la propiedad del bloqueo". En los hilos POSIX, esto sería pthread_mutex_lock(&myMutex). En Java, esto sería lock.lock(). En ambos casos, la línea de tiempo se llama hilo. Los modelos de ejecución de C y Java son secuenciales, y establecen que la línea de tiempo tiene actividades que vienen antes de la llamada para "obtener la propiedad del bloqueo", y actividades que vienen después de la llamada. De igual manera, hay una operación de "ceder la propiedad del bloqueo". En C, esto sería pthread_mutex_unlock(&myMutex). En Java, esto sería lock.unlock(). Nuevamente, los modelos de ejecución de C y Java definen que un grupo de instrucciones se ejecuta antes de que se ceda la propiedad del bloqueo, y otro grupo de instrucciones se ejecuta después de que se ceda la propiedad del bloqueo.

Ahora, consideremos el caso de dos líneas de tiempo, también conocidas como dos hilos. Un hilo, llamémoslo hilo A, ejecuta algunas instrucciones, llamémoslas A-pre-gain-lockinstrucciones. Luego, el hilo A ejecuta "obtener la propiedad del bloqueo", luego el hilo A ejecuta instrucciones A-post-obtener-bloqueo, que vienen después de que A obtiene la propiedad del bloqueo. Finalmente, el hilo A realiza "ceder la propiedad del bloqueo". Luego, el hilo A realiza A-post-giveup-lockinstrucciones.

Un segundo hilo, llamémoslo hilo B, ejecuta algunas instrucciones, llamémoslas B-pre-lockinstrucciones. Luego, el hilo B ejecuta "obtener la propiedad del bloqueo", y luego el hilo B ejecuta las instrucciones B-post-lock, que se ejecutan después de que B obtiene la propiedad del bloqueo.

Ahora bien, podemos hablar del modelo de ejecución paralela de la construcción de sincronización "obtener la propiedad del bloqueo" y "ceder la propiedad del bloqueo". El modelo de ejecución es el siguiente:

"En caso de que la propiedad del candado pase del hilo A al hilo B, A-post-gain-locklas declaraciones preceden a B-post-gain-locklas declaraciones."

La complicación radica en que el modelo de ejecución no permite que la operación de "ceder el bloqueo" influya en la ejecución posterior de "adquirir el bloqueo" en otro hilo. Con frecuencia, solo ciertas transferencias dan resultados válidos. Por lo tanto, el programador debe considerar todas las combinaciones posibles en las que un hilo cede un bloqueo y otro lo adquiere, y asegurarse de que su código solo permita combinaciones válidas.

El único efecto es que A-post-gain-locklas instrucciones preceden a B-post-gain-locklas instrucciones. No se produce ningún otro efecto, ni se puede confiar en ningún otro orden relativo. En concreto, A-post-give-up-locky no B-post-gain-locktienen un orden relativo definido, lo que sorprende a muchos. Pero el hilo A puede haber sido reemplazado tras ceder la propiedad, por lo que A-post-give-up-locklas instrucciones pueden ejecutarse mucho después de que muchas B-post-gain-lockotras hayan finalizado. Esta es una de las posibilidades que deben tenerse en cuenta al diseñar bloqueos, y demuestra por qué la programación multihilo es compleja.

Los lenguajes paralelos modernos cuentan con modelos de ejecución mucho más fáciles de usar. El modelo de hilos fue uno de los modelos de ejecución paralela originales, lo que podría explicar su persistencia a pesar de su dificultad de uso.

Véase también

Referencias

  1. "Documentación de Python: Modelo de ejecución" .
  2. "Características lingüísticas de la UPC" .
  3. Cardoso, JMP; Diniz, PC (2011). Lenguajes de programación y modelos de ejecución . Springer US. ISBN 9780387096711.
  4. PELLIZZONI, R.; BETTI, E.; BAK, S.; YAO, G.; CRISWELL, J.; CACCAMO, M. y KEGLEY, R (2011). "Un modelo de ejecución predecible para sistemas embebidos basados ​​en COTS" (PDF) . Simposio sobre tecnología y aplicaciones en tiempo real y sistemas embebidos . IEEE. Archivado del original (PDF) el 12 de agosto de 2017. Consultado el 20 de mayo de 2015 .
  5. Kernighan, Brian W.; Dennis M. Ritchie (febrero de 1978). El lenguaje de programación C (1.ª ed.). Englewood Cliffs, NJ : Prentice Hall . ISBN  0-13-110163-3.