Execution model: Difference between revisions

Content deleted Content added
Bluelinking 1 books for verifiability.) #IABot (v2.1alpha3
Rescuing 1 sources and tagging 0 as dead.) #IABot (v2.0.9.5
 
(24 intermediate revisions by 13 users not shown)
Line 1:
{{short description|Behavioral rules for all elements of a programming language}}
{{Program execution}}
 
AIn [[computing]], a [[programming language]] consists of a grammar/[[Syntax (programming languages)|syntax]] plus an '''execution model'''. The execution model specifies the behavior of elements of the language. By applying itthe execution model, one can derive the behavior of a [[Computer program|program]] that was written in terms of that programming language. For example, [[Operational_semantics| Operational Semantics]] is one method of specifyingwhen a language'sprogrammer execution"reads" model.code, Thein observedtheir behaviormind, ofthey awalk running program must match the behavior derived from the execution model. An execution model covers things such asthrough what is an indivisibleeach unitline of work,code anddoes. what areIn theeffect constraintsthey onsimulate the orderbehavior ininside whichtheir those units of work take placemind. For example,What the additionprogrammer is operationdoing is anapplying indivisiblethe unitexecution ofmodel workto inthe many languagescode, andwhich results in sequentialthe languages such unitsbehavior of work are constrained to take place one after the othercode.
 
Each and every programming language has an execution model, which determines the manner in which the units of work (that are indicated by program [[Syntax (programming languages)|syntax]]) are [[Scheduling (computing)|scheduled]] for [[Execution (computing)|execution]]. Detailed examples of the specification of execution models of a few popular languages include those of [[Python (programming language)|Python]],<ref>
In particular, the [[C (programming language)|C programming language]], has a concept called a statement. The language specification defines a statement as a chunk of syntax that is terminated by a ";". The language spec then says that execution of the program proceeds statement by statement, which tells us something about the execution model of the language. It tells us that statements are indivisible units of work and that they proceed in the same order as their syntactic appearance in the code (except when a control statement such as IF or WHILE modifies the order). By stating the order in which statements are executed, the language spec has stated constraints on the order of performing units of work. The C language actually has an additional level to its execution model, which is the order of precedence. It states the rules for the order of operations within a single statement. The order of precedence can be viewed as stating the constraints on performing the units of work that are within a single statement. So, ";" and "IF" and "WHILE" cover constraints on the order of statements, while order of precedence covers constraints on work within a statement. Hence, these parts of the C language specification are stating the execution model of the C language.
 
Execution models can also exist independently from programming languages, examples of which would be the [[POSIX Threads]] library, and Hadoop's Map-Reduce [[programming model]]. The implementation of an execution model can be via [[compiler]], or [[Interpreter_(computing)|interpreter]], and often includes a [[runtime system]].
 
An implementation of an execution model controls the order in which work takes place during execution. This order may be chosen ahead of time, in some situations, or it can be dynamically determined as the execution proceeds. Most execution models allow varying degrees of both. For example, the C language fixes the order of work within a statement and it fixes the order of all statements, except ones that involve an IF statement or a form of loop statement. Hence, most of the order of execution may be chosen statically, before execution begins, but a small portion must be chosen dynamically, as execution proceeds.
 
The static choices are most often implemented inside a [[compiler]], in which case the order of work is represented by the order in which instructions are placed into the executable binary. The dynamic choices would then be implemented inside the language's [[runtime system]]. The runtime system may be a library, which is called by instructions inserted by the [[compiler]], or the runtime system may be embedded into the [[executable]] directly, such as by inserting branch instructions, which make dynamic choices about which work to perform next.
 
However, an [[Interpreter_(computing)|interpreter]] may also be constructed for any language, in which case all decisions on order of execution are dynamic. An [[Interpreter_(computing)|interpreter]] can be viewed as being part translator, and part execution model implementation.
 
