• Tidak ada hasil yang ditemukan

2.3 Dynamic Single Assignment

2.3.5 Repetition Statements

is transformed into

x0:=xinit; *[ X!x0; C?x1; Y!x1; D?x2 ]

then the variable x0 does not hold the value of x2 after an iteration but instead always keeps the initial valuexinit. DDD’s solution is to change the name of the variable defined in the initial code and insert a copy statement for DSA variables ofx at the beginning of the main loop. The transformed program is therefore

x2:=xinit; *[ x0:=x2; X!x0; C?x1; Y!x1; D?x2 ]

Consider a program P containing a loop as above, where x represents all variables used in S before they are defined inS. DDD begins by individually convertingAADSA,SSDSAandZ ZDSA such that for all variables x in P, NADSA[x] = N0SDSA[x] and NSDSA[x] = N0ZDSA[x]. It transforms G GDSA by replacing all instances of x in G with DSA variable xNADSA

[x]. The intermediate program that results is

ADSA; *[ GDSA−→ SDSA ]; ZDSA

(Note that when x is used before being defined in SDSA, its DSA index isNADSA[x].) DDD then inserts two copy statements into the code:

ADSA; xNSDSA

[x]:=xNADSA

[x]; *[ GDSA−→ xNADSA

[x]:=xNSDSA

[x]; SDSA ]; ZDSA

Theorem 4 Let P ≡ A;*[G → S];Z be a non-terminating program with terminating compo- nents A, S , and Z . If PPDSA following the DDD method given above, then P pgm≡ PDSA and PDSA is in DSA form.

Proof: We begin by noting that, for all variables x used before being defined in S,

NADSA[x] =N0SDSA[x]≤NSDSA[x]

ThereforexNADSA

[x]is used but not defined anywhere in the body ofSDSA, andxNSDSA

[x]is also not defined anywhere in the body of ADSA, and so the insertion of the two copy statements does not

affect the individual DSA form of eitherSDSAor ofADSA. Therefore, by Definition 6, since the code preceding the loop, the code in the loop body, and the code following the loop are all individually in DSA form,PDSA is in DSA form as well.

Now, since they are all terminating programs, A pgm≡ ADSA, S pgm≡ SDSA and Z pgm≡ ZDSA

by Theorems 2 and 3. To fulfill program equivalence for non-terminating programs as specified in Definition 2, it remains to show that the names of all variables xi ∈ XDSA used in the body of PDSA’s loop before being defined in the loop match the names of variables on the LHS of the l ast assignments to any DSA variablexi ∈XDSA in ADSA andSDSA.

But the first definition to a DSA variable in the loop body is actually the inserted copy assign- ment at the beginning of the loop. The only DSA variable used before the definition is therefore on the RHS of the definition itself,xNSDSA

[x]. By definition, this is the DSA variable last assigned a value inSDSA. Because of the copy statement inserted immediately preceding the loop, it is also the last DSA variable assigned a value inADSA. Therefore,P pgm≡ PDSA. 2

2.3.5.2 Nested Conditional Loops

The case of conditional repetition statements nested within a non-terminating program is illustrated by the following code:

P ≡ Ainit; *[ A; *[G −→ S]; Z ]

We present two methods of transforming such loops into DSA form: one straightforward but ineffi- cient, the other more complicated but also more generally applicable.

The first method, transforming the entire program into a state machine, is inefficient in terms of the communications that it will require in the eventual decomposed system. We include it because it is general and straightforward and can be useful in simple cases. The method converts nested loops into selection statements through the addition of a state bit to the process. Then, the DSA transformation for selection statements can be performed to rewrite the entire program in DSA form.

Consider the general programPfor repetition statements given above. We introduce a state bitx that is true when the program is executing statements within the loop, and false when the program is on the outside of the loop. With the addition of a large encompassing selection statement, we can now push the repetitive behavior of the inner loop out onto the unconditional main loop.

Ainit, x↓;

*[ [¬x −→ A, x↑ [] x∧ G−→ S [] x∧ ¬G−→ Z, x↓ ] ]

While this is a valid transformation, it is not ideal because all program variables now directly depend upon x. When the variables are all split into their own processes by DDD, the value of x will need to be explicitly communicated to all of them. Even when hardware optimizations introduced in Chapter 4 are applied to the decomposed system, the system may be inefficient with its communications. Still, the nested repetitions have been removed, and the program can be converted to DSA form as illustrated in the previous section.

A more efficient way of handling nested loops is to perform an early decomposition of the se- quential program. The code within the loop is moved to one process while the code outside of the loop is kept in another. An example of such a solution is

P ≡ Ainit; *[ A; *[G−→ S]; Z ] Pout k Pin

Pout ≡ Ainit; *[ A; AS!; SZ?; Z ]

Pin ≡ x↓; *[ [¬x −→ AS? []x −→ skip];

[ G−→ S, x↑ []¬G−→ SZ!, x↓ ] ]

whereAS and SZ are newly- introduced channels.

There is no added concurrency in this decomposition. Synchronizing semicolons in the sequential program have been replaced with synchronizing communications in the decomposed system, and the

P ≡ Ainit; ause :=faa(ainit);

*[ adef := A(ause);

guse :=fag(adef), suse :=fas(adef), zuse :=faz(adef);

*[ G(guse)−→ sdef := S(suse);

guse :=fsg(sdef), zuse :=fsz(sdef), suse :=fss(sdef) ];

zdef := Z(zuse);

ause :=fza(zdef) ]

P ≡ Pin k Pout

Pout ≡ Ainit; ause :=faa(ainit);

*[ adef := A(ause);

guse :=fag(adef), suse :=fas(adef), zuse :=faz(adef);

AS!{suse,guse}; SZ?zuse; zdef := Z(zuse);

ause :=fza(zdef) ]

Pin ≡x↓;

*[ [ ¬x −→ AS?{suse,guse} [] x −→ skip ];

[ G(guse)−→ sdef := S(suse);

guse :=fsg(sdef), zuse :=fsz(sdef), suse :=fss(sdef), x↑ [] ¬ G(guse)−→ SZ!zuse, x↓

] ]

Figure 2.4: DSA transformation of repetition statements.

Example of early decomposition, including data.

two implementations are semantically equivalent. The advantage of this solution over the general state machine is that only short communication statements, and not arbitrarily long series, are contained within selection statements. Thus, less communication will be required between guard variables and decomposed processes in the eventual distributed system. Both processes can now be converted into DSA form and decomposed separately.

We demonstrated the abstract split of computations above, but have not yet included the data communications required between processes. A more realistic representation of the scenario that explicitly includes variables that are used and defined by each CHP series is given in Figure 2.4. In this example, the notation “vdef :=V(vuse)” indicates that the CHP seriesVuses variables from the setvuse and contains assignments to variables from the setvdef. The notation “wuse :=fvw(vdef)” is included to explicit indicate which variables assigned values in the seriesVare used in the ensuing

seriesW.

The decomposition shown in Figure 2.4 is correct: the two new processes together form the equivalent of the original sequential program. Both new processes (Pin and Pout) contain only straightline code and selection statements, and so can be converted into DSA form as demonstrated in the previous sections. Now DDD can apply the projection technique of Section 2.4 to both processes separately and then recombine the resulting systems for the clustering heuristic of Chapter 5.