from shader code to a teraflop: how shader cores work...memory pre-fetcher data cache (a big one)...

53
Beyond Programmable Shading: Fundamentals From Shader Code to a Teraflop: How Shader Cores Work Kayvon Fatahalian Stanford University

Upload: others

Post on 02-Jan-2021

5 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

From Shader Code to a Teraflop: How Shader Cores Work

Kayvon Fatahalian Stanford University

Page 2: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 2

This talk

•  Three key concepts behind how modern architectures run “shader” code

•  Knowing these concepts will help you: 1.  Understand space of GPU shader core (and

throughput CPU processing core) designs

2.  Optimize shaders/compute kernels

3.  Establish intuition: what workloads might benefit from the design of these architectures?

Page 3: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

What’s in a GPU?

3

Shader Core

Shader Core

Shader Core

Shader Core

Shader Core

Shader Core

Shader Core

Shader Core

Tex

Tex

Tex

Tex

Input Assembly

Rasterizer

Output Blend

Video Decode

Work Distributor

Heterogeneous chip multi-processor (highly tuned for graphics)

HW or

SW?

Page 4: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

A diffuse reflectance shader

4

sampler mySamp; 

Texture2D<float3> myTex; 

float3 lightDir; 

float4 diffuseShader(float3 norm, float2 uv) 

  float3 kd; 

  kd = myTex.Sample(mySamp, uv); 

  kd *= clamp( dot(lightDir, norm), 0.0, 1.0); 

  return float4(kd, 1.0);    

}  

Independent, but no explicit parallelism

Page 5: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Compile shader

5

sampler mySamp; 

Texture2D<float3> myTex; 

float3 lightDir; 

float4 diffuseShader(float3 norm, float2 uv) 

  float3 kd; 

  kd = myTex.Sample(mySamp, uv); 

  kd *= clamp ( dot(lightDir, norm), 0.0, 1.0 ); 

  return float4(kd, 1.0);    

}  

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

1 unshaded fragment input record

1 shaded fragment output record

Page 6: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Execute shader

6

ALU (Execute)

Fetch/ Decode

Execution Context

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

Page 7: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Execute shader

7

ALU (Execute)

Fetch/ Decode

Execution Context

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

Page 8: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Execute shader

8

ALU (Execute)

Fetch/ Decode

Execution Context

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

Page 9: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Execute shader

9

ALU (Execute)

Fetch/ Decode

Execution Context

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

Page 10: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Execute shader

10

ALU (Execute)

Fetch/ Decode

Execution Context

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

Page 11: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Execute shader

11

ALU (Execute)

Fetch/ Decode

Execution Context

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

Page 12: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

CPU-“style” cores

12

ALU (Execute)

Fetch/ Decode

Execution Context

Out-of-order control logic

Fancy branch predictor

Memory pre-fetcher

Data Cache (A big one)

Page 13: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Slimming down

13

ALU (Execute)

Fetch/ Decode

Execution Context

Idea #1:

Remove components that help a single instruction stream run fast

Page 14: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Two cores (two fragments in parallel)

14

ALU (Execute)

Fetch/ Decode

Execution Context

ALU (Execute)

Fetch/ Decode

Execution Context

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

fragment 1

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

fragment 2

Page 15: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Four cores (four fragments in parallel)

15

ALU (Execute)

Fetch/ Decode

Execution Context

ALU (Execute)

Fetch/ Decode

Execution Context

ALU (Execute)

Fetch/ Decode

Execution Context

ALU (Execute)

Fetch/ Decode

Execution Context

Page 16: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Sixteen cores (sixteen fragments in parallel)

16

ALU ALU

ALU ALU

ALU ALU

ALU ALU

ALU ALU

ALU ALU

ALU ALU

ALU ALU

16 cores = 16 simultaneous instruction streams

Page 17: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Instruction stream coherence

17

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

But… many fragments should be able to share an instruction stream!

Page 18: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Recall: simple processing core

18

Fetch/ Decode

ALU (Execute)

Execution Context

Page 19: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Add ALUs

19

Fetch/ Decode

Idea #2:

Amortize cost/complexity of managing an instruction stream across many ALUs

ALU 1 ALU 2 ALU 3 ALU 4

ALU 5 ALU 6 ALU 7 ALU 8