Each and every programming language has an execution model, which determines the manner in which the units of work (that are indicated by program [[Syntax (programming languages)|syntax]]) are [[Scheduling (computing)|scheduled]] for [[Execution (computing)|execution]]. Detailed examples of the specification of execution models of a few popular languages include those of Python,<ref>
{{cite web
| url=https://docs.python.org/3/reference/executionmodel.html
| title=Python Documentation: Execution Model
}}</ref>
the execution model of the [[Unified Parallel C]] (UPC) programming language,
<ref>{{cite web
| url=http://upc.lbl.gov/lang-overview.shtml
| title=UPC Language Features
}}</ref>
a discussion of various classes of execution model such as for [[Imperative programming|imperative]] versus [[Functional programming|functional languages]],<ref>
{{cite webbook
| url=https://books.google.com/books?id=4xwWNCiF9CgC&pg=PA61&lpg=PA61&dqq=C+language+execution+model&sourcepg=bl&ots=pjBT99RWMQ&sig=bEKw6hgDsG9l4yqxiGyEEdFlWQI&hl=en&sa=X&ei=pElcVa-NNsbZsAWrs4DwDw&ved=0CFcQ6AEwCA#v=onepage&q=C%20language%20execution%20model&f=falsePA61
| title=Programming Languages and Execution Models
| author1=Cardoso, J.M.P.
Line 33 ⟶ 24:
| publisher=Springer US
}}</ref>
and an article discussing execution models for [[Real-time computing|real-time embedded]] languages.<ref>{{cite journal
{{cite web
| url=http://pertsserver.cs.uiuc.edu/~mcaccamo/papers/PREM_rtas11.pdf
| title=A Predictable Execution Model for COTS-based Embedded Systems
Line 45 ⟶ 35:
| author6=CACCAMO, M.
| author7=KEGLEY, R
| lastname-authorlist-ampstyle=yesamp
| publisher=IEEE
| journal=Real-Time and Embedded Technology and Applications Symposium
| access-date=2015-05-20
| format=PDF
| archive-date=2017-08-12
}}</ref>
| archive-url=https://web.archive.org/web/20170812100818/http://pertsserver.cs.uiuc.edu/~mcaccamo/papers/PREM_rtas11.pdf
| url-status=dead
}}</ref>
 
== Details of an execution model ==
 
[[Operational_semantics| Operational Semantics]] is one method of specifying a language's execution model. The observed behavior of a running program must match the behavior derived from the operational semantics (which define the execution model of the language).
 
An execution model covers things such as what is an indivisible unit of work, and what are the constraints on the order in which those units of work may take place. For example, the addition operation is an indivisible unit of work in many languages, and in sequential languages such units of work are constrained to take place one after the other.
 
