Performance Target Tesla M2090 512 CUDA processors @ 1.3 GHz each - - PowerPoint PPT Presentation

performance target
SMART_READER_LITE
LIVE PREVIEW

Performance Target Tesla M2090 512 CUDA processors @ 1.3 GHz each - - PowerPoint PPT Presentation

CUDA Deep Dive Performance CSE 6230 Jee Choi September 10, 2013 Performance Target Tesla M2090 512 CUDA processors @ 1.3 GHz each processor is capable of issuing 1 FMA (2 flops) instruction per cycle throughput = 512 1.3


slide-1
SLIDE 1

CUDA Deep Dive – Performance


CSE 6230

Jee Choi September 10, 2013

slide-2
SLIDE 2

Performance Target

  • Tesla M2090

– 512 CUDA processors @ 1.3 GHz – each processor is capable of issuing 1 FMA (2 flops) instruction per cycle – throughput = 512 × 1.3 × 2 = 1.33 TFLOP/s – 384-bit memory interface @ 1.85 GHz – GDDR5 memory transfers data on both rising and falling edge of the clock signal – bandwidth = 384 /8 bytes × 1.85 × 2 = 177 GB/s

  • How can we achieve this level of performance in
  • ur code?
slide-3
SLIDE 3

GPU Architecture

warp ¡ scheduler ¡ warp ¡ scheduler ¡ shared ¡memory ¡/ ¡ ¡ L1 ¡cache ¡(64 ¡KB) ¡ register ¡file ¡ (32,768 ¡× 32-bit) ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡ CP ¡

  • Dual warp scheduler

– in each cycle, dual warp scheduler selects two warps and issues one instruction from each warp to a group of sixteen cores

  • Register file

– each thread currently residing on the multiprocessor gets its own register set

  • 32 cores

– an instruction that has been scheduled from a warp is assigned to a group of 16 cores – it takes 2 cycles to issue 1 warp (first half-warp

  • n the first cycle, second half-warp on the

second cycle)

  • Shared memory

– 64 KB can be configured to give 48 KB or 16 KB to shared memory, and the rest to L1 cache – shared memory is “shared” amongst the thread blocks currently residing on the SM

Streaming ¡ MulGprocessor ¡(SM) ¡

slide-4
SLIDE 4

Achieving performance

  • Does this mean as long as we have 2 warps in

each SM, we can achieve peak performance?

slide-5
SLIDE 5

Achieving performance

  • Does this mean as long as we have 2 warps in

each SM, we can achieve peak performance?

– theoretically yes, but realistically no

slide-6
SLIDE 6

Achieving performance

  • Does this mean as long as we have 2 warps in

each SM, we can achieve peak performance?

– theoretically yes, but realistically no

  • Latency

– from beginning to end, instructions take X cycles to finish – arithmetic instructions ~10’s of cycles – memory reads ~100’s of cycles

  • Data dependency

– dependent instructions can’t be issued back-to-back

slide-7
SLIDE 7

Example

  • On the G80 architecture arithmetic instruction

latency is 24 cycles

a = a * b + c; // 1) takes 24 cycles to complete a = a * b + c; // 2) stalled because of dependency on 1) x = x * y + z; // 3) issued immediately after 2) because no dependency a = a * b + c; // 4) stalled because of dependency on 2) X = x * y + z; // 5) immediately issued after 4) because by the time 4) // was issued 3) was on its last cycle

slide-8
SLIDE 8

Example

  • On the G80 architecture arithmetic instruction

latency is 24 cycles

a = a * b + c; // 1) takes 24 cycles to complete a = a * b + c; // 2) stalled because of dependency on 1) x = x * y + z; // 3) issued immediately after 2) because no dependency a = a * b + c; // 4) stalled because of dependency on 2) X = x * y + z; // 5) immediately issued after 4) because by the time 4) // was issued 3) was on its last cycle

instrucGon ¡1 ¡ instrucGon ¡1 ¡issued ¡

slide-9
SLIDE 9

Example

  • On the G80 architecture arithmetic instruction

latency is 24 cycles

a = a * b + c; // 1) takes 24 cycles to complete a = a * b + c; // 2) stalled because of dependency on 1) x = x * y + z; // 3) issued immediately after 2) because no dependency a = a * b + c; // 4) stalled because of dependency on 2) X = x * y + z; // 5) immediately issued after 4) because by the time 4) // was issued 3) was on its last cycle

instrucGon ¡1 ¡ instrucGon ¡2 ¡issued ¡ instrucGon ¡2 ¡ 24 ¡cycles ¡

slide-10
SLIDE 10