SIMD processing Ctx Ctx Ctx Ctx

Ctx Ctx Ctx Ctx

Shared Ctx Data

Page 20: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Modifying the shader

20

<diffuseShader>: 

sample r0, v4, t0, s0 

mul  r3, v0, cb0[0] 

madd r3, v1, cb0[1], r3 

madd r3, v2, cb0[2], r3 

clmp r3, r3, l(0.0), l(1.0) 

mul  o0, r0, r3 

mul  o1, r1, r3 

mul  o2, r2, r3 

mov  o3, l(1.0) 

Original compiled shader:

Fetch/ Decode

Ctx Ctx Ctx Ctx

Ctx Ctx Ctx Ctx

Shared Ctx Data

ALU 1 ALU 2 ALU 3 ALU 4

ALU 5 ALU 6 ALU 7 ALU 8

Processes one fragment using scalar ops on scalar registers

Page 21: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Modifying the shader

21

Fetch/ Decode

<VEC8_diffuseShader>: 

VEC8_sample vec_r0, vec_v4, t0, vec_s0 

VEC8_mul  vec_r3, vec_v0, cb0[0] 

VEC8_madd vec_r3, vec_v1, cb0[1], vec_r3 

VEC8_madd vec_r3, vec_v2, cb0[2], vec_r3 

VEC8_clmp vec_r3, vec_r3, l(0.0), l(1.0) 

VEC8_mul  vec_o0, vec_r0, vec_r3 

VEC8_mul  vec_o1, vec_r1, vec_r3 

VEC8_mul  vec_o2, vec_r2, vec_r3 

VEC8_mov  vec_o3, l(1.0) 

Ctx Ctx Ctx Ctx

Ctx Ctx Ctx Ctx

Shared Ctx Data Processes 8 fragments using vector ops on vector registers

ALU 1 ALU 2 ALU 3 ALU 4

ALU 5 ALU 6 ALU 7 ALU 8

New compiled shader:

Page 22: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Modifying the shader

22

Fetch/ Decode

<VEC8_diffuseShader>: 

VEC8_sample vec_r0, vec_v4, t0, vec_s0 

VEC8_mul  vec_r3, vec_v0, cb0[0] 

VEC8_madd vec_r3, vec_v1, cb0[1], vec_r3 

VEC8_madd vec_r3, vec_v2, cb0[2], vec_r3 

VEC8_clmp vec_r3, vec_r3, l(0.0), l(1.0) 

VEC8_mul  vec_o0, vec_r0, vec_r3 

VEC8_mul  vec_o1, vec_r1, vec_r3 

VEC8_mul  vec_o2, vec_r2, vec_r3 

VEC8_mov  vec_o3, l(1.0) 

Ctx Ctx Ctx Ctx

Ctx Ctx Ctx Ctx

Shared Ctx Data

2 3 1 4

6 7 5 8

ALU 1 ALU 2 ALU 3 ALU 4

ALU 5 ALU 6 ALU 7 ALU 8

Page 23: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

128 fragments in parallel

23 = 16 simultaneous instruction streams

16 cores = 128 ALUs

Page 24: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

128 [ ] in parallel

24

vertices / fragments primitives

CUDA threads OpenCL work items

compute shader threads

primitives

vertices

fragments

Page 25: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 25

But what about branches?

ALU 1 ALU 2 . . . ALU 8 . . . Time

(clocks)

2 ... 1 ... 8

if (x > 0) { 

} else { 

<unconditional shader code> 

<resume unconditional shader code> 

y = pow(x, exp); 

y *= Ks; 

refl = y + Ka;   

x = 0;  

refl = Ka;   

Page 26: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 26

But what about branches?

ALU 1 ALU 2 . . . ALU 8 . . . Time

(clocks)

2 ... 1 ... 8

if (x > 0) { 

} else { 

<unconditional shader code> 

<resume unconditional shader code> 

y = pow(x, exp); 

y *= Ks; 

refl = y + Ka;   

x = 0;  

refl = Ka;   

T T T F F F F F

Page 27: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 27

But what about branches?

ALU 1 ALU 2 . . . ALU 8 . . . Time

(clocks)

2 ... 1 ... 8

if (x > 0) { 

} else { 

<unconditional shader code> 

<resume unconditional shader code> 

y = pow(x, exp); 

y *= Ks; 

refl = y + Ka;   

x = 0;  

refl = Ka;   

T T T F F F F F

Not all ALUs do useful work! Worst case: 1/8 performance

Page 28: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 28

But what about branches?

ALU 1 ALU 2 . . . ALU 8 . . . Time

(clocks)

2 ... 1 ... 8

if (x > 0) { 

} else { 

<unconditional shader code> 

<resume unconditional shader code> 

y = pow(x, exp); 

y *= Ks; 

refl = y + Ka;   

x = 0;  

refl = Ka;   

T T T F F F F F

Page 29: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Clarification

29

•  Option 1: Explicit vector instructions –  Intel/AMD x86 SSE, Intel Larrabee

•  Option 2: Scalar instructions, implicit HW vectorization –  HW determines instruction stream sharing across ALUs

(amount of sharing hidden from software) –  NVIDIA GeForce (“SIMT” warps), AMD Radeon architectures

SIMD processing does not imply SIMD instructions

In practice: 16 to 64 fragments share an instruction stream

Page 30: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 30

Stalls!

Texture access latency = 100’s to 1000’s of cycles

We’ve removed the fancy caches and logic that helps avoid stalls.

Stalls occur when a core cannot run the next instruction because of a dependency on a previous operation.

Page 31: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 31

But we have LOTS of independent fragments.

Idea #3: Interleave processing of many fragments on a single core to

avoid stalls caused by high latency operations.

Page 32: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

32

Hiding shader stalls Time

(clocks) Frag 1 … 8

Fetch/ Decode

Ctx Ctx Ctx Ctx

Ctx Ctx Ctx Ctx

Shared Ctx Data

ALU ALU ALU ALU

ALU ALU ALU ALU

Page 33: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 33

Hiding shader stalls Time

(clocks)

Fetch/ Decode

ALU ALU ALU ALU

ALU ALU ALU ALU

1 2

3 4

1 2 3 4

Frag 1 … 8 Frag 9… 16 Frag 17 … 24 Frag 25 … 32

Page 34: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 34

Hiding shader stalls Time

(clocks)

Stall

Runnable

1 2 3 4

Frag 1 … 8 Frag 9… 16 Frag 17 … 24 Frag 25 … 32

Page 35: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 35

Hiding shader stalls Time

(clocks)

Stall

Runnable

1 2 3 4

Frag 1 … 8 Frag 9… 16 Frag 17 … 24 Frag 25 … 32

Page 36: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 36

Hiding shader stalls Time

(clocks)

1 2 3 4

Stall

Stall

Stall

Stall

Runnable

Runnable

Runnable

Frag 1 … 8 Frag 9… 16 Frag 17 … 24 Frag 25 … 32

Page 37: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 37

Throughput! Time

(clocks)

Stall

Runnable

2 3 4

Frag 1 … 8 Frag 9… 16 Frag 17 … 24 Frag 25 … 32

Done!

Stall

Runnable

Done!

Stall

Runnable

Done!

Stall

Runnable

Done!

1

Increase run time of one group To maximum throughput of many groups

Start

Start

Start

Page 38: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 38

Storing contexts

Fetch/ Decode

ALU ALU ALU ALU

ALU ALU ALU ALU

Pool of context storage

32KB

Page 39: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 39

Twenty small contexts

Fetch/ Decode

ALU ALU ALU ALU

ALU ALU ALU ALU

1 2 3 4 5

6 7 8 9 10

11 15 12 13 14

16 20 17 18 19

(maximal latency hiding ability)

Page 40: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 40

Twelve medium contexts

Fetch/ Decode

ALU ALU ALU ALU

ALU ALU ALU ALU

1 2 3 4

5 6 7 8

9 10 11 12

Page 41: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 41

Four large contexts

Fetch/ Decode

ALU ALU ALU ALU

ALU ALU ALU ALU

4 3

1 2

(low latency hiding ability)

Page 42: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 42

My chip!

16 cores

8 mul-add ALUs per core (128 total)

16 simultaneous instruction streams

64 concurrent (but interleaved) instruction streams

512 concurrent fragments

= 256 GFLOPs (@ 1GHz)

Page 43: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 43

My “enthusiast” chip!

32 cores, 16 ALUs per core (512 total) = 1 TFLOP (@ 1 GHz)

Page 44: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 44

Summary: three key ideas

1.  Use many “slimmed down cores” to run in parallel

2.  Pack cores full of ALUs (by sharing instruction stream across groups of fragments)

–  Option 1: Explicit SIMD vector instructions –  Option 2: Implicit sharing managed by hardware

3.  Avoid latency stalls by interleaving execution of many groups of fragments

–  When one group stalls, work on another group

Page 45: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 45

Thank you

Additional information on “supplemental slides” and at http://graphics.stanford.edu/~kayvonf/gblog

Page 46: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals 46

Supplemental slides •  Disclaimer #1: the following slides describe “how I think”

about the NVIDIA GTX 280, ATI Radeon 4870, and Intel Larrabee GPUs

•  Disclaimer #2: Many other factors play a role in actual chip performance

•  These slides use the same hand-wavy notion of “core” as I established in the talk

•  Remember: you can substitute the term vertex, primitive, CUDA thread, compute shader thread, or OpenCL work item, for “fragment” (pick your favorite language)

Page 47: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

GPU block diagram key

47

= single “physical” instruction stream fetch/decode (functional unit control)

= SIMD programmable functional unit (FU), control shared with other functional units. This functional unit may contain multiple 32-bit “ALUs”

= execution context storage

= fixed function unit

= 32-bit mul-add unit = 32-bit multiply unit

Page 48: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

NVIDIA GeForce GTX 280 •  NVIDIA-speak:

–  240 stream processors –  “SIMT execution” (automatic HW-managed sharing of instruction stream)

•  Generic speak: –  30 processing cores –  8 SIMD functional units per core –  1 mul-add (2 flops) + 1 mul per functional units (3 flops/clock) –  Best case: 240 mul-adds + 240 muls per clock –  1.3 GHz clock –  30 * 8 * (2 + 1) * 1.3 = 933 GFLOPS

•  Mapping data-parallelism to chip: –  Instruction stream shared across 32 fragments (16 for vertices) –  8 fragments run on 8 SIMD functional units in one clock –  Instruction repeated for 4 clocks (2 clocks for vertices)

48

Page 49: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

NVIDIA GeForce GTX 280

49

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Zcull/Clip/Rast Output Blend Work Distributor

… … …

… … …

… … …

… … …

… … …

… … …

… … …

… … …

… … …

… … …

Page 50: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

ATI Radeon 4870 •  AMD/ATI-speak:

–  800 stream processors –  Automatic HW-managed sharing of scalar instruction stream (like “SIMT”)

•  Generic speak: –  10 processing cores –  16 SIMD functional units per core –  5 mul-adds per functional unit (5 * 2 =10 flops/clock) –  Best case: 800 mul-adds per clock –  750 MHz clock –  10 * 16 * 5 * 2 * .75 = 1.2 TFLOPS

•  Mapping data-parallelism to chip: –  Instruction stream shared across 64 fragments –  16 fragments run on 16 SIMD functional units in one clock –  Instruction repeated for 4 consecutive clocks

50

Page 51: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

ATI Radeon 4870

51

Zcull/Clip/Rast Output Blend Work Distributor

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Tex

Page 52: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Intel Larrabee •  Intel speak:

–  We won’t say anything about the number of cores or clock rate of cores –  Explicit 16-wide vector ISA –  If 1GHz clock (then 1 core = 1 LRB unit = 32 GFLOPS from paper)

•  Generic speak: –  X processing cores –  16 SIMD functional units per core –  1 mul-add per functional unit (2 flops/clock) –  Best case: 16X mul-adds per clock –  If you wanted to compete with current GPUs (~ 1 TFLOP), you need about 32

Larrabee units •  32 * 16 * 2 = 1 TFLOP

•  Mapping data-parallelism to chip: –  Compilation options determine instruction stream sharing across fragments (a

multiple of 16) –  16 fragments run on 16 SIMD functional units in one clock

52

Page 53: From Shader Code to a Teraflop: How Shader Cores Work...Memory pre-fetcher Data Cache (A big one) Beyond Programmable Shading: Fundamentals Slimming down 13 ALU (Execute) Fetch/ Decode

Beyond Programmable Shading: Fundamentals

Intel Larrabee (SIGGRAPH paper)

53

? ?

Tex Tex Tex Tex … ? …