- 42 Views
- Uploaded on
- Presentation posted in: General

Compiler Challenges, Introduction to Data Dependences

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Compiler Challenges, Introduction to Data Dependences

Allen and Kennedy, Chapter 1, 2

- Pipelining
- Multiple execution units
- Pipelined

- Vector operations
- Parallel processing
- Shared memory, distributed memory, message-passing

- Simultaneous Multithreading (SMT) VLIW and Superscalar instruction issue
- Registers
- Cache hierarchy
- Combinations of the above
- Parallel-vector machines

- When is it safe to run two tasks R1 and R2 in parallel?
- If none of the following holds:
- R1 writes into a memory location that R2 reads
- R2 writes into a memory location that R1 reads
- Both R1 and R2 write to the same memory location

- If none of the following holds:
- How can we convert this to loop parallelism?
- Think of loop iterations as tasks

- Problem: memory is moving farther away in processor cycles
- Latency and bandwidth difficulties

- Solution
- Reuse data in cache and registers

- Challenge: How can we enhance reuse?
- Coloring register allocation works well
- But only for scalars
- DO I = 1, N
- DO J = 1, N
- C(I) = C(I) + A(J)

- But only for scalars
- Strip mining to reuse data from cache

- Coloring register allocation works well

- Program Transformations
- Most of these architectural issues can be helped by restructuring transformations that can be reflected in source
- Vectorization, parallelization, cache reuse enhancement

- Challenges:
- Determining when transformations are legal
- Selecting transformations based on profitability

- Most of these architectural issues can be helped by restructuring transformations that can be reflected in source
- Low level code generation
- Some issues must be dealt with at a low level
- Prefetch insertion
- Instruction scheduling

- Some issues must be dealt with at a low level
- All require some understanding of the ways that instructions and statements depend on one another (share data)

- Goal: aggressive transformations to improve performance
- Problem: when is a transformation legal?
- Simple answer: when it does not change the meaning of the program
- But what defines the meaning?

- Same sequence of memory states
- Too strong!

- Same answers
- Hard to compute (in fact intractable)
- Need a sufficient condition

- We use dependence
- Ensures instructions that access the same location (with at least one a store) must not be reordered

Allen and Kennedy, Chapter 2 pp. 35-48

What shall we cover in this chapter?

- Introduction to Dependences
- Loop-carried and Loop-independent Dependences
- Simple Dependence Testing
- Parallelization and Vectorization

What are our goals?

- Simple Goal: Make execution time as small as possible
Which leads to:

- Achieve execution of many (all, in the best case) instructions in parallel
- Find independentinstructions

- We will concentrate on data dependences
- Chapter 7 deals with control dependences
- Need both to determine correctness
- Simple example of data dependence:
S1PI = 3.14

S2 R = 5.0

S3 AREA = PI * R ** 2

- Statement S3 cannot be moved before either S1 or S2 without compromising correct results

- Formally:
There is a data dependence from statement S1 to statement S2 (S2depends on S1) if:

1. Both statements access the same memory location and at least one of them stores onto it, and

2. There is a feasible run-time execution path from S1 to S2

Cannot determine in general if there is an actual path at runtime

- Undecidable

- Feasible path = path in control flow graph

- Dependences classified in terms of load-store order:
1. True (flow) dependences (RAW hazard) X =

- S2 depends on S1 is denoted by S1 S2 = X
2. Antidependence (WAR hazard) = X

S2 depends on S1 is denoted by S1-1 S2X =

3. Output dependence (WAW hazard)X =

S2 depends on S1 is denoted by S10 S2X =

- S2 depends on S1 is denoted by S1 S2 = X

- Let us look at two different loops:

DO I = 1, N

S1 A(I+1) = A(I) + B(I)

ENDDO

DO I = 1, N

S1 A(I+2) = A(I) + B(I)

ENDDO

- In both cases, statement S1 depends on itself
- However, there is a significant difference
- We need a formalism to describe and distinguish such dependences

- The iteration number of a loop is equal to the value of the loop index for a simple loop (DO I = 1, N)
- Definition:
- For an arbitrary loop in which the loop index I runs from L to U in steps of S, the iteration numberi of a specific iteration is equal to the index value I on that iteration
- The normalized iteration number i is given by (I – L + S) / S
Example:

DO I = 0, 10, 2

S1 <some statement>

ENDDO

What do we do for nested loops?

- Need to consider the nesting level of a loop
- Nesting level of a loop is equal to one more than the number of loops that enclose it.
- Given a nest of n loops, the iteration vector i of a particular iteration of the innermost loop is a vector of integers that contains the iteration numbers for each of the loops in order of nesting level.
- Thus, the iteration vector is: {i1, i2, ..., in }where ik, 1 k m represents the iteration number for the loop at nesting level k

Example:

DO I = 1, 2

DO J = 1, 2

S1 <some statement>

ENDDO

ENDDO

- The iteration vector S1[(2, 1)] denotes the instance of S1 executed during the 2nd iteration of the I loop and the 1st iteration of the J loop

- Iteration Space: The set of all possible iteration vectors for a statement
Example:

DO I = 1, 2

DO J = 1, 2

S1 <some statement>

ENDDO

ENDDO

- The iteration space for S1 is { (1,1), (1,2), (2,1), (2,2) }

- Useful to define an ordering for iteration vectors
- Define an intuitive, lexicographic order
- Iteration i precedes iteration j, denoted i< j, iff:
1. i[i:n-1] < j[1:n-1], or

2. i[1:n-1] = j[1:n-1] and in < jn

- Theorem 2.1 Loop Dependence:There exists a dependence from statements S1 to statement S2 in a common nest of loops if and only if there exist two iteration vectors i and j for the nest, such that (1) i < j or i = j and there is a path from S1 to S2 in the body of the loop, and(2) statement S1 accesses memory location M on iteration i and statement S2 accesses location M on iteration j, and (3) one of these accesses is a write.
- Follows from the definition of dependence

- We call a transformation safe if the transformed program has the same "meaning" as the original program
- But, what is the "meaning" of a program?
For our purposes:

- Two computations are equivalent if, on the same inputs:
- They produce the same outputs in the same order

- Qu: What about exceptions/errors?

- A reordering transformation is any program transformation that merely changes the order of execution of the code, without adding or deleting any executions of any statements
- Examples
- Scheduling
- Tiling
- Loop Reversal
- Loop Fusion
- …

- A reordering transformation does not eliminate dependences
- However, it can change the ordering of the dependence which will lead to incorrect behavior
- A reordering transformation preserves a dependence if it preserves the relative execution order of the source and sink of that dependence.

- Fundamental Theorem of Dependence:
- Any reordering transformation that preserves every dependence in a program preserves the meaning of that program

- Proof by contradiction. Theorem 2.2 in the book.

- A transformation is said to be validfor the program to which it applies if it preserves all dependences in the program.
- Preserves load/store order
- Only order of inputs can change
- Doesn’t use
- Semantic knowledge
- Equivalence

- Consider a dependence in a loop nest of n loops
- Statement S1 on iteration i is the source of the dependence
- Statement S2 on iteration j is the sink of the dependence

- The distance vector is a vector of length n d(i,j) such that: d(i,j)k = jk - ik
- We shall normalize distance vectors for loops in which the index step size is not equal to 1.

- Definition 2.10 in the book:
Suppose that there is a dependence from statement S1 on iterationi of a loop nest of n loops andstatement S2 on iteration j, then the dependence direction vector is D(i,j) is defined as a vector of length n such that

“<” if d(i,j)k > 0

D(i,j)k =“=” if d(i,j)k = 0

“>” if d(i,j)k < 0

Example:

DO I = 1, N

DO J = 1, M

DO K = 1, L

S1 A(I+1, J, K-1) = A(I, J, K) + 10

ENDDO

ENDDO

ENDDO

- S1 has a true dependence on itself.
- Distance Vector: (1, 0, -1)
- Direction Vector: (<, =, >)

- A dependence cannot exist if it has a direction vector whose leftmost non "=" component is not "<" as this would imply that the sink of the dependence occurs before the source.