Example

  • On the G80 architecture arithmetic instruction

latency is 24 cycles

a = a * b + c; // 1) takes 24 cycles to complete a = a * b + c; // 2) stalled because of dependency on 1) x = x * y + z; // 3) issued immediately after 2) because no dependency a = a * b + c; // 4) stalled because of dependency on 2) X = x * y + z; // 5) immediately issued after 4) because by the time 4) // was issued 3) was on its last cycle

instrucGon ¡1 ¡ instrucGon ¡3 ¡issued ¡ instrucGon ¡2 ¡ instrucGon ¡3 ¡ 26 ¡cycles ¡

slide-11
SLIDE 11

Example

  • On the G80 architecture arithmetic instruction

latency is 24 cycles

a = a * b + c; // 1) takes 24 cycles to complete a = a * b + c; // 2) stalled because of dependency on 1) x = x * y + z; // 3) issued immediately after 2) because no dependency a = a * b + c; // 4) stalled because of dependency on 2) X = x * y + z; // 5) immediately issued after 4) because by the time 4) // was issued 3) was on its last cycle

instrucGon ¡1 ¡ instrucGon ¡2 ¡ instrucGon ¡3 ¡ instrucGon ¡4 ¡

slide-12
SLIDE 12

Example

  • On the G80 architecture arithmetic instruction

latency is 24 cycles

a = a * b + c; // 1) takes 24 cycles to complete a = a * b + c; // 2) stalled because of dependency on 1) x = x * y + z; // 3) issued immediately after 2) because no dependency a = a * b + c; // 4) stalled because of dependency on 2) X = x * y + z; // 5) immediately issued after 4) because by the time 4) // was issued 3) was on its last cycle

instrucGon ¡1 ¡ instrucGon ¡2 ¡ instrucGon ¡3 ¡ instrucGon ¡4 ¡ instrucGon ¡5 ¡

  • nly ¡5 ¡instrucGons ¡

have ¡completed ¡

  • vs. ¡

73 ¡instrucGons ¡to ¡ achieve ¡peak ¡ 73 ¡cycles ¡

slide-13
SLIDE 13

Thread level parallelism

  • Thus, we need lots of independent threads/

warps to hide latency and achieve peak performance

  • Exactly how many do we need?
slide-14
SLIDE 14

Achieving performance

  • Thus, we need lots of independent threads/

warps to hide latency and achieve peak performance

  • Exactly how many do we need?

– Little’s Law can help us figure this out – recall that we used Little’s Law to help us figure out the number of in-flight memory requests to maximize bandwidth utilization

slide-15
SLIDE 15

Performance Notes


Bandwidth Utilization II

  • Little’s Law

– L = λW

  • L = average number of customers in a store
  • λ = arrival rate
  • W = average time spent
  • Memory Bandwidth

Latency (W) Bandwidth (λ) tens of thousands of in-flight requests!!!

slide-16
SLIDE 16

Thread level parallelism

  • For the G80 architecture GPU

– arithmetic instruction latency ~24 cycles (W) – 8 cores per multiprocessor (λ) – parallelism (number of in-flight instructions) = 24 × 8 = 192 (6 warps) – we need 6 warps of FMA instructions with independent instructions in order to achieve peak performance (equivalently, issue FMA instructions every cycle)

slide-17
SLIDE 17

Thread level parallelism

  • What if we have no FMA instructions?

– achieving “peak” is impossible

  • If we don’t have enough thread-level

parallelism?

– is it impossible to achieve peak?

slide-18
SLIDE 18

Thread level parallelism

  • What if we have no FMA instructions?

– achieving “peak” is impossible

  • If we don’t have enough thread-level

parallelism?

– is it impossible to achieve peak? – not if you take advantage of instruction-level parallelism (ILP)

slide-19
SLIDE 19

Occupancy

  • Recall that occupancy is

