176 lines
10 KiB
HTML
176 lines
10 KiB
HTML
|
<!DOCTYPE HTML PUBLIC "-//W3O//DTD W3 HTML 2.0//EN">
|
||
|
<!Converted with LaTeX2HTML 0.6.5 (Tue Nov 15 1994) by Nikos Drakos (nikos@cbl.leeds.ac.uk), CBLU, University of Leeds >
|
||
|
<HEAD>
|
||
|
<TITLE>A.3.2. Constraint Cycles</TITLE>
|
||
|
</HEAD>
|
||
|
<BODY>
|
||
|
<meta name="description" value=" Constraint Cycles">
|
||
|
<meta name="keywords" value="clm">
|
||
|
<meta name="resource-type" value="document">
|
||
|
<meta name="distribution" value="global">
|
||
|
<P>
|
||
|
<b>Common Lisp the Language, 2nd Edition</b>
|
||
|
<BR> <HR><A NAME=tex2html6178 HREF="node359.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html6176 HREF="node356.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html6170 HREF="node357.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html6180 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html6181 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html6179 HREF="node359.html"> Defining New Series </A>
|
||
|
<B>Up:</B> <A NAME=tex2html6177 HREF="node356.html"> Optimization</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html6171 HREF="node357.html"> Basic Restrictions</A>
|
||
|
<HR> <P>
|
||
|
<H2><A NAME=SECTION003432000000000000000>A.3.2. Constraint Cycles</A></H2>
|
||
|
<P>
|
||
|
<img align=bottom alt="change_begin" src="gif/change_begin.gif"><br>
|
||
|
Even if a series expression satisfies all of the restrictions above, it
|
||
|
still may not be possible to transform the expression into a loop. The
|
||
|
sole remaining problem is that if a series is used in two places, the
|
||
|
two uses may place incompatible constraints on the times at which series
|
||
|
elements should be produced.
|
||
|
<P>
|
||
|
The series expression below shows a situation where this problem arises.
|
||
|
The expression creates a series <tt>x</tt> of the elements in a list. It then
|
||
|
creates a normalized series by dividing each element of <tt>x</tt> by the sum
|
||
|
of the elements in <tt>x</tt>. Finally, the expression returns the maximum of
|
||
|
the normalized elements.
|
||
|
<P><pre>
|
||
|
(let ((x (scan '(1 2 5 2)))) ;Warning message issued
|
||
|
(collect-max (#M/ x (series (collect-sum x))))) => 1/2
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
The two uses of <tt>x</tt> in the expression place contradictory
|
||
|
constraints on the way pipelined evaluation must proceed; <tt>collect-sum</tt>
|
||
|
requires that all of the elements of <tt>x</tt> be produced before the sum can
|
||
|
be returned, and <tt>series</tt> requires that its input be available before it
|
||
|
can start to produce its output. However, <tt>#M/</tt> requires that the
|
||
|
first element of <tt>x</tt> be available at the same time as the first element
|
||
|
of the output of <tt>series</tt>. For pipelining to work,
|
||
|
the first element of the output of <tt>series</tt> (and therefore the output
|
||
|
of <tt>collect-sum</tt>) must be available before the second element of
|
||
|
<tt>x</tt> is produced. Unfortunately, this is impossible.
|
||
|
<P>
|
||
|
The essence of the inconsistency above is the cycle of constraints used in
|
||
|
the argument. This in turn stems from a cycle in the data flow graph
|
||
|
underlying the expression. In
|
||
|
figure <A HREF="node358.html#SERIESF1FIGURE">A-1</A> function calls are represented by boxes and data
|
||
|
flow is represented by arrows. Simple arrows indicate the flow of series
|
||
|
values and cross-hatched arrows indicate the flow of non-series values.
|
||
|
<P>
|
||
|
<A NAME=SERIESF1FIGURE> </A>
|
||
|
<listing>
|
||
|
----------------------------------------------------------------
|
||
|
Figure A-1: A Constraint Cycle in a Series Expression
|
||
|
|
||
|
+------+ +-----+ +-----+
|
||
|
-->| scan |----------------------------------->| #M/ |-->| max |-->
|
||
|
+------+ \ +-----+ +--------+ / +-----+ +-----+
|
||
|
-->| sum |-++++->| series |--
|
||
|
+-----+ +--------+
|
||
|
|
||
|
----------------------------------------------------------------
|
||
|
</listing>
|
||
|
<P>
|
||
|
Given a data flow graph corresponding to a series expression, a <i>constraint cycle</i> is a closed oriented loop of data flow arcs such
|
||
|
that each arc is traversed exactly once and no non-series arc
|
||
|
is traversed backward. (Series data flow arcs can be traversed in either
|
||
|
direction.) A constraint cycle is said to <i>pass through</i> an input or
|
||
|
output port when exactly one of the arcs in the cycle touches the port. In
|
||
|
figure <A HREF="node358.html#SERIESF1FIGURE">A-1</A> the data flow arcs touching <tt>scan</tt>, <tt>sum</tt>,
|
||
|
<tt>series</tt>, and <tt>#M/</tt> form a constraint cycle. Note that if the
|
||
|
output of <tt>scan</tt> were not a series, this loop would not be a constraint
|
||
|
cycle, because there would be no valid way to traverse it. Also note that
|
||
|
while the constraint cycle passes through all the other ports it touches,
|
||
|
it does not pass through the output of <tt>scan</tt>.
|
||
|
<P>
|
||
|
Whenever a constraint cycle passes through a non-series output, an argument
|
||
|
analogous to the one above can be constructed and therefore pipelining will be
|
||
|
impossible. When this situation arises, a warning message is issued
|
||
|
identifying the problematical port and the cycle passing through it. For
|
||
|
instance, the warning triggered by the example above states that the
|
||
|
constraint cycle associated with <tt>scan</tt>, <tt>collect-sum</tt>,
|
||
|
<tt>series</tt>, and <tt>#M/</tt> passes through the non-series output of
|
||
|
<tt>collect-sum</tt>.
|
||
|
<P>
|
||
|
Given this kind of detailed information, it is easy to alleviate the
|
||
|
problem. To start with, every cycle must contain at least one function
|
||
|
that has two series data flows leaving it. At worst, the cycle can be broken by
|
||
|
duplicating this function (and any functions computing series used by it).
|
||
|
For instance, the example above can be
|
||
|
rewritten as shown below.
|
||
|
<P><pre>
|
||
|
(let ((x (scan '(1 2 5 2)))
|
||
|
(sum (collect-sum (scan '(1 2 5 2)))))
|
||
|
(collect-max (#M/ x (series sum))))
|
||
|
=> 1/2
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
It would be easy enough to automatically apply code copying to break
|
||
|
problematical constraint cycles. However, this is not done for two
|
||
|
reasons. First, there is considerable virtue in maintaining the property
|
||
|
that each function in a series expression turns into one piece of
|
||
|
computation in the loop produced. Users can be confident that series
|
||
|
expressions that look simple and efficient actually are simple and
|
||
|
efficient. Second, with a little creativity, constraint problems can often
|
||
|
be resolved in ways that are much more efficient than copying code. In the
|
||
|
example above, the conflict can be eliminated efficiently by interchanging
|
||
|
the operation of computing the maximum with the operation of normalizing an
|
||
|
element.
|
||
|
<P><pre>
|
||
|
(let ((x (scan '(1 2 5 2))))
|
||
|
(/ (collect-max x) (collect-sum x))) => 1/2
|
||
|
</pre><P>
|
||
|
<P>
|
||
|
The restriction that optimizable series expressions cannot contain
|
||
|
constraint cycles that pass through non-series outputs places limitations on
|
||
|
the qualitative character of optimizable series expressions. In particular,
|
||
|
they all must have the general form of creating some number of series using
|
||
|
scanners, computing various intermediate series using transducers, and then
|
||
|
computing one or more summary results using collectors. The output of a
|
||
|
collector cannot be used in the intermediate computation unless it is the
|
||
|
output of a separate subexpression.
|
||
|
<P>
|
||
|
It is worthy of note that the last expression above fixes the constraint
|
||
|
conflict by moving the non-series output out of the cycle, rather than by
|
||
|
breaking the cycle. This illustrates the fact that constraint cycles that
|
||
|
do not pass through non-series outputs do not necessarily cause problems.
|
||
|
They cause problems only if they pass through <i>off-line</i> ports.
|
||
|
<P>
|
||
|
A series input port or series output port of a series function is <i>on-line</i>
|
||
|
if and only if it is processed in lockstep with all the other on-line
|
||
|
ports as follows: the initial element of each on-line input is
|
||
|
read, then the initial element of each on-line output is written, then the
|
||
|
second element of each on-line input is read, then the second element of
|
||
|
each on-line output is written, and so on. Ports that are not on-line are
|
||
|
off-line. If all of the series ports of a function are on-line, the
|
||
|
function is said to be on-line; otherwise, it is off-line. (The above
|
||
|
extends the standard definition of the term <i>on-line</i> so that it applies
|
||
|
to individual ports as well as whole functions.)
|
||
|
<P>
|
||
|
If all of the ports a cycle passes through are on-line, the lockstep
|
||
|
processing of these ports guarantees that there cannot be any conflicts
|
||
|
between the constraints associated with the cycle. However, passing
|
||
|
through an off-line port leads to the same kinds of problems as passing
|
||
|
through a non-series output.
|
||
|
<P>
|
||
|
Most of the series functions are on-line. In particular, scanners and
|
||
|
collectors are all on-line as are many transducers. However, the
|
||
|
transducers in section <A HREF="node353.html#SERIESOLSECTION">A.2.4</A> are off-line. In particular, the
|
||
|
series inputs of <tt>catenate</tt>, <tt>choose-if</tt>, <tt>chunk</tt>, <tt>expand</tt>, <tt>mask</tt>,
|
||
|
<tt>mingle</tt>, <tt>positions</tt>, and <tt>subseries</tt> along with the
|
||
|
series outputs of <tt>choose</tt>, <tt>split</tt>, and <tt>split-if</tt> are off-line.
|
||
|
<P>
|
||
|
In summary, the fourth and final restriction is that <b>for optimization
|
||
|
to be possible, a series expression cannot contain a constraint cycle that
|
||
|
passes through a non-series output or an off-line port</b>. Whenever this
|
||
|
restriction is violated a warning message is issued. Violations can be
|
||
|
fixed either by breaking the cycle or restructuring the computation so that
|
||
|
the offending port is removed from the cycle.
|
||
|
<br><img align=bottom alt="change_end" src="gif/change_end.gif">
|
||
|
<P>
|
||
|
<BR> <HR><A NAME=tex2html6178 HREF="node359.html"><IMG ALIGN=BOTTOM ALT="next" SRC="icons/next_motif.gif"></A> <A NAME=tex2html6176 HREF="node356.html"><IMG ALIGN=BOTTOM ALT="up" SRC="icons/up_motif.gif"></A> <A NAME=tex2html6170 HREF="node357.html"><IMG ALIGN=BOTTOM ALT="previous" SRC="icons/previous_motif.gif"></A> <A NAME=tex2html6180 HREF="node1.html"><IMG ALIGN=BOTTOM ALT="contents" SRC="icons/contents_motif.gif"></A> <A NAME=tex2html6181 HREF="index.html"><IMG ALIGN=BOTTOM ALT="index" SRC="icons/index_motif.gif"></A> <BR>
|
||
|
<B> Next:</B> <A NAME=tex2html6179 HREF="node359.html"> Defining New Series </A>
|
||
|
<B>Up:</B> <A NAME=tex2html6177 HREF="node356.html"> Optimization</A>
|
||
|
<B> Previous:</B> <A NAME=tex2html6171 HREF="node357.html"> Basic Restrictions</A>
|
||
|
<HR> <P>
|
||
|
<HR>
|
||
|
<P><ADDRESS>
|
||
|
AI.Repository@cs.cmu.edu
|
||
|
</ADDRESS>
|
||
|
</BODY>
|