Professional Documents
Culture Documents
A typical VLIW (very long instruction word) machine has instruction words hundreds of bits in length. Multiple functional units are used concurrently in a VLIW processor. All functional units share the use of a common large register file.
Advantages of VLIW
Compiler prepares fixed packets of multiple operations that give the full "plan of execution"
dependencies are determined by compiler and used to schedule according to function unit latencies function units are assigned by compiler and correspond to the position within the instruction packet ("slotting") compiler produces fully-scheduled, hazard-free code => hardware doesn't have to "rediscover" dependencies or schedule
Disadvantages of VLIW
Compatibility across implementations is a major problem
VLIW code won't run properly with different number of function units or different latencies unscheduled events (e.g., cache miss) stall entire processor low slot utilization (mostly nops) reduce nops by compression ("flexible VLIW", "variable-length VLIW")
Overview
Basic Compiler Techniques
Pipeline scheduling loop unrolling
Static Branch Prediction Static Multiple Issue: VLIW Advanced Compiler Support for Exposing ILP
Detecting loop-level parallelism Software pipelining symbolic loop unrolling Global code scheduling
Pentium III/4 MIPS R10K, Alpha 21264, HP PA 8500, IBM RS64III Trimedia, i860
VLIW/LIW
static
software
static
EPIC
mostly static
mostly software
Load double
Store double
Loop Example
Add a scalar to an array. for (i=1000; i>0; i=i-1) x[i] = x[i] + s; Iterations of the loop are parallel with no dependencies between iterations.
Straightforward Conversion
R1 holds the address of the highest array element F2 holds the scalar R2 is pre-computed so that 8(R2) is the last element loop: L.D F0, 0(R1) ;F0 = array element ADD.D F4,F0,F2 ;add scalar in F2 S.D F4, 0(R1) ;store result DADDUI R1,R1,#-8 ;decrement pointer (DW) BNE R1,R2, loop ;branch if R1 != R2
OLD
R1,R2, loop
loop:
2-cycle latency
NEW
Compiler Tasks
loop: L.D DADDUI ADD.D Stall BNE S.D F0, 0(R1) R1,R1,#-8 F4,F0,F2 R1,R2, loop F4, 8(R1) Clock cycle issued 1 2 3 4 5 6
OK to reorder DADDUI and ADD.D OK to reorder S.D and BNE OK to reorder DADDUI and S.D, but requires
0(R1) 8(R1)
This one is difficult since a reverse dependency can be seen:
Loop Overhead
loop: L.D DADDUI ADD.D Stall BNE S.D F0, 0(R1) R1,R1,#-8 F4,F0,F2
R1,R2, loop F4, 8(R1) Clock cycle issued 1 2 3 4 5 6
6 is the minimum due to dependencies and pipeline latencies Actual work of the loop is just 3 instructions:
L.D, ADD.D, S.D
Loop Unrolling
Eliminate some of the overhead by unrolling the loop (fully or partially). Need to adjust the loop termination code Allows more parallel instructions in a row Allows more flexibility in reordering Usually requires register renaming
Unrolled Version
loop: L.D ADD.D S.D L.D ADD.D S.D F0, 0(R1) F4,F0,F2 F4, 0(R1) F6, -8(R1) F8,F6,F2 F8, -8(R1) Assume that the # iterations is a multiple of 4 Decrement R1 by 32 for this 4 iterations More registers required to avoid unnecessary dependencies
F4, 0(R1)
Summary of Example
Version Unscheduled Scheduled
Code size
5 5
Unrolled
Unrolled and Scheduled
7
3.5
14
14
Eliminate extra test and branch instructions and adjust iteration code
OK to move L.D and S.D instructions in unrolled code (requires analyzing memory addresses) Keep all the real dependencies, but reorder to avoid stalls
Compiler limitations
Shortfall in registers Increase in number of live values past # registers
FP Instruction
Clock Cycle 1 2 3 4 5 6
S.D
S.D DADDI
F8, -8(R1)
F12, -16(R1) R1, R1, # -32
ADD.D
F20,F18,F2
7
8 9
S.D
BNE S.D
F16, 16(R1)
R1, R2, loop F20, 8(R1)
10
11 12
Summary of Example
Version Unscheduled Scheduled Unrolled (4) Unrolled (4) and Scheduled Unrolled (5) and Schedule in MultiIssue Pipe
Code size
5 5 14 14 17
Overview
Basic Compiler Techniques
Pipeline scheduling loop unrolling
Static Branch Prediction Static Multiple Issue: VLIW Advanced Compiler Support for Exposing ILP
Detecting loop-level parallelism Software pipelining symbolic loop unrolling Global code scheduling
loop carried dependency, but no cycle (B[k+1] does not have B[k] as source)
Transformation
Two statements can be interchanged. First iteration of first statement can be computed outside loop so that A[k+1] is computed within loop. Last iteration of second statement must also be computed outside loop. A[1] = A[1] + B[1]; for (k=1; k<=100; k=k+1) { A[k] = A[k] + B[k]; B[k+1] = C[k] + D[k];
Expose the parallelism
Recurrences
for (i=2; i<=100; i=i-1) { Y[i] = Y[i-n] + Y[i]; }
Y[i] depends on itself, but uses the value of an earlier iteration. n = dependence distance. Most often, n=1. The larger that n is, the more parallelism is available.
Finding Dependencies
Important for
Efficient scheduling Determining which loops to unroll Eliminating name dependencies
Dependencies in Arrays
Array indices, i, are affine if:
ai+ b (for a one-dimensional array) Index of multiple-dimension arrays is affine if indices in each dimension are affine
For two affine indices: ai+b and ck+d there is a dependence if:
GCD(c,a) must divide (d-b) evenly
Example
For (k=1; k<=100; k=k+1) { X[2k+3] = X[2k] * 5.0; }
GCD test: a=2, b=3 c=2, d=0 Dependence if GCD(c,a) divides (d-b) evenly GCD(2,2) = 2 d-b = -3 k 1 2 3 4 5 6 7 . . . . 100 2k+3 5 7 9 11 13 15 17 . . . . 203 2k 2 4 6 8 10 12 14 . . . . 200
In general, determining if dependency exists is NP-complete. There are exact tests for restricted situations
Dependency Classification
Different dependencies are handled differently
Anti-dependence and output dependence
rename
Real dependencies
try to reorder to separate by length of latency
Example
Find dependencies
True dependencies Output dependencies Anti-dependencies
Output dependence
X[i] = X[i] + c;
Z[i] = Y[i] + c;
Y[i] = c -Y[i]; }
Anti-dependence
Example
Eliminate output dependence (also eliminates second anti-dependence)
Rename Y T
Output dependence
X[i] = X[i] + c;
Z[i] = T[i] + c;
Y[i] = c -T[i]; }
Anti-dependence
Example
Eliminate anti-dependence
Rename X S Final result is parallel loop that can be unrolled
S[i] = X[i] + c;
Z[i] = T[i] + c;
Y[i] = c -T[i]; }
Software Pipelining
Interleaves instructions from different iterations of a loop without unrolling
each iteration is made from instructions from different iterations of the loop software counterpart to Tomasulos algorithm start-up and finish-up code required
Software Pipelining
Software Pipelining
Loop: LD ADD.D S.D DADDUI BNE F0, 0(R1) F4, F0, F2 F4, 0(R1) R1, R1, # -8 R1,R2, Loop 3
symbolic unrolling
new loop
Loop: S.D ADD.D L.D DADDUI BNE F0, 16(R1) ; store to M[i] F4, F0, F2 ; add to M[i-1] F4, 0(R1) ; load M[i-2] R1, R1, # -8 R1,R2, Loop
F0, 0(R1) F4, F0, F2 F4, 0(R1) F0, 0(R1) F4, F0, F2 F4, 0(R1) F0, 0(R1) F4, F0, F2 F4, 0(R1)
3 2
Software Pipelining
new loop
Loop: S.D ADD.D L.D DADDUI BNE F0, 16(R1) ; store to M[i] F4, F0, F2 ; add to M[i-1] F4, 0(R1) ; load M[i-2] R1, R1, # -8 R1,R2, Loop
Result: 1 cycle per instruction 1 loop iteration per 5 cycles less code space than unrolling
rescheduled loop
Loop: S.D DADDUI ADD.D BNE L.D F0, 16(R1) ; store to M[i] R1, R1, # -8 F4, F0, F2 ; add to M[i-1] R1, R2, Loop F4, 8(R1) ; load M[i-2]
Here the overhead includes branch/counter instructions that are not easy to overlap
Finding shortest possible sequence requires identification of critical path. Critical path is the longest sequence of dependent instructions
Trace exits and re-entrances are very complex and require much bookkeeping
Trace Scheduling
Advantages
eliminates some hard decisions in global code scheduling good for code such as scientific programs with intensive loops and predictable behavior
Disadvantages
significant overhead in compensation code when trace must be exited
Superblocks
Similar to trace scheduling, but have only ONE entrance point When trace is exited, a duplicate loop is used for remainder of code (tail duplication)
Tail duplication
Chapter 4 Overview
Basic Compiler Techniques
Pipeline scheduling loop unrolling
Static Branch Prediction Static Multiple Issue: VLIW Advanced Compiler Support for Exposing ILP
Detecting loop-level parallelism Software pipelining symbolic loop unrolling Global code scheduling
Hardware Options
Instruction set change:
conditional instructions
example: conditional move CMOVZ R1, R2, R3
R1 R2 if R3=0
predicated instructions
example: predicated load LWC R1, 9(R2), R3
R1 M[R2+9] if R3 0
Conditional Moves
Can be used to eliminate some branches
if (A==0) {S=T;}
Let A,S,T be assigned to R1, R2, R3 Code without conditional move: BNEZ R1, L ADDU R2, R3, R0 L: Using conditional move: CMOVZ R2, R3, R1 Control dependence is converted to data dependence
Conditional Moves
EX:
Useful for conversions such as absolute value A = abs (B) if (B < 0), { A = -B;} else {A = B}; Can implement with two conditional moves
Useful for short sequences Not efficient for branches that guard large blocks of code. Simplest form of predicated instruction
Predication
Execution of an instruction is controlled by a predicate.
When predicate is false, instruction becomes a nop Full predication is when all instructions can be predicated. Full predication allows conversions of large blocks of code that are branch dependent
Examples
Support conditional moves:
MIPS Alpha PowerPC SPARC Intelx86
Compiler Speculation
To speculate ambitiously, must have
1. The ability to find instructions that can be speculatively moved and not affect program data flow. 2. The ability to ignore exceptions in speculated instructions, until it is certain they should occur. 3. The ability to speculatively interchange loads and stores which may have address conflicts. The last two require hardware support.
Itanium Implementation
Functional units and instruction issue Performance
Other Registers for systems control, memory mapping, performance counters, communication with OS
Integer Registers
R0-R31 always accessible R32-R127 implemented as a register stack
each procedure is allocated to a set of registers
CFM Current Frame pointer used to point to a set of registers for a procedure
Instruction Format
VLIW approach
implicit parallelism among operations in an instruction fixed formatting of the operation fields
A sequence of consecutive instructions with no register dependencies There may be some memory dependencies Boundaries between groups are indicated with a stop.
Instruction Groups
Instruction Bundles
128 bits of encoded instructions Each bundle: 5-bit template field specifies what types of execution units each instruction requires 3 instructions, each 41 bits
Execution Slots
Execution unit slot Instruction Instruction Type Description I-unit A Integer ALU Non-integer ALU Integer ALU Memory Access Floating Point Example instructions
add,sub,and,or... integer and multimedia shifts, bit tests, ... add,sub,and,or... load/stores, int/FP
Floating point instructions Conditional branches Extended immediates, stops, nops
I
M-unit A M F
F-unit
B-unit
L+X
B
L+X
Branches
Extended
31-bits
Together with the 5-bit bundle template, determine the major operation
Predication
Almost all instructions can be predicated
Specify a predicate register in last 6 bits of instruction Predicate registers set with compare or test instructions
Compare 10 possible comparison tests Two predicate registers as destinations Written with result and compliment OR, with logical function that combines tests and compliment Multiple tests can be done with one instruction
Speculation Support
Control speculation support:
Deferred exceptions for speculated instructions
Equivalent of poison bits
Deferred Exceptions
Support to indicate an exception on a speculative instruction
GPRs have NaT (Not a Thing) bits (make registers 65-bits long) FPRs use NaTVal (Not a Thing Value)
Significand of 0 and exponent out of range
NaTs and NaTVals are propagated by speculative instructions that dont reference memory FP instructions use status registers to record exceptions for this purpose.
If a chk.s instruction detects the presence of NaT or NaTVal, branch to routine designed to recover from speculative operation.
When instruction USING speculative load value is executed, ALAT table is checked
Ld.c check that is used if only load is speculative
Only causes a reload of the value
Chk.a check that is used if other speculative code used the load value.
Specifies address of a fix-up routine that re-executes code sequence.
Itanium Processor
First implementation of IA-64 (2001) 800 MHz clock Multi-issue up to 6-issues per clock cycle Up to 3 branches and 2 memory references 3-level cache memory hierarchy
L1 is split data/instruction caches L2 is unified cache on-chip L3 is unified cache off-chip (but on container)
Features of itanium
64-bit addressing EPIC (Explicit Parallel Instruction Computing) Wide Parallel Execution core Prediction FPU, ALU and Rotating registers Large fast Cache High Clock Speed Scalability Error Handling Fast Bus Architecture
Functional Units
I-unit I-unit M-unit M-unit Instruction Integer load B-unit F-unit B-unit F-unit B-unit Floating-point load Correctly predicted taken branch Mispredicted branch Latency 1 9 0-3 9 All functional units are pipelined Bypassing paths are implemented (forwarding) Bypass between units has a 1 cycle delay
0 4
Itanium Multi-Issue
Instruction Issue window of 2 bundles at a time Up to 6 instructions issues at once
template
inst 1
inst 2
inst 3
template
inst 1
inst 2
inst 3
NOPs and predicated instructions with false predicates are not issued If one or more instructions cannot be issued due to unavailable function unit, bundle can be split
Itanium Pipeline
10 Stages
Front-End IPG Fetch Rotate Instruction Delivery EXP REN Operand Delivery WLD REG EXE Execution DET WRB
Prefetches up to 32 bytes per clock Can hold up to 8 bundles Branch prediction: multilevel adaptive predictor
Access register file register bypassing register scoreboard checks predicate dependencies
Executes instructions through ALU and load-store units Detects exceptions and posts NaTs Write back
IPG
FET
ROT EXP REN
: Fetch instruction
: Rotate : Expand : Rename
WL.D
REG EXE DET WRB
Limits on ILP
Achieving Parallelism
Techniques Scoreboarding / Tomasulos Algorithm Pipelining Speculation Branch Prediction But how much more performance could we theoretically get? How much ILP exists? How much more performance could we realistically get?
Limits to ILP
Initial HW Model here; MIPS compilers. Assumptions for ideal/perfect machine to start: 1. Register renaming infinite virtual registers => all register WAW & WAR hazards are avoided 2. Branch prediction perfect; no mispredictions 3. Jump prediction all jumps perfectly predicted (returns, case statements) 2 & 3 no control dependencies; perfect speculation & an unbounded buffer of instructions available 4. Memory-address alias analysis addresses known & a load can be moved before a store provided addresses not equal; 1&4 eliminates all but RAW Also: perfect caches; 1 cycle latency for all instructions (FP 83 *,/); unlimited instructions issued/clock cycle;
Power 5
4 200 48 integer + 40 Fl. Pt. 2% to 6% misprediction (Tournament Branch Predictor) 64KI, 32KD, 1.92MB L2, 36 MB L3 ??
WAR and WAW hazards through memory: Eliminated WAW and WAR hazards through register renaming, but not in memory usage
84