Академический Документы
Профессиональный Документы
Культура Документы
Chapter 4
Data-Level Parallelism in
Vector, SIMD, and GPU
Architectures
Vector architectures
Multimedia extensions
Graphics processor units
Classes of Computers
Flynns Taxonomy
No commercial implementation
Tightly-coupled MIMD
Loosely-coupled MIMD
Copyright 2012, Elsevier Inc. All rights reserved.
Introduction
Introduction
Vector architectures
SIMD extensions
Graphics Processor Units (GPUs)
Introduction
SIMD Parallelism
Figure 4.1 Potential speedup via parallelism from MIMD, SIMD, and both MIMD and SIMD over time for
x86 computers. This figure assumes that two cores per chip for MIMD will be added every two years and the
number of operations for SIMD will double every four years.
Basic idea:
Vector Architectures
Vector Architectures
Fully pipelined
Data and control hazards are detected
Vector Architectures
VMIPS
Fully pipelined
One word per clock cycle after initial latency
Scalar registers
32 general-purpose registers
32 floating-point registers
Copyright 2012, Elsevier Inc. All rights reserved.
Figure 4.2 The basic structure of a vector architecture, VMIPS. This processor has a scalar architecture just like MIPS. There are
also eight 64-element vector registers, and all the functional units are vector functional units. This chapter defines special vector
instructions for both arithmetic and memory accesses. The figure shows vector units for logical and integer operations so that
VMIPS looks like a standard vector processor that usually includes these units; however, we will not be discussing these units. The
vector and scalar registers have a significant number of read and write ports to allow multiple simultaneous vector operations. A set
of crossbar switches (thick gray lines) connects these ports to the inputs and outputs of the vector functional units.
Copyright 2011, Elsevier Inc. All rights Reserved.
Vector Architectures
VMIPS Instructions
Loop:
L.D
DADDIU
L.D
MUL.D
L.D
ADD.D
S.D
DADDIU
DADDIU
SUBBU
BNEZ
F0,a
R4,Rx,#512
F2,0(Rx )
F2,F2,F0
F4,0(Ry)
F4,F2,F2
F4,9(Ry)
Rx,Rx,#8
Ry,Ry,#8
R20,R4,Rx
R20,Loop
; load scalar a
; last address to load
; load X[i]
; a x X[i]
; load Y[i]
; a x X[i] + Y[i]
; store into Y[i]
; increment index to X
; increment index to Y
; compute bound
; check if done
Vector Architectures
10
Vector Architectures
Convoy
11
Chaining
Vector Architectures
Chimes
Chime
12
LV
MULVS.D
LV
ADDVV.D
SV
Convoys:
1
LV
2
LV
3
SV
V1,Rx
V2,V1,F0
V3,Ry
V4,V2,V3
Ry,V4
;load vector X
;vector-scalar multiply
;load vector Y
;add two vectors
;store the sum
Vector Architectures
Example
MULVS.D
ADDVV.D
13
Start up time
Vector Architectures
Challenges
Optimizations:
14
Vector Architectures
Multiple Lanes
15
Vector Architectures
low = 0;
VL = (n % MVL); /*find odd-size piece using modulo op % */
for (j = 0; j <= (n/MVL); j=j+1) { /*outer loop*/
for (i = low; i < (low+VL); i=i+1) /*runs for length VL*/
Y[i] = a * X[i] + Y[i] ; /*main operation*/
low = low + VL; /*start of next vector*/
VL = MVL; /*reset the length to maximum vector length*/
}
16
Consider:
for (i = 0; i < 64; i=i+1)
if (X[i] != 0)
X[i] = X[i] Y[i];
Use vector mask register to disable elements (if
conversion):
LV
LV
L.D
SNEVS.D
SUBVV.D
SV
V1,Rx
V2,Ry
F0,#0
V1,F0
V1,V1,V2
Rx,V1
Vector Architectures
17
Vector Architectures
Memory Banks
Example:
32x6=192 accesses,
15/2.1677 processor cycles
1344!
Copyright 2012, Elsevier Inc. All rights reserved.
18
Consider:
for (i = 0; i < 100; i=i+1)
for (j = 0; j < 100; j=j+1) {
A[i][j] = 0.0;
for (k = 0; k < 100; k=k+1)
A[i][j] = A[i][j] + B[i][k] * D[k][j];
}
Vector Architectures
Stride
Should it be GCD?
19
Example:
8 memory banks with a bank busy time of 6 cycles and a total
memory latency of 12 cycles. How long will it take to complete a 64element vector load with a stride of 1? With a stride of 32?
Answer:
Vector Architectures
Stride
20
Vector Architectures
Scatter-Gather
21
Vector Architectures
22
Optimizations:
Multiple Lanes: > 1 element per clock cycle
Vector Length Registers: Non-64 wide vectors
Vector Mask Registers: IF statements in vector code
Memory Banks: Memory system optimizations to
support vector processors
Stride: Multiple dimensional matrices
Scatter-Gather: Sparse matrices
Programming Vector Architectures: Program
structures affecting performance
Vector Architectures
23
Vector Architectures
In-class exercise
Asumme that the processor runs at 700 MHz and has a maximum
vector length of 64.
A.
B.
C.
What is the arithmetic intensity of this kernel (i.e., the ratio of floating-point
operations per byte of memory accessed)?
Convert this loop into VMIPS assembly code using strip mining.
Assuming chaining and a single memory pipeline, how many chimes are
required?
24
A.
B.
This code reads four floats and writes two floats for every six FLOPs, so the
arithmetic intensity = 6/6 = 1.
Assume MVL = 64 300 mod 64 = 44
Vector Architectures
In-class exercise
25
C.
Identify convoys:
1. mulvv.s
lv
# a_re * b_re
# (assume already loaded),
# load a_im
2. lv
mulvv.s
# load b_im, a_im * b_im
3. subvv.s
sv
# subtract and store c_re
4. mulvv.s
lv
# a_re * b_re,
# load next a_re vector
5. mulvv.s
lv
# a_im * b_re,
# load next b_re vector
6. addvv.s
sv
Vector Architectures
In-class exercise
6 chimes
26
SIMD Extensions
27
Implementations:
SIMD Implementations
28
Example DXPY:
L.D
MOV
MOV
MOV
DADDIU
Loop:
MUL.4D
L.4D
ADD.4D
S.4D
DADDIU
DADDIU
DSUBU
BNEZ
F0,a
F1, F0
F2, F0
F3, F0
R4,Rx,#512
L.4D F4,0[Rx]
F4,F4,F0
F8,0[Ry]
F8,F8,F4
F8,0[Ry]
Rx,Rx,#32
Ry,Ry,#32
R20,R4,Rx
R20,Loop
;load scalar a
;copy a into F1 for SIMD MUL
;copy a into F2 for SIMD MUL
;copy a into F3 for SIMD MUL
;last address to load
;load X[i], X[i+1], X[i+2], X[i+3]
;aX[i],aX[i+1],aX[i+2],aX[i+3]
;load Y[i], Y[i+1], Y[i+2], Y[i+3]
;aX[i]+Y[i], ..., aX[i+3]+Y[i+3]
;store into Y[i], Y[i+1], Y[i+2], Y[i+3]
;increment index to X
;increment index to Y
;compute bound
;check if done
29
Basic idea:
Plot peak floating-point throughput as a function of
arithmetic intensity
Ties together floating-point performance and memory
performance for a target machine
Arithmetic intensity
Floating-point operations per byte read
30
Examples
31
32
33
Differences:
No scalar processor
Uses multithreading to hide memory latency
Has many functional units, as opposed to a few
deeply pipelined units like a vector processor
Copyright 2012, Elsevier Inc. All rights reserved.
34
Example
35
36
Figure 4.15 Floor plan of the Fermi GTX 480 GPU. This diagram shows 16 multithreaded SIMD Processors. The
Thread Block Scheduler is highlighted on the left. The GTX 480 has 6 GDDR5 ports, each 64 bits wide, supporting up
to 6 GB of capacity. The Host Interface is PCI Express 2.0 x 16. Giga Thread is the name of the scheduler that
distributes thread blocks to Multiprocessors, each of which has its own SIMD Thread Scheduler.
37
Terminology
32 SIMD lanes
Wide and shallow compared to vector processors
Copyright 2012, Elsevier Inc. All rights reserved.
38
Figure 4.16 Scheduling of threads of SIMD instructions. The scheduler selects a ready thread of SIMD instructions and
issues an instruction synchronously to all the SIMD Lanes executing the SIMD thread. Because threads of SIMD instructions
are independent, the scheduler may select a different SIMD thread each time.
39
Example
40
Figure 4.14 Simplified block diagram of a Multithreaded SIMD Processor. It has 16 SIMD lanes. The SIMD Thread
Scheduler has, say, 48 independentthreads of SIMD instructions that it schedules with a table of 48 PCs.
41
shl.s32
R8, blockIdx, 9 ; Thread Block ID * Block size (512 or 29)
add.s32
R8, R8, threadIdx ; R8 = i = my CUDA thread ID
ld.global.f64 RD0, [X+R8]
; RD0 = X[i]
ld.global.f64 RD2, [Y+R8]
; RD2 = Y[i]
mul.f64 R0D, RD0, RD4
; Product in RD0 = RD0 * RD4 (scalar a)
add.f64 R0D, RD0, RD2
; Sum in RD0 = RD0 + RD2 (Y[i])
st.global.f64 [Y+R8], RD0
; Y[i] = sum (X[i]*a + Y[i])
Copyright 2012, Elsevier Inc. All rights reserved.
42
Conditional Branching
Act as barriers
Pops stack
43
if (X[i] != 0)
X[i] = X[i] Y[i];
else X[i] = Z[i];
ld.global.f64
setp.neq.s32
@!P1, bra
RD0, [X+R8]
P1, RD0, #0
ELSE1, *Push
; RD0 = X[i]
; P1 is predicate register 1
; Push old mask, set new mask bits
; if P1 false, go to ELSE1
ld.global.f64
RD2, [Y+R8]
; RD2 = Y[i]
sub.f64
RD0, RD0, RD2
; Difference in RD0
st.global.f64
[X+R8], RD0
; X[i] = RD0
@P1, bra
ENDIF1, *Comp
; complement mask bits
; if P1 true, go to ENDIF1
ELSE1:
ld.global.f64 RD0, [Z+R8]
; RD0 = Z[i]
st.global.f64 [X+R8], RD0
; X[i] = RD0
ENDIF1: <next instruction>, *Pop
; pop to restore old mask
Example
44
45
Figure 4.18 GPU Memory structures. GPU Memory is shared by all Grids (vectorized loops), Local Memory is shared by
all threads of SIMD instructions within a thread block (body of a vectorized loop), and Private Memory is private to a single
CUDA Thread.
46
47
Figure 4.19 Block Diagram of Fermis Dual SIMD Thread Scheduler. Compare this design to the single
SIMD Thread Design in Figure 4.16.
48
49
Loop-carried dependence
Example 1:
for (i=999; i>=0; i=i-1)
x[i] = x[i] + s;
Loop-Level Parallelism
No loop-carried dependence
50
Example 2:
for (i=0; i<100; i=i+1) {
A[i+1] = A[i] + C[i]; /* S1 */
B[i+1] = B[i] + A[i+1]; /* S2 */
}
Loop-Level Parallelism
51
Example 3:
for (i=0; i<100; i=i+1) {
A[i] = A[i] + B[i]; /* S1 */
B[i+1] = C[i] + D[i]; /* S2 */
}
S1 uses value computed by S2 in previous iteration but dependence
is not circular so loop is parallel
Transform to:
A[0] = A[0] + B[0];
for (i=0; i<99; i=i+1) {
B[i+1] = C[i] + D[i];
A[i+1] = A[i+1] + B[i+1];
}
B[100] = C[99] + D[99];
Loop-Level Parallelism
52
Example 4:
for (i=0;i<100;i=i+1) {
A[i] = B[i] + C[i];
D[i] = A[i] * E[i];
}
No loop-carried dependence
Example 5:
for (i=1;i<100;i=i+1) {
Y[i] = Y[i-1] + Y[i];
}
Loop-Level Parallelism
53
Finding dependencies
Store to a x i + b, then
Load from c x i + d
i runs from m to n
Dependence exists if:
54
GCD test:
Example:
for (i=0; i<100; i=i+1) {
X[2*i+3] = X[2*i] * 5.0;
}
Finding dependencies
55
Example 2:
for (i=0; i<100; i=i+1) {
Y[i] = X[i] / c; /* S1 */
X[i] = X[i] + c; /* S2 */
Z[i] = Y[i] + c; /* S3 */
Y[i] = c - Y[i]; /* S4 */
}
Finding dependencies
56
Reduction Operation:
for (i=9999; i>=0; i=i-1)
sum = sum + x[i] * y[i];
Transform to
for (i=9999; i>=0; i=i-1)
sum [i] = x[i] * y[i];
for (i=9999; i>=0; i=i-1)
finalsum = finalsum + sum[i];
Do on p processors:
for (i=999; i>=0; i=i-1)
finalsum[p] = finalsum[p] + sum[i+1000*p];
Note: assumes associativity!
Copyright 2012, Elsevier Inc. All rights reserved.
Reductions
57