AsTo aillustrate simple example of a basic execution modelthis, that ofconsider the [[C (programming language)|C programming language]], isas described in the book by Kernighan and Richie.<ref name="k&r1e">{{cite book | last=Kernighan | first=Brian W. | authorlink=Brian Kernighan | author2=Dennis M. Ritchie | title=The C Programming Language | edition=1st | publisher=[[Prentice Hall]] | date=February 1978 | ___location=[[Englewood Cliffs, NJ]] | isbn=0-13-110163-3 | authorlink2=Dennis M. Ritchie | url-access=registration | url=https://archive.org/details/cprogramminglang00kern }}</ref> The book describes that work takes places in units called statements, which are syntactically indicated by a terminating ";". It specifies that statements are completed serially (one at a time) and sequentially (a previous statement completes before the next statement begins). Details such as this are part of the execution model.
C has a concept called a statement. The language specification defines a statement as a chunk of syntax that is terminated by a ";". The language spec then says that "execution of the program proceeds one statement after the other, in sequence". Those words: "execution of the program proceeds one statement after the other, in sequence" are one piece of the execution model of C. Those words tell us that statements are indivisible units of work and that they proceed in the same order as their syntactic appearance in the code (except when a control statement such as IF or FOR modifies the order). By stating that "execution of the program proceeds one statement after the other, in sequence", the programming model has stated constraints on the order of performing units of work.
 
In particular, the [[C (programming language)|C programming language]], has a concept called a statement. The language specification defines a statement as a chunk of syntax that is terminated by a ";". The language spec then says that execution of the program proceeds statement by statement, which tells us something about the execution model of the language. It tells us that statements are indivisible units of work and that they proceed in the same order as their syntactic appearance in the code (except when a control statement such as IF or WHILE modifies the order). By stating the order in which statements are executed, the language spec has stated constraints on the order of performing units of work. The C language actually has an additional level to its execution model, which is the order of precedence. It Order of precedence states the rules for the order of operations within a single statement. The order of precedence can be viewed as stating the constraints on performing the units of work that are within a single statement. So, ";" and "IF" and "WHILE" cover constraints on the order of statements, while order of precedence covers constraints on work within a statement. Hence, these parts of the C language specification are statingalso part of the execution model of the C language.
 
Execution models can also exist independently from programming languages, examples of which would be the [[POSIX Threads]] library, and Hadoop's Map-Reduce [[programming model]]. The implementation of an execution model can be via [[compiler]], or [[Interpreter_(computing)|interpreter]], and often includes a [[runtime system]].
 
An implementation of an execution model controls the order in which work takes place during execution. This order may be chosen ahead of time, in some situations, or it can be dynamically determined as the execution proceeds. Most execution models allow varying degrees of both. For example, the C language fixes the order of work within a statement and it fixes the order of all statements, except ones that involve an IF statement or a form of loop statement. Hence, most of the order of execution may be chosen statically, before execution begins, but a small portion must be chosen dynamically, as execution proceeds.
 
The static choices are most often implemented inside a [[compiler]], in which case the order of work is represented by the order in which instructions are placed into the executable binary. The dynamic choices would then be implemented inside the language's [[runtime system]]. The runtime system may be a library, which is called by instructions inserted by the [[compiler]], or the runtime system may be embedded into the [[executable]] directly, such as by inserting branch instructions, which make dynamic choices about which work to perform next.
 
However, an [[Interpreter_(computing)|interpreter]] may also be constructed for any language, in which case all decisions on order of execution are dynamic. An [[Interpreter_(computing)|interpreter]] can be viewed as being part translator, and part execution model implementation.
 
== Assembly language execution model versus implementation by micro-architectures ==
 
Assembly languages also have execution models, the same as any other language. Such an execution model is implemented by a CPU micro-architecture. For example, both a 5 stage in-order pipeline and a large out of order CPU implement the same assembly language execution model. The execution model is the definition of the behavior, so all implementations, whether in-order or out-of-order or interpreted or JIT'd etc.. must all give the exact same result, and that result is defined by the execution model.
 
== Parallel Execution Models ==
In the modern age, parallel programming is an increasingly important topic. Parallel execution models tend to be complex because they involve multiple timelines. Parallel execution models necessarily include the behavior of [[Synchronization_construct| synchronization constructs]]. A synchronization construct has the effect of establishing an ordering between activities in one timeline relative to activities in another timeline.
 
For example, a common synchronization construct is the lock. Consider one timeline. The timeline has a point at which it executes the "gain ownership of the lock" synchronization construct. In Posix threads this would be pthread_mutex_lock(&myMutex). In Java this would be lock.lock(). In both cases, the timeline is called a thread. The C and Java execution models are sequential, and they state that the timeline has activities that come before the call to "gain ownership of the lock", and activities that come after the call. Likewise there is a "give up ownership of the lock" operation. In C this would be pthread_mutex_unlock(&myMutex). In Java this would be lock.unlock(). Again, the execution models C and Java define that one group of statements is executed before ownership of the lock is given up, and another group of statements is executed after ownership of the lock is given up.
 
Now, consider the case of two timelines, also known as two threads. One thread, call it thread A, executes some statements, call them A-pre-gain-lock statements. Then thread A executes "gain ownership of the lock", then thread A executes A-post-gain-lock statements, which come after A gains ownership of the lock. Finally, thread A performs "give up ownership of the lock". Then thread A performs A-post-giveup-lock statements.
 
A second thread, call it thread B, executes some statements, call them B-pre-lock statements. Then thread B executes "gain ownership of the lock", then thread B executes B-post-lock statements, which come after B gains ownership of the lock.
 
Now, we can say the parallel execution model of the "gain ownership of lock" and "give up ownership of lock" synchronization construct. The execution model is this:
 
"In the case that ownership of the lock goes from thread A to thread B, A-post-gain-lock statements come before B-post-gain-lock statements."
 
The complication comes from the fact that the execution model does not have any means for the execution of "give up ownership of the lock" to have any influence over which execution of "gain ownership of the lock" in some other timeline (thread) follows. Very often, only certain handoffs give valid results. Thus, the programmer must think of all possible combinations of one thread giving up a lock and another thread getting it next, and make sure their code only allows valid combinations.
 
The only effect is that A-post-gain-lock statements come before B-post-gain-lock statements. No other effect happens, and no other relative ordering can be relied upon. Specifically, A-post-give-up-lock and B-post-gain-lock have ''no relative ordering'' defined, which surprises many people. But thread A may have been swapped out after giving up ownership, so A-post-give-up-lock statements may happen long after many B-post-gain-lock statements have finished. That is one of the possibilities that must be thought about when designing locks, and illustrates why multi-threaded programming is difficult.
== Overview ==
As a simple example of a basic execution model, that of the [[C (programming language)|C language]] is described in the book by Kernighan and Richie.<ref name="k&r1e">{{cite book | last=Kernighan | first=Brian W. | authorlink=Brian Kernighan | author2=Dennis M. Ritchie | title=The C Programming Language | edition=1st | publisher=[[Prentice Hall]] | date=February 1978 | ___location=[[Englewood Cliffs, NJ]] | isbn=0-13-110163-3 | authorlink2=Dennis M. Ritchie | url-access=registration | url=https://archive.org/details/cprogramminglang00kern }}</ref> The book describes that work takes places in units called statements, which are syntactically indicated by a terminating ";". It specifies that statements are completed serially (one at a time) and sequentially (a previous statement completes before the next statement begins). Details such as this are part of the execution model.
 
Modern parallel languages have much easier to use execution models. The thread model was one of the original parallel execution models, which may account for why it has persisted despite being difficult to use.
In the modern age, parallel programming is an increasingly important topic. Parallel execution models (several at a time) are much more complex. For example, the [[C++11]] standard includes sizeable wording that deals with the parallel execution model of the language.
 
== See also ==