– (# of warps) / (maximum # warps)

  • Higher is generally better, but not always

– higher occupancy means more warps with which to hide latency – higher occupancy comes at a cost of fewer registers per thread – registers are the fastest memory and are necessarily in achieving high performance

slide-20
SLIDE 20

Occupancy on G80

  • G80

– maximum of 24 warps per SM – 6 warps are required to hide instruction latency using only TLP – occupancy = 6 / 24 = 0.25

  • Let’s try to achieve peak using occupancy

< 0.25 using ILP

slide-21
SLIDE 21

Example

  • On the G80 architecture

– arithmetic instruction latency is 24 cycles – there are 8 processors per SM – 192 threads / 6 warps are required to completely hide instruction latency

for(i=0; i< N; i++) { a = a * b + c; // no ILP; requires 6 warps to achieve peak } `

slide-22
SLIDE 22

Example

  • On the G80 architecture

– arithmetic instruction latency is 24 cycles – there are 8 processors per SM – with ILP of 2, each warp has 2 instructions that can be issued back-to-back – this is similar to having 2 warps with ILP of 1 – you can achieve peak using half the warps

for(i=0; i< N; i++) { a = a * b + c; // 2 independent instructions; ILP is 2 d = d * e + f; } `

slide-23
SLIDE 23

Example

  • On the G80 architecture

– arithmetic instruction latency is 24 cycles – there are 8 processors per SM – what is the minimum amount of ILP needed to achieve peak performance with 2 warps?

slide-24
SLIDE 24

Example

  • On the G80 architecture

– arithmetic instruction latency is 24 cycles – there are 8 processors per SM – what is the minimum amount of ILP needed to achieve peak performance with 2 warps? – since we need 6 warps of ILP of 1, we can get away with 2 warps of ILP of 3 – equivalent to an occupancy of 2 / 24 = 0.083

for(i=0; i< N; i++) { a = a * b + c; // 3 independent instructions; ILP is 3 d = d * e + f; g = g * h + I; } `

slide-25
SLIDE 25

Impact of using fewer warps

  • Typically there is a limit on the amount of

ILP that the GPU can take advantage of

– you need to mix ILP and TLP to more easily achieve peak or target performance

  • Having lower occupancy means more

registers per thread with which to increase performance

– more work per thread may also reduce thread block scheduling overheads

slide-26
SLIDE 26

Memory bandwidth

  • Similar techniques can be used to
  • ptimize memory bandwidth utilization

– copy more than 1 float per thread – use float2 and float4 data types when possible

  • You can achieve as much as 84% of peak

bandwidth using as little as 0.042

  • ccupancy
slide-27
SLIDE 27

Registers and performance

  • Why are registers important for

performance?

– only registers are fast enough to sustain peak performance – consider a = a * b + c – in order to issue this instruction every cycle, we need to read (4×3=12 Bytes) every cycle – On Tesla M2090, this translates to 12 Bytes × 512 × 1.3 GHz = 8 TB/s

slide-28
SLIDE 28

Registers and performance

  • Can registers accommodate it?

– obviously yes, otherwise you can NEVER achieve peak

  • Can anything else?

– how about shared memory, the second fastest memory on a GPU – shared memory is configured with 32 banks per SM, each providing 4 Bytes and takes 2 cycles to read – effective bandwidth = 4 Bytes × 32 banks ×16 SM × 1.3 GHz × 0.5 = 1.33 TB/s

slide-29
SLIDE 29

Registers and performance

  • Can registers accommodate it?

– obviously yes, otherwise you can NEVER achieve peak

  • Can anything else?

– how about shared memory, the second fastest memory on a GPU – shared memory is configured with 32 banks per SM, each providing 4 Bytes and takes 2 cycles to read – effective bandwidth = 4 Bytes × 32 banks ×16 SM × 1.3 GHz × 0.5 = 1.33 TB/s

slide-30
SLIDE 30

Shared memory banks

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

bank ¡ thread ¡ shared ¡memory ¡ no ¡ ¡ bank ¡ ¡ conflict ¡

slide-31
SLIDE 31

Shared memory banks

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

bank ¡ thread ¡ shared ¡memory ¡ no ¡ ¡ bank ¡ ¡ conflict ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

bank ¡ thread ¡ shared ¡memory ¡ no ¡ ¡ bank ¡ ¡ conflict ¡

slide-32
SLIDE 32

Shared memory banks

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

bank ¡ thread ¡ shared ¡memory ¡ no ¡ ¡ bank ¡ ¡ conflict ¡ shared ¡memory ¡

slide-33
SLIDE 33

Shared memory banks

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

bank ¡ thread ¡ shared ¡memory ¡ no ¡ ¡ bank ¡ ¡ conflict ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

bank ¡ thread ¡ shared ¡memory ¡ 2-­‑way ¡ bank ¡ ¡ conflict ¡

slide-34
SLIDE 34

Shared memory banks

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

0 ¡ 1 ¡ 2 ¡ 3 ¡ 4 ¡ 5 ¡ 6 ¡ 7 ¡ 8 ¡ 9 ¡ 10 ¡ 11 ¡ 12 ¡ 13 ¡ 14 ¡ 15 ¡

bank ¡ thread ¡ shared ¡memory ¡ no ¡ ¡ bank ¡ ¡ conflict ¡

slide-35
SLIDE 35

Registers and performance

  • You must use registers to achieve peak

performance

Global ¡ memory ¡ Shared ¡ memory ¡ (1.33 ¡TB/s) ¡ Registers ¡ (8 ¡TB/s) ¡

177 GB/s

1.33 TB/s

8 TB/s

slide-36
SLIDE 36

Real applications

  • On real applications with interleaved

memory loads and computations, how do we approximate “achievable” performance

  • We can use computation intensity and the

“roofline” model

– intensity = FLOPs / Byte – system’s balance = performance (FLOPs) / bandwidth (GB/s)

slide-37
SLIDE 37

Roofline in time ¡

1/32 1/16 1/8 1/4 1/2 1

3.6

GFLOP/s

1/2 1 2 4 8 16 32 64 128

Intensity (FLOP:Byte) Relative performance

system’s “balance”

slide-38
SLIDE 38

Roofline in time ¡

1/32 1/16 1/8 1/4 1/2 1

3.6

GFLOP/s

1/2 1 2 4 8 16 32 64 128

Intensity (FLOP:Byte) Relative performance

Compute bound Memory (bandwidth) bound

slide-39
SLIDE 39

Roofline in time ¡

1/32 1/16 1/8 1/4 1/2 1

3.6

GFLOP/s

1/2 1 2 4 8 16 32 64 128

Intensity (FLOP:Byte) Relative performance

application’s computational intensity

slide-40
SLIDE 40

Roofline in time ¡

1/32 1/16 1/8 1/4 1/2 1

3.6

GFLOP/s

1/2 1 2 4 8 16 32 64 128

Intensity (FLOP:Byte) Relative performance

expected performance

slide-41
SLIDE 41

Real applications

  • This is just a rough estimate with

assumptions

– perfect overlap between computation and communication – no other resource bottlenecks (shared memory, registers, parallelism)

  • Generally a good place to start when

estimating performance

– you can iteratively apply bottlenecks and limitations to get a more accurate achievable performance estimate

slide-42
SLIDE 42

Case studies

  • Consider matrix-matrix multiplication

– C = A × B

  • Naïvely

– 2 flops for every 2 words – intensity = 2 / 8 = 0.25

for(i=0; i< N; i++) { // row for(j=0; j < N; j++) { // column for(k = 0; k < N; k++) C[i][j] += A[i][k] * B[k][j]; // 2 flops and 2 words } } }

slide-43
SLIDE 43

Performance

N ¡ Time ¡ Performance ¡ Speedup ¡ Naïve ¡ 1024 ¡ 29.63 ¡ms ¡ 72.48 ¡GFLOP/s ¡ 1.0× ¡

slide-44
SLIDE 44

Case studies

  • Naïvely

– 2 flops for every 2 words – intensity = 2 / 8 = 0.25 – expected performance = 0.25 FLOP/Byte × 177 GB/s = 44.25 GFLOP/s – achieved performance = 72.48 GFLOP/s – 15 registers and occupancy of 0.667 – why? did we just break the barriers of reality?

slide-45
SLIDE 45

Case studies

  • Naïvely

– 2 flops for every 2 words – intensity = 2 / 8 = 0.25 – expected performance = 0.25 FLOP/Byte × 177 GB/s = 44.25 GFLOP/s – achieved performance = 72.48 GFLOP/s – 15 registers and occupancy of 0.667 – why? did we just break the barriers of reality? – no, probably just caching in L1 and L2

slide-46
SLIDE 46

Case studies

  • Let’s try using shared memory (32×32)

– 1 thread per target (C[i][j]) – still 2 flops for every 2 words (intensity = 0.25) – performance now depends on shared memory bandwidth – expected performance = ~333 GFLOP/s

C B A

slide-47
SLIDE 47

Case studies

  • Let’s try using shared memory (32×32)

– 1 thread per target (C[i][j]) – still 2 flops for every 2 words (intensity = 0.25) – performance now depends on shared memory bandwidth – expected performance = ~333 GFLOP/s – achieved performance = 227.6 GFLOP/s – 20 registers and occupancy of 0.667 – why only 68% of peak?

slide-48
SLIDE 48

Case studies

  • Let’s try using shared memory (32×32)

– 1 thread per target (C[i][j]) – still 2 flops for every 2 words (intensity = 0.25) – performance now depends on shared memory bandwidth – expected performance = ~333 GFLOP/s – achieved performance = 227.6 GFLOP/s – 20 registers and occupancy of 0.667 – why only 68% of peak? – only 1 thread block per SM (limited by warps) – no latency hiding for global memory

slide-49
SLIDE 49

Performance

N ¡ Time ¡ Performance ¡ Speedup ¡ Naïve ¡ 1024 ¡ 29.63 ¡ms ¡ 72.48 ¡GFLOP/s ¡ 1.0× ¡ shared ¡ memory ¡ 1024 ¡ 9.44 ¡ms ¡ 227.6 ¡GFLOP/s ¡ 3.1× ¡

slide-50
SLIDE 50

Case studies

  • How can we improve performance?

– re-use data in registers – halve the number of threads and assign 2 targets per thread (re-use element B[i][j]) – now 4 flops for every 3 words (intensity = 0.33) – expected performance = ~429 GFLOP/s

slide-51
SLIDE 51

Case studies

  • How can we improve performance?

– re-use data in registers – halve the number of threads and assign 2 targets per thread (re-use element B[i][j]) – now 4 flops for every 3 words (intensity = 0.33) – expected performance = ~429 GFLOP/s – achieved performance = 332.3 GFLOP/s – 23 registers and occupancy of 0.667 – 2 thread blocks per SM and 77% of expected performance

slide-52
SLIDE 52

Performance

N ¡ Time ¡ Performance ¡ Speedup ¡ Naïve ¡ 1024 ¡ 29.63 ¡ms ¡ 72.5 ¡GFLOP/s ¡ 1.0× ¡ shared ¡ memory ¡ 1024 ¡ 9.44 ¡ms ¡ 227.6 ¡GFLOP/s ¡ 3.1× ¡ shared ¡ memory ¡+ ¡2 ¡ targets/thread ¡ 1024 ¡ 6.46 ¡ms ¡ 332.3 ¡GFLOP/s ¡ 4.6× ¡

slide-53
SLIDE 53

Case studies

  • How can we push this even further?

– 4 targets per thread – now 8 flops for every 5 words (intensity = 0.4) – expected performance = ~520 GFLOP/s

slide-54
SLIDE 54

Case studies

  • How can we push this even further?

– 4 targets per thread – now 8 flops for every 5 words (intensity = 0.4) – expected performance = ~520 GFLOP/s – achieved performance = 424.7 GFLOP/s – 32 registers and occupancy of 0.667 – 4 thread blocks per SM and 82% of expected performance

slide-55
SLIDE 55

Performance

N ¡ Time ¡ Performance ¡ Speedup ¡ Naïve ¡ 1024 ¡ 29.63 ¡ms ¡ 72.5 ¡GFLOP/s ¡ 1.0× ¡ shared ¡ memory ¡ 1024 ¡ 9.44 ¡ms ¡ 227.6 ¡GFLOP/s ¡ 3.1× ¡ shared ¡ memory ¡+ ¡2 ¡ targets/thread ¡ 1024 ¡ 6.46 ¡ms ¡ 332.3 ¡GFLOP/s ¡ 4.6× ¡ shared ¡ memory ¡+ ¡4 ¡ targets/thread ¡ 1024 ¡ 5.05 ¡ms ¡ 424.7 ¡GFLOP/s ¡ 5.9× ¡

slide-56
SLIDE 56

Case studies

  • Let’s assign even more work per thread

– 8 targets per thread – now 16 flops for every 9 words (intensity = 0.44) – expected performance = ~578 GFLOP/s

slide-57
SLIDE 57

Case studies

  • Let’s assign even more work per thread

– 8 targets per thread – now 16 flops for every 9 words (intensity = 0.44) – expected performance = ~578 GFLOP/s – achieved performance = 474.2 GFLOP/s – 51 registers and occupancy of 0.333 – 4 thread blocks per SM and 82% of expected performance (same as before)

slide-58
SLIDE 58

Performance

N ¡ Time ¡ Performance ¡ Speedup ¡ Naïve ¡ 1024 ¡ 29.63 ¡ms ¡ 72.5 ¡GFLOP/s ¡ 1.0× ¡ shared ¡ memory ¡ 1024 ¡ 9.44 ¡ms ¡ 227.6 ¡GFLOP/s ¡ 3.1× ¡ shared ¡ memory ¡+ ¡2 ¡ targets/thread ¡ 1024 ¡ 6.46 ¡ms ¡ 332.3 ¡GFLOP/s ¡ 4.6× ¡ shared ¡ memory ¡+ ¡4 ¡ targets/thread ¡ 1024 ¡ 5.05 ¡ms ¡ 424.7 ¡GFLOP/s ¡ 5.9× ¡ shared ¡ memory ¡+ ¡8 ¡ targets/thread ¡ 1024 ¡ 4.53 ¡ms ¡ 474.2 ¡GFLOP/s ¡ 6.5× ¡