Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

There is one point that BrowserUk keeps insisting on that everyone else in this thread (as far as I can tell) has the opposite conclusion. So let's discuss just that one point: Does a defined or undefined evaluation order allow or prevent the compiler from introducing implicit parallelization?

If I write $x = f() + g(); and the order of evaluation is defined, let's say from left to right, then f() must be called before g(). If the evaluation order is undefined, then f() could be called first or g() could be called first or f() and g() could be called in parallel.

So, undefined evaluation order allows the compiler to perform operations in parallel (because the programmer can indicate that f() and g() can be done in any order by putting them into the same expression, inside of which evaluation order is not restricted by a definition).

If EO is defined, then f() and g() can't be optimized to be called in parallel unless the compiler can fully analyze f() and g() and determine that they have no effect on each other. This is a fundamentally difficult problem and so, in the general case, this analysis cannot be done. So defined EO prevents the compiler from automatically adding parallelization (or other optimizations made possible by changing the order in which steps are performed).

With undefined EO, if f() and g() should not be called in parallel, then the program instead writes $x= f(); $x += g();. With defined EO, there is no difference between the two ways of writing that sum so the programmer has no way to communicate a distinction between "these must be run in a particular order" from "these can be run in parallel".

Now, BrowserUk had an example closer to $x = f($i) + g(++$i); and so perhaps BrowserUk is thinking that a defined EO is important to allow the compiler to add parallelization because otherwise writing this expression is basically an error -- because what gets passed to f() and/or g() depends on the implementation. If so, then he has a point there. But that point is invalidated by two points.

Firstly, the first part of this node shows that this same definition of EO prevents f() and g() from being parallelized so the ability to write $x = f($i) + g(++$i); can't provide the specified gain. You can now write this expression safely, but the compiler can't (in general) do any optimization on it that involves calling g() other than after f() has finished.

Secondly, defined EO is not required for the programmer to express that. If that is what the programmer wants, then they write

$x = f($i) + g(1+$i); $i+=1;
or
$i+=1; $x = f($i-1) + g();
or
my $t = $i++; $x = f($t) + g($i);

or whatever they really meant (I don't know, because I don't know what precise evaluation order was in the mind of this theoretical programmer when they wrote that expression which is ambiguous in the absense of a specific, strict definition of EO).

Note that such an expression of the algorithm would prevent the compiler from moving the assignment to $i around because the programmer ends up specifying the assignment in a separate statement which introduces a sequence point (denoted by the semicolor, ";") across which the compiler is forbidden to move operations (in time) -- well, unless the compiler can perform an analysis that shows that such a movement would not change the outcome.

So, you could make the point that the undefined EO has required the programmer to write code in a way that prevents the compiler from optimizing parts of the code. This is true. However, the gain of being able to call f() and g() in parallel is likely much greater than any gain to be had by being able to move around the much simpler operation of assigning to $i. Further, the compiler is much more likely to be smart enough to be able to tell when a simple assignment can be moved than to be able to tell when two arbitrary expressions (calls to the f and g functions in our examples) are totally independent.

And that is part of the point. f() and g() are stand-ins for arbitrary expressions and so are the important things to consider parallelizing. And the process of making them parallelizible (because EO is undefined) while still well-defined (in the face of undefined EO) is easy to do by, at worst, introducing temporary variables. And the fact that the simple assignments to these temporary variables are restricted by being in separate statements is still a net win because 1) they are tiny operations so optimizing them is much less important and 2) they are extremely simple operations so analysing them to the point of determining that they can be safely moved despite the sequence points is often feasible.

In summary, a defined EO prevents the compiler from moving around operations (in time) in order to optimize them (including running them in parallel) unless the compiler can analyse the operations to the point of determining that such a move does not impact the results.

An undefined EO allows the programmer to write expressions that tell the compiler "you don't need to perform a difficult or impossible analysis of the parts of this expression in order to be able to prove that the order in which parts are done doesn't matter, because I am confident that the order doesn't matter" but can also require the programmer to move certain simple operations out in to separate statements. This prevents the compiler from optimizing these separate statements, except (as in the previous paragraph) when it can prove that the optimizations are safe.

Finally, from experience, I assert that it is not hard to come across cases of f() and g() in the real world where it is easy for the programmer to understand (without being able to prove it) that they are not intertwined while the amount of analysis required by a compiler to prove independence is substantial, often to the point of being infeasible or even impossible.

I hope that helps cut through the near total lack of communication that I perceive in the majority of this thread and allows someone to get to the crux of this persistent misunderstanding.

- tye        


In reply to Re: Why is the execution order of subexpressions undefined? (basics) by tye
in thread Why is the execution order of subexpressions undefined? by BrowserUk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (4)
As of 2024-04-25 18:52 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found