Parallel programming with models
of computation
Prof. Dr.-Ing. Jeronimo Castrillon
Tunis, Tunisia. December 2-4, 2015
Chair for Compiler Construction
Georg-Schumann-Str. 7A, 2 OG
Lecture 2: Compilers and task-based
programming models
Parallel programming with models of computation
Prof. Dr.-Ing. Jeronimo Castrillon
Tunis, Tunisia. December 2-4, 2015
Chair for Compiler Construction
Georg-Schumann-Str. 7A, 2 OG
Agenda
09:00 AM
12:30 PM
14:00 PM
LB1-I
HO-I
LB2-I
break
LB2-I (cont)
break
LB2-II
HO-II
LB3-I
break
LB3-II
HO-III
LB4/Q&A
LB1-I
17:30 PM
3
© J. Castrillon. Parallel Programming
Recall: Lecture 1
q Why parallelism?
q Programming models
q Basics of computer architectures (including parallel ones)
q Fundamentals of parallelism (concurrency, types, Amdahl/Gustafson, …)
q Example of standard programming models (MPI, Pthreads, OpenMP)
4
© J. Castrillon. Parallel Programming
Recall: Lecture 1 (2)
q Pthreads/OpenMP – Shared memory
q Easy to introduce races (when/how to use private?)
q Easy to introduce locks
q MPI: Message Passing Interface – Distributed memory
q Large API: 152!
q Easy to introduce deadlocks
q In this lecture:
http://nerds-
central.blogspot.de/2011/11/atomicinteger-
volatile-synchronized-and.html
q Why not stick to sequential programming? – Limits of compilers
q Easier models – Task-based programming
5
© J. Castrillon. Parallel Programming
Contents
q Basics of compilers
q Auto-parallelizing compilers
q Task-based programming models
6
© J. Castrillon. Parallel Programming
Basics of compilers
7
© J. Castrillon. Parallel Programming
Compiler phases
Frontend
Middle-end
Backend
IR
IR
q IR: Intermediate representation
q Frontend: Legal code è IR
q (Typ.) Target-independent
q Middle-end: IR è Optimized IR
q (Typ.) Target-independent
q Backend: IR è Target code
q Target-dependent
Java
C
ML
Fortran
Pentium
Sparc
MIPS
Java
C
ML
Fortran
IR
Pentium
Sparc
MIPS
Adapted from: A. Appel: Modern Compiler Implementation in C.
8
© J. Castrillon. Parallel Programming
Front-end
q Deals with the language syntax and semantics to produce an interanal model
(i.e., the IR)
while (y < z)
{
int x = a + b;
y += x;
Frontend
}
9
© J. Castrillon. Parallel Programming
Middle-end
q Further analysis (e.g., dataflow) and model transformation
Middle-
end
10
© J. Castrillon. Parallel Programming
Backend
q Target-specific optimization and transformations
Backend
11
© J. Castrillon. Parallel Programming
Linear IR: Three-address code (TAC)
q “High-level assembly”
q Each operation has at most 3 operands
q x = y op z
q Representation used by many compilers
q Example: LLVM
int main()
{
int a, b, c;
a = 2; b = 3;c = 5;
c += (a*b) >> a;
c += foo(a);
return 0;
}
12
© J. Castrillon. Parallel Programming
define i32 @main() #0 {
t2 = t1 >> 2
t3 = t2 – 7
t4 = t2 + t3
%1 = alloca i32, align 4
%a = alloca i32, align 4
%b = alloca i32, align 4
%c = alloca i32, align 4
store i32 0, i32* %1
store i32 2, i32* %a, align 4
store i32 3, i32* %b, align 4
store i32 5, i32* %c, align 4
%2 = load i32* %a, align 4
%3 = load i32* %b, align 4
%4 = mul nsw i32 %2, %3
%5 = load i32* %a, align 4
%6 = ashr i32 %4, %5
%7 = load i32* %c, align 4
%8 = add nsw i32 %7, %6
store i32 %8, i32* %c, align 4
%9 = load i32* %a, align 4
%10 = call i32 @foo(i32 %9)
%11 = load i32* %c, align 4
%12 = add nsw i32 %11, %10
store i32 %12, i32* %c, align 4
ret i32 0}
Int: 32 bits
c +=
(a*b) >> a
Calling
conventions
Flow analysis: Intuition
q Better representation of program facts not directly visible in the TAC IR
q Branching, loops, definition of variables, …
è Collected information is key for optimizations
x = 10 * 2
_t1 = x < z
if _t1 goto L1
u = y + z
goto L2:
L1:
u = y – z
L2:
z = u + x
x = 20
x = 10 * 2
_t1 = x < z
_t1 = x < z
if _t1 goto L1
if _t1 goto L1
Control flow
graph
Basic block
u = y + z
u = y + z
u = y - z
u = y - z
z = u + 20
z = u + x
13
© J. Castrillon. Parallel Programming
Data-flow analysis
q Collect information about the possible set of values at various points in a
program for performing sound optimizations and code generation
q Examples:
q Where is a variable defined?
q Could some statement use a variable definition?
q Principle
out[p1]
out[p2]
Join function
in[n]
n (stmt,BB,...)
in[n] = joinp
out[n] = fn(in[n])
2
pred(n)(out[p])
Transfer function
out[n]
Program point
14
© J. Castrillon. Parallel Programming
Data-flow analysis: Principle of operation
q Data-flow equations
in[n] = joinp
out[n] = fn(in[n])
2
pred(n)(out[p])
q Typical join and transfer functions:
in[n] =
out[p]
pred(n)
[p
2
out[n] = gen[n]
(in[n]
[
kill[n])
(efficient implementation via
bit-vectors)
II -
15
© J. Castrillon. Parallel Programming
out[p1]
out[p2]
in[n]
n (stmt,BB,...)
out[n]
f
o
r
w
a
r
d
q in[n]
data coming directly before n
q out[n] data outgoing directly after n
q gen[n] data produced by n
q kill[n] data destroyed by n
Solving the data-flow system of equations
q The equations for each statement (or
basic-block) depend on each other
è System of equations
q Iterative solution
q Initialize the in-sets
q Iteratively compute the out-sets,
update the in-sets, until no changes
are observed
q Termination? Nice application of
theory of semi-lattices
in[n1] =
out[p]
out[n1] = gen[n1]
[
in[n2] =
pred(n1)
[p
2
(in[n1]
kill[n1])
out[p]
out[n2] = gen[n2]
pred(n2)
[p
2
(in[n2]
kill[n2])
[
…
II -
16
© J. Castrillon. Parallel Programming
Dataflow analysis: Example
q Information collected stored in use-def or def-use chains
q Needed if computation is mapped to another core
1: a = 5
2: c = 1
3: L1: if (a > c) goto L2;
{1}
{2,4}
{2,4}
{2,4}
4: c = c + c;
5: goto L1;
6: L2: a = c – a;
7: c = 0;
17
© J. Castrillon. Parallel Programming
Control and dataflow: Example
18
© J. Castrillon. Parallel Programming
Source: Leupers, Sheng, Castrillon. “Software Compilation Techniques for MPSoCs”. Springer 2010
Limits of dataflow analysis
q Conservative: Cannot produce wrong code
q For sound analysis: Suppose all paths can be taken (“flow insesitive”)
q Pointer access “*p = z” could potentially modify every variable x
q Analyze uses of the address operator “&”
q If not possible to reduce the set of affected variables suppose all can be modified
q Point-to and alias analysis are difficult!
19
© J. Castrillon. Parallel Programming
Dependence analysis
q A dependency between two statements s1 and s2
indicates that s2 cannot be executed before s1
q Read after write (RAW, true dependence): s1
defines a variable, then s2 reads it (see
reachable definitions)
s1: a = b + c;
s2: d = a * x;
q Write after write (WAW, output dependence): s1
defines a variable, then s2 defines it again
q Write after read (WAR, anti-dependence): s1 uses
a variable, then s2 defines it
s1: a = b - c;
s2: a = b * x;
s1: x = a - c;
s2: a = b * y;
q Control dependency: s1 controls whether or not s2
is executed
s1: if (x) goto L1
...
s2: L1: a = b * y;
20
© J. Castrillon. Parallel Programming
Dependence analysis in arrays
s1: A[i] = b - c;
...
s2: x = A[k] + d;
Whether or not there is RAW
dependency depends on i and k
q In general: analysis needed to reason about potential parallel schedules
Advertisement
q In arrays
q Impossible in the general case
q Possible, but difficult for special cases, i.e., afine index expressions
21
© J. Castrillon. Parallel Programming
Dependence analysis in arrays: Example
q Example
s0: for (i=2; i<=4; i++) {
s1: b[i] = a[3*i-5] + 2;
s2: a[2*i+1] = 100;}
Dare to put
#openmp parallel for?
q Is there a dependency between the statements within an iteration?
è Solve 3i-5 = 2i+1 è i = 6, but 6 ∉ [2,4] è No dependency!
q What about across iterations?
è We look for an integer solution to 3i1-5 = 2i2+1
è Pairs (i1 = 2k, i2 = 3k-3) are valid solutions
è Solution k = 2: (4,3) ∈ [2,4] è RAW on a[7] (written in it. 3, read in it. 4)
22
© J. Castrillon. Parallel Programming
Middle-end: Compiler optimization
q Optimizations: Enabled by analysis (control, dataflow)
q Classical optimizations
q Improve performance on single cores
q Expose more instruction-level parallelism (ILP)
q Newer optimizations
q Vectorize, use SIMD instructions
q Extract DLP and TLP (more on this later)
23
© J. Castrillon. Parallel Programming
Optimizations: Examples
q Loop invariants and semantic preserving transformations
for (i=0; i < k; i++)
{
?
z = x/y;
a = z * A[i];
}
z = x/y;
for (i=0; i < k; i++)
{
a = z * A[i];
}
What if y = 0 and
k <= 0?
q Improving ILP: Loop unrolling
for (i=0; i < N; i++) {
C[i] = A[i]*B[i];
}
for (i=1; i < N; i+=2) {
C[i-1] = A[i-1]*B[i-1];
C[i] = A[i]*B[i];
}
if (N%2) C[N-1] = A[N-1]*B[N-1];
24
© J. Castrillon. Parallel Programming
Backend (recall)
q Target dependent
Backend
25
© J. Castrillon. Parallel Programming
Backend phases
Optimized IR
Code
selection
asm
∞ regs
Register
allocation
asm
k regs
Scheduling
Machine code
q Code selection: Uses pattern matching
q Map IR code to assembly instructions (assume fixed code shape, i.e., IR is “optimal”)
q Combine operations, use addressing modes (assume infinite registers)
q Register allocation
q Assign registers to variables (change storage pattern, i.e., inserts load/stores)
q Scheduling
q Reorder operations to hide latencies, assume a fixed program (set of operations)
26
© J. Castrillon. Parallel Programming
Backend-phases: Relation to Multicore-compilers
q Both require a machine model
q Code selection
q Cost of operations (instructions)
q Resource usage (reservation tables in VLIWs)
q Register allocation
q How to intelligently map data: Goes beyond register file (caches, scratchpads, …)
q Scheduling (and mapping)
q Which functional unit executes what and when
q Works on dependence graphs (similar to task graphs – see later)
27
© J. Castrillon. Parallel Programming
Scheduling: Basics
Def. Scheduling is the reordering of instructions for a given target architecture
(constraints) to increase performance
q Scheduling in a compiler shares common principles with scheduling/mapping in
dataflow/task graphs
q Scheduling with resource constraints is NP complete: Need heuristics
q Basics
q Dependence graphs
q ASAP/ALAP
q List scheduling
q SW pipelining
28
© J. Castrillon. Parallel Programming
Static (compile-time) vs. Dynamic (run-time)
q Static (compile-time)
q Avoids extra hardware (e.g., pipeline-interlocks & out-of-order execution): VLIW vs.
Superscalar
q Can observe the entire program
q Has more time to optimize the schedule
q Dynamic (run-time)
q More precise: Some dependencies only known at run-time
A[i] = x;
y
= A[k];
ST [r1],r2
LD r3,[r4]
Static: i = k?
Dynamic: r1 = r4?
29
© J. Castrillon. Parallel Programming
Data dependency graph
Def. Given a basic-block BB, its dependency graph is an edge-weighted
directed acyclic graph G = (V,E,W) where nodes represent the instructions of BB
and there is an edge e = (u,v) ∈ E if due to dependencies, u has to execute
before v. The edge-weight we ∈ W models the latency of the architecture.
q Possible schedule: Any topological sort of the graph (more on this later)
q WAR dependency: Depending on target architecture, usually means “u cannot
execute after v”
30
© J. Castrillon. Parallel Programming
Data dependency graph: Example
t0 = t1 + t2
t1 = t0 + t1
t3 = t2 + t4
t0 = t1 + t0
t5 = t3 + t4
t6 = t2 + t7
t0 = t1 + t2
t0 = t1 + t2
t1 = t0 + t1
t1 = t0 + t1
t3 = t2 + t4
t0 = t1 + t0
t0 = t1 + t0
t3 = t2 + t4
t5 = t3 + t4
t5 = t3 + t4
t6 = t2 + t7
t6 = t2 + t7
Adapted from: http://web.stanford.edu/class/archive/cs/cs143/cs143.1128/
31
© J. Castrillon. Parallel Programming
Possible schedules: Topological sort
t3 = t2 + t4
t0 = t1 + t2
t6 = t2 + t7
t5 = t3 + t4
t1 = t0 + t1
t0 = t1 + t0
t3 = t2 + t4
t0 = t1 + t2
t5 = t3 + t4
t3 = t2 + t4
t0 = t1 + t2
t6 = t2 + t7
t1 = t0 + t1
t1 = t0 + t1
t0 = t1 + t0
t5 = t3 + t4
t6 = t2 + t7
t0 = t1 + t0
Which one is better?
Heuristics, e.g., schedule
first instructions with many
outgoing edges
32
© J. Castrillon. Parallel Programming
Adding edge weights: RISC processor
t3 = t2 + t4
3
t0 = t1 + t2
3
t6 = t2 + t7
3
t5 = t3 + t4
t1 = t0 + t1
3
t0 = t1 + t0
Option 1
1
2
3
4
5
6
7
8
9
10 11 12 13 14 15 16
t3 = t2 + t4 IF ID EX MM WB
t5 = t3 + t4
t0 = t1 + t2
t1 = t0 + t1
t0 = t1 + t0
t6 = t2 + t7
IF ID EX MM WB
IF ID EX MM WB
IF ID EX MM WB
IF ID EX MM WB
IF ID EX MM WB
33
© J. Castrillon. Parallel Programming
Adding edge weights: RISC processor
t3 = t2 + t4
3
t0 = t1 + t2
3
t6 = t2 + t7
3
t5 = t3 + t4
t1 = t0 + t1
3
t0 = t1 + t0
Option 2
1
2
3
4
5
6
7
8
9
10 11 12 13 14 15 16
t0 = t1 + t2
IF ID EX MM WB
t3 = t2 + t4
IF ID EX MM WB
Saved cycles
t6 = t2 + t7
t1 = t0 + t1
t5 = t3 + t4
t0 = t1 + t0
IF ID EX MM WB
IF ID EX MM WB
IF ID EX MM WB
IF ID EX MM WB
34
© J. Castrillon. Parallel Programming
Basic algorithms: ASAP
q ASAP: As soon as possible – schedule the earliest ignoring resource constraints
q Intuition: The earliest time depends on the predecessors and the latencies
Def. Given a dependency graph G = (V,E,W), ASAP(v) denotes the earliest
scheduling time for every v ∈ V and is defined as:
• ASAP(v) = 1 if pred(v) = ∅
• ASAP(v) = maxu∈pred(v)(ASAP(u) + w(u,v))
q Relevance: The ASAP time represents an absolute lower bound
35
© J. Castrillon. Parallel Programming
ASAP: Example (edge weights: 1)
a
e
t = 1
*
i
*
f
*
-
*
t = 2
t = 3
t = 4
t = 5
+
+
36
© J. Castrillon. Parallel Programming
h
b
g
d
c
*
*
*
-
*
-
*
Basic algorithms: ALAP
q ALAP: As late as possible – schedule the latest ignoring resource constraints
while keeping same duration as ASAP
Def. Given a dependency graph G = (V,E,W), the critical path length (Lc) is the
length of the paths in the graph with maximum edge weights
Def. Given a dependency graph G = (V,E,W), ALAP(v) for every v ∈ V is
defined as:
• ALAP(v) = Lc if succ(v) = ∅
• ALAP(v) = minu∈succ(v)(ALAP(u) – w(v,u))
37
© J. Castrillon. Parallel Programming
ASAP: Example (edge weights: 1)
a
e
t = 1
*
i
*
f
*
-
*
t = 2
t = 3
t = 4
t = 5
+
+
38
© J. Castrillon. Parallel Programming
h
b
g
d
c
*
*
*
-
*
-
*
ALAP: Example (edge weights: 1)
a
e
t = 1
*
i
*
f
*
-
*
+
t = 2
t = 3
t = 4
t = 5
Advertisement
h
b
g
d
c
-
*
*
+
*
*
-
*
39
© J. Castrillon. Parallel Programming
ASAP & ALAP
q Theoretical optimum: Serves to restrict search
q Critical path: All nodes for which ASAP(v) = ALAP(v)
q Mobility: ALAP(v) – ASAP(v)
q If every node v is scheduled within [ASAP(v), ALAP(v)] è Optimal schedule
q ASAP & ALAP: Ignore resource constraints
q Requires 4 ALUs!
40
© J. Castrillon. Parallel Programming
List scheduling
q Widespread heuristic algorithm for local scheduling, i.e, within basic-blocks
q Simple and efficient
q Idea: Build dependency graph and repeatedly
q Get ordered ready set of statements, i.e., statements whose predecessors are
already scheduled
q Select a node from the ready set (according to priority)
q Insert the node in the partial schedule (in the best possible slot)
41
© J. Castrillon. Parallel Programming
Algorithm
Proc ListSched(Graph G)
S = empty schedule
O = ∅
while O ≠ V
// Ordered nodes
R = ReadySet(G) // R = {v ∈ V; v ∉ O, pred(v)⊆O}
v = SelectNode(R) // Heuristic selection
S = Insert(S,v) // Insert v in the earliest possible time
O = O ∪{v}
return S
42
© J. Castrillon. Parallel Programming
List scheduling: Select heuristics
q In case |R| > 1: Good selection of a node to schedule is crucial
q Most famous ones
q Select node with the most successors (increases options)
q Select node on the dynamic critical path
q Many others, although less used
q Complexity: Dominated by the construction of the dependency graph O(|V|2)
43
© J. Castrillon. Parallel Programming
Example
1*
1*
2*
3*
4*
R
1-
7*
1+
5*
6*
3-
9*
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
*
+/-
+/-
*
1*
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
44
© J. Castrillon. Parallel Programming
Example
1*
2*
2*
3*
4*
R
1-
7*
1+
5*
6*
3-
9*
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
*
1*
*
2*
+/-
+/-
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
45
© J. Castrillon. Parallel Programming
Example
1*
2*
3*
3*
4*
R
1-
7*
1+
5*
6*
3-
9*
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
+/-
+/-
*
2*
*
1*
3*
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
46
© J. Castrillon. Parallel Programming
Example
1*
2*
3*
4*
4*
R
1-
7*
1+
5*
6*
3-
9*
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
+/-
+/-
*
1*
3*
*
2*
4*
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
47
© J. Castrillon. Parallel Programming
Example
1*
2*
3*
4*
1-
1-
7*
1+
6*
5*
R
3-
9*
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
*
1*
3*
*
2*
4*
+/-
+/-
1-
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
48
© J. Castrillon. Parallel Programming
Example
1*
2*
3*
4*
1-
7*
1+
6*
5*
R
3-
9*
2-
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
*
1*
3*
*
2*
4*
+/-
+/-
1-
2-
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
49
© J. Castrillon. Parallel Programming
Example
1*
2*
3*
4*
1-
7*
1+
6*
5*
R
3-
9*
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
*
1*
3*
5*
*
2*
4*
6*
+/-
+/-
1-
2-
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
50
© J. Castrillon. Parallel Programming
Example
1*
2*
3*
4*
1-
7*
1+
5*
6*
3-
9*
2-
8*
2+
q Assumptions
q ISA with 2 multipliers and 2 ALU (+/-)
q Instructions take 1 cycle
q Select heuristic: Dynamic critical path
Time
t = 1
t = 2
t = 3
t = 4
t = 5
t = 6
*
2*
4*
6*
Advertisement
8*
*
1*
3*
5*
7*
9*
+/-
+/-
1-
2-
3-
1
+
2
+
51
© J. Castrillon. Parallel Programming
VLIW example: TI C6201
int dotp(short a[], short b[])
{ int sum0, sum1, i;
sum0 = sum1 = 0;
for (i = 0; i < 100; i += 2) {
sum0 += a[i] * b[i];
sum1 += a[i+1] * b[i+1];
}
return sum0 + sum1;
}
Registers A0 - A15
Registers B0 - B15
1X
2X
S1
S2
D DL
SL
SL
DL
D
S1
S2
D S1
S2
L 1
S1
M1
D S1 S2
D1
S2
DS1
D2
S2
S1
D
S2
S1
D
DL
SL
SL
DL
D
S2
S1
M2
S2
L2
DDATA_I1
(load data)
DDATA_I2
(load data)
DDATA_O1
(store data)
DADR1
(address)
DADR2
(address)
DDATA_O2
(store data)
Cross Paths
40-bit Write Paths (8 MSBs)
40-bit Read Paths/Store Paths
LOAD
LOAD
LOAD
LOAD
sum0
0
5
+
1
5
*
2
sum1
0
5
*
2
5
+
1
© J. Castrillon. Parallel Programming
52
Dependency
graph
VLIW example: TI C6201 (2)
LOAD
LOAD
LOAD
LOAD
1X
Registers A0 - A15
Registers B0 - B15
2X
sum0
0
5
+
1
5
sum1
0
*
2
5
*
2
5
+
1
LDH .D2 ++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2 +B4(2),B5 || LDH .D1 +A4(2),A6
NOP 3
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP
ADD .L1 A6,A0,A0
|| ADD .S1 A5,A3,A3
1
53
© J. Castrillon. Parallel Programming
S1
S2
D DL
SL
SL
DL
D
S1
S2
D S1
S2
L 1
S1
M1
D S1 S2
D1
S2
DS1
D2
S2
S1
D
S2
S1
D
DL
SL
SL
DL
D
S2
S1
M2
S2
L2
DDATA_I1
(load data)
DDATA_I2
(load data)
DDATA_O1
(store data)
DADR1
(address)
DADR2
(address)
DDATA_O2
(store data)
Cross Paths
40-bit Write Paths (8 MSBs)
40-bit Read Paths/Store Paths
Using max. 2 parallel loads
3 more cycles delay before
Multiply
SW Pipelining
q Equivalent of instruction pipelining
Instructions
1
2
3
4
5
6
7
for statements in a loop
q Widely used for VLIW
q SW Pipeline for a loop
for (...)
A;
B;
C;
D;
}
A
B
C
D
t0 = t1 + t2
IF ID EX MM WB
t3 = t2 + t4
IF ID EX MM WB
t6 = t2 + t7
IF ID EX MM WB
Loop-carried
dependency
ILP Pipeline
Iteration
1
2
3
4
5
6
7
Iteration 1
Iteration 2
A B C D
A B C D
Iteration 3
Iteration 4
Different iterations
at same time
A B C D
A B C D
54
© J. Castrillon. Parallel Programming
Principle
q Analyze data dependencies inside a loop
q Unroll loop body to eliminate loop-carried dependencies (conceptually)
q Find kernel with operations that repeat
A
B A
C B A
D C B A
D C B
D C
D
A
B A
C B A
D C B A
D C B
D C
D
Loop prolog
Loop kernel
Loop epilog
55
© J. Castrillon. Parallel Programming
Problem overview
q Given a graph with operations,
q A description of instructions from the target architecture
q A set of reservation tables
q Find the kernel for software pipelining
q Which operations belong to kernel?
q How long is the kernel?
q Then: Generate code accordingly
56
© J. Castrillon. Parallel Programming
Example: TI C6201 (recall)
LOAD
LOAD
LOAD
LOAD
1X
Registers A0 - A15
Registers B0 - B15
2X
sum0
0
5
+
1
5
sum1
0
*
2
5
*
2
5
+
1
S1
S2
D DL
SL
SL
DL
D
S1
S2
D S1
S2
L 1
S1
M1
D S1 S2
D1
S2
DS1
D2
S2
S1
D
S2
S1
D
DL
SL
SL
DL
D
S2
S1
M2
S2
L2
DDATA_I1
(load data)
DDATA_I2
(load data)
DDATA_O1
(store data)
DADR1
(address)
DADR2
(address)
DDATA_O2
(store data)
Advertisement
Cross Paths
40-bit Write Paths (8 MSBs)
40-bit Read Paths/Store Paths
int dotp(short a[], short b[])
{ int sum0, sum1, i;
sum0 = sum1 = 0;
for (i = 0; i < 100; i += 2) {
sum0 += a[i] * b[i];
sum1 += a[i+1] * b[i+1];
}
return sum0 + sum1;
LDH .D2 ++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2 +B4(2),B5 || LDH .D1 +A4(2),A6
NOP 3
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP 1
ADD .L1 A6,A0,A0
|| ADD .S1 A5,A3,A3
}57
© J. Castrillon. Parallel Programming
Example: Adding control
++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2
LDH .D2 *+B4(2),B5
NOP 3
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP 1
ADD .L1
A6,A0,A0
|| LDH .D1 *+A4(2),A6
|| ADD .S1 A5,A3,A3
L: LDH .D2 ++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2 *+B4(2),B5
SUB .L2 B0,1,B0
[B0] B .S1 L
|| LDH .D1 *+A4(2),A6
NOP 1
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP 1
ADD .L1 A6,A0,A0 || ADD .S1 A5,A3,A3
Reservation
table: 1
Iteration
0
1
LDH LDH
LDH LDH
D1
D2
M1
M2
L1
L2
S1
S2
2
3
4
5
6
7
8
MPY MPY
New iteration can
be scheduled here
SUB
B
ADD
ADD
58
© J. Castrillon. Parallel Programming
Example: Finding kernel
++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2
LDH .D2 *+B4(2),B5
NOP 3
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP 1
ADD .L1
A6,A0,A0
|| LDH .D1 *+A4(2),A6
|| ADD .S1 A5,A3,A3
L: LDH .D2 ++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2 *+B4(2),B5
SUB .L2 B0,1,B0
[B0] B .S1 L
|| LDH .D1 *+A4(2),A6
NOP 1
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP 1
ADD .L1 A6,A0,A0 || ADD .S1 A5,A3,A3
Reservation
table: Fully
unrolled
D1
D2
M1
M2
L1
L2
S1
S2
0
2
3
1
4
LDH LDH LDH LDH LDH LDH LDH LDH LDH
LDH LDH LDH LDH LDH LDH LDH LDH LDH
MPY
MPY
8
5
6
7
MPY
MPY
Kernel repeats
from cycle 7
onwards
SUB
SUB
SUB
B
B
B
ADD
SUB
ADD
Prolog
59
© J. Castrillon. Parallel Programming
Example: Code generation
++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2
LDH .D2 *+B4(2),B5
NOP 3
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP 1
ADD .L1
A6,A0,A0
|| LDH .D1 *+A4(2),A6
|| ADD .S1 A5,A3,A3
SW pipelining: 4.5x speedup
8
7
L: LDH .D2 ++B4(4),B6 || LDH .D1 ++A4(4),A5
LDH .D2 *+B4(2),B5
SUB .L2 B0,1,B0
[B0] B .S1 L
|| LDH .D1 *+A4(2),A6
NOP 1
MPY .M1X B6,A5,A5
MPY .M1X B5,A6,A6
NOP 1
ADD .L1 A6,A0,A0 || ADD .S1 A5,A3,A3
Jump executed after 5 cycles è After
two iterations!
// Prolog
L3:
LDH LDH
LDH LDH
MPY
MPY
ADD
SUB
ADD
B
D1
D2
M1
M2
L1
L2
S1
S2
60
ADD .L2 B6,B5,B5 || MPY .M2X B4,A0,B6 || [ B0] B .S1 L3
|| LDH .D2 +B7(2),B4 || LDH .D1 +A3(2),A0
ADD .L1 A5,A4,A4 || MPY .M1X B4,A0,A5 || [ B0] SUB .L2 B0,1,B0
|| LDH .D2 ++B7(4),B4 || LDH .D1 ++A3(4),A0
// Epilog
© J. Castrillon. Parallel Programming
Algorithm sketch
q Optimal SW pipelining: NP complete è Heuristic
q Iterative modulo scheduling (Rau, 1994)
q Search for kernel of length ∆
q Start growing ∆ until it is possible to build a schedule
q Starting point for ∆: Obtaining “minimal ∆” also NP complete
q Use estimation based on the target architecture and the properties of the
dependency graph
61
© J. Castrillon. Parallel Programming
Modulo scheduling
q Why modulo scheduling
q When trying to fit a computation
within a kernel of length ∆, move
statements across iterations
q Example
§ 2-slot VLIW
§ ∆ = 3
§ load delay: 4
Respect dependency: Schedule
addition after t > 5 cycles
è Place in kernel: t mod ∆
Slot 1
Fi = A[i]
Slot 1
Fi = A[i]
Slot 1
Fi = A[i]
0
1
2
0
1
2
0
1
2
Slot 2
Xi = Fi+...
✗
Slot 2
Xi-1 = Fi-1+…
Slot 2
Y = …
Xi-2 = Fi-2+…
62
© J. Castrillon. Parallel Programming
Agenda
09:00 AM
12:30 PM
14:00 PM
LB1-I
HO-I
LB2-I
break
LB2-I (cont)
break
LB2-II
HO-II
LB3-I
break
LB3-II
HO-III
LB4/Q&A
LB1-I
17:30 PM
63
© J. Castrillon. Parallel Programming
Auto-parallelizing compilers
64
© J. Castrillon. Parallel Programming
Auto-parallelizing: The idea
Sequential
code
Compiler
Parallel code
(OpenMP, Pthreads,…)
q Keep sequential programming: It’s easy and widespread
q Let the compiler do all the work
q Analyze: instrument, profile, trace memory, estimate performance, …
q Parallelize: exploit locality, identify parallel regions, insert synchronization, …
q Generate correct code (deal with APIs complexity)
65
© J. Castrillon. Parallel Programming
66
© J. Castrillon. Parallel Programming
Analysis
q Instrumentation
q Insert code into application
q Collect information at runtime (profile, memory trace, …)
67
© J. Castrillon. Parallel Programming
Analysis: Example
q Information collected after running instrumented application
68
© J. Castrillon. Parallel Programming
Analysis: Memory traces
q Memory traces: Important for
q Dynamic dependence analysis: unsafe, but often more insightful than static analysis
q Locality analysis
Good temporal
and spatial
x
e
d
n
i
y
a
r
r
A
Bad temporal
Bad spatial
locality
Time
69
© J. Castrillon. Parallel Programming
Analysis: Performance estimation
q To reason about parallel execution
q Execution of computation on multiple resources
q Costs of communication and synchronization
q Methods (some details in lecture 4)
q Table-based on IR
q Emulation of target-specific transformation at IR level
q Worst-case-execution time (WCET) analysis
70
© J. Castrillon. Parallel Programming
Improving locality and extracting parallelism
q Locality
q Important for cache utilization
q Loop transformations (more on this below)
q Extracting parallelism
q Graph partitioning:
q Pattern matching: identify known parallel patterns (TLP, DLP, PLP, reduction, …)
identify threads working on “almost” different data sets
71
© J. Castrillon. Parallel Programming
Metrics for partitioning
q Load distribution
q It does not make sense to create a thread that does almost nothing
q Synchronization
q Reduce the amount of waiting (related to a good load balance)
q Communication
q Should be small: Min ratio-cut in graphs
72
© J. Castrillon. Parallel Programming
Parallelism patterns: Graphs and metrics
q Example TLP
q Estimated performance depends on the kind and location of the dependency
73
© J. Castrillon. Parallel Programming
Parallelism patterns: Graphs and metrics (2)
q Similar for DLP and PLP
q DLP: Depends on the cost for spawning workers (e.g., fix OpenMP threads)
q PLP: Perform pipeline balancing
74
© J. Castrillon. Parallel Programming
Example: Generating OpenMP
q EP: Application in the NAS parallel benchmark
q Autom...