GPU Threads and SchedulingPerhaad Mistry & Dana Schaa,Northeastern University Computer ArchitectureResearch Lab, with Benedict R. Gaster, AMD© 2011
Instructor NotesThis lecture deals with how work groups are scheduled for execution on the compute units of devicesAlso explain the effects of divergence of work items within a group and its negative effect on performanceReasons why we discuss warps and wavefronts because even though they are not part of the OpenCL specificationServe as another hierarchy of threads and their implicit synchronization enables interesting implementations of algorithms on GPUsImplicit synchronization and write combining property in local memory used to implement warp votingWe discuss how predication is used for divergent work items even though all threads in a warp are issued in lockstep2Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
TopicsWavefronts and warpsThread scheduling for both AMD and NVIDIA GPUsPredicationWarp voting and synchronizationPitfalls of wavefront/warp specific implementations3Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Work Groups to HW ThreadsOpenCL kernels are structured into work groups that map to device compute unitsCompute units on GPUs consist of SIMT processing elementsWork groups automatically get broken down into hardware schedulable groups of threads for the SIMT hardwareThis “schedulable unit” is known as a warp (NVIDIA) or a wavefront (AMD)4Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Work-Item SchedulingHardware creates wavefronts by grouping threads of a work groupAlong the X dimension firstAll threads in a wavefront execute the same instructionThreads within a wavefront move in lockstepThreads have their own register state and are free to execute different control pathsThread masking used by HWPredication can be set by compilerWavefront 00,00,10,140,151,01,11,141,152,02,12,142,153,03,13,143,15Wavefront 14,04,14,144,157,147,07,17,15Wavefront 2Wavefront 3Grouping of work-group into wavefronts5Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Wavefront Scheduling - AMDIssue and Branch Control UnitWavefront size is 64 threads Each thread executes a 5 way VLIW instruction issued by the common issue unitA Stream Core (SC) executes one VLIW instruction16 stream cores execute 16 VLIW instructions on each cycle A quarter wavefront is executed on each cycle, the entire wavefront is executed in four consecutive cyclesSIMD EngineSC 0SC 1SC 2Local Data ShareSC 3SC 4SC 156Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Wavefront Scheduling - AMDIn the case of Read-After-Write (RAW) hazard, one wavefront will stall for four extra cyclesIf another wavefront is available it can be scheduled to hide latencyAfter eight total cycles have elapsed, the ALU result from the first wavefront is ready, so the first wavefront can continue executionTwo wavefronts (128 threads) completely hide a RAW latencyThe first wavefront executes for four cyclesAnother wavefront is scheduled for the next four cyclesThe first wavefront can then run againNote that two wavefronts are needed just to hide RAW latency, the latency to global memory is much greaterDuring this time, the compute unit can process other independent wavefronts, if they are available7Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Warp Scheduling - NvidiaWarp 2Warp 0Warp 1Work groups are divided into 32-thread warps which are scheduled by a SMOn Nvidia GPUs half warps are issued each time and they interleave their execution through the pipeline The number of warps available for scheduling is dependent on the resources used by each  blockSimilar to wavefronts in AMD hardware except for size differencesInstruction Fetch/Dispatcht32 – t63t64 – t95t0 – t31SPSPSPSPWork GroupSPSPSPSPStreaming MultiprocessorShared Memory8Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Occupancy - TradeoffsLocal memory and registers are persistent within compute unit when other work groups executeAllows for lower overhead context switchThe number of active wavefronts that can be supported per compute unit is limitedDecided by the local memory required per workgroup and register usage per threadThe number of active wavefronts possible on a compute unit can be expressed using a metric called occupancyLarger numbers of active wavefronts allow for better latency hiding on both AMD and NVIDIA hardwareOccupancy will be discussed in detail in Lecture 089Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Divergent Control FlowInstructions are issued in lockstep in a wavefront /warp for both AMD and NvidiaHowever each work item can execute a different path from other threads in the wavefrontIf work items within a wavefront go on divergent paths of flow control, the invalid paths of a work-items are masked by hardwareBranching should be limited to a wavefront granularity to prevent issuing of wasted instructions10Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Predication and Control FlowHow do we handle threads going down different execution paths when the same instruction is issued to all the work-items in a wavefront ?Predication is a method for mitigating the costs associated with conditional branches Beneficial in case of branches to short sections of codeBased on fact that executing an instruction and squashing its result may be as efficient as executing a  conditionalCompilers may replace “switch” or “if then else” statements by using branch predication 11Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Predication for GPUs__kernel void test() {inttid= get_local_id(0) ;	if( tid %2 == 0)Do_Some_Work() ;	elseDo_Other_Work() ; }Predicate is a condition code that is set to true or false based on a conditionalBoth cases of conditional flow get scheduled for executionInstructions with a true predicate are committedInstructions with a false predicate do not write results or read operandsBenefits performance only for very short conditionalsPredicate = True  for threads 0,2,4….Predicate = False for threads 1,3,5….Predicates switched for the else condition12Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Divergent Control FlowCase 1: All odd threads will execute if conditional while all even threads execute the else conditional. The if and else block need to be issued for each wavefrontCase 2:All threads of the first wavefront will execute the if case while other wavefronts will execute the else case. In this case only one out of if or else is issued for each wavefrontCase 2Case 1inttid = get_local_id(0)if ( tid / 64 == 0)  //Full First WavefrontDoSomeWork()else if (tid /64 == 1) //Full Second  Wavefront	DoSomeWork2()inttid = get_local_id(0)if ( tid % 2 == 0) //Even Work ItemsDoSomeWork()else	DoSomeWork2()Conditional – With divergenceConditional – No divergence13Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Effect of Predication on PerformanceTime for Do_Some_Work = t1 (if case)Time for Do_Other _Work = t2 (else case)T = 0T = tstartif( tid %2 == 0)Do_Some_Work()t1Green colored threads have valid resultsSquash invalid results, invert maskT =  tstart + t1Do_Other _Work()t2T =  tstart + t1 + t2Squash invalid resultsGreen colored threads have valid resultsTotal Time taken = tstart +t1 + t2 14Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Warp VotingImplicit synchronization per instruction allows for techniques like warp votingUseful for devices without atomic shared memory operationsWe discuss warp voting with the 256-bin Histogram exampleFor 64 bin histogram, we build a sub histogram per threadLocal memory per work group for 256 bins256 bins * 4Bytes * 64 threads / block =  64KBG80 GPUs have only 16KB of shared memoryAlternatively, build per warp subhistogramLocal memory required per work group256 bins * 4Bytes * 2 warps / block =  2KBwork item jwork item kwork item iLocal memoryShared memory write combining on allows ONLY one write from work-items i,j or k to succeedBy tagging bits in local memory and rechecking the value a work-item could know if its previously attempted write succeeded15Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Warp Voting for Histogram256Build per warp subhistogramCombine to per work group subhistogramLocal memory budget in per warp sub histogram technique allows us to have multiple work groups activeHandle conflicting writes by threads within a warp using warp votingTag writes to per warp subhistogram with intra-warp thread IDThis allows the threads to check if their writes were successful in the next iteration of the while loopWorst case : 32 iterations done when all 32 threads write to the same bin32 bit Uint5 bit tag27 bit tagvoid addData256( 	volatile __local uint * l_WarpHist, uint data, uintworkitemTag) { unsigned intcount; do{ 	// Read the current value from histogram	count = l_WarpHist[data] & 0x07FFFFFFU; 	// Add the tag and incremented data to	// the position in the histogram 	count = workitemTag | (count + 1);l_WarpHist[data] = count; }  // Check if the value committed to local memory // If not go back in the loop and try againwhile(l_WarpHist[data] != count);}Source: Nvidia GPU Computing SDK Examples16Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Pitfalls of using WavefrontsOpenCL specification does not address warps/wavefronts or provide a means to query their size across platformsAMD GPUs (5870) have 64 threads per wavefront while NVIDIA has 32 threads per warpNVIDIA’s OpenCL extensions (discussed later) return warp size only for Nvidia hardwareMaintaining performance and correctness across devices becomes harderCode hardwired to 32 threads per warp when run on AMD hardware 64 threads will waste execution resourcesCode hardwired to 64 threads per warp when run on Nvidia hardware can lead to races and affects the local memory budgetWe have only discussed GPUs, the Cell doesn’t have wavefrontsMaintaining portability – assign warp size at JIT timeCheck if running AMD / Nvidia and add a –DWARP_SIZE Sizeto build command17Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
Warp-Based ImplementationImplicit synchronization in warps at each instruction allows for expression of another thread hierarchy within work groupWarp specific implementations common in CUDA literatureE.g.: 256 Bin Histogram NVIDIA’s implementation allows building histograms in local memory for devices without  atomic operation support and limited shared memorySynchronization in warps allows for implementing the voting discussed previously reducing local memory budget from N_THREADS*256 to N_WARPS_PER_BLOCK*256E.g.: CUDPP: CUDA Data Parallel PrimitivesUtilizes an efficient warp scan to construct a block scan which works on one block in CUDA18Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
SummaryDivergence within a work-group should be restricted to a wavefront/warp granularity for performanceA tradeoff between schemes to avoid divergence and simple code which can quickly be predicated Branches are usually highly biased and localized which leads to short predicated blocks The number of wavefronts active at any point in time should be maximized to allow latency hidingNumber of active wavefronts is determined by the requirements of resources like registers and local memoryWavefront specific implementations can enable more optimized implementations and enables more algorithms to GPUsMaintaining performance and correctness may be hard due to the different wavefront sizes on AMD and NVIDIA hardware19Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011

Lec07 threading hw

  • 1.
    GPU Threads andSchedulingPerhaad Mistry & Dana Schaa,Northeastern University Computer ArchitectureResearch Lab, with Benedict R. Gaster, AMD© 2011
  • 2.
    Instructor NotesThis lecturedeals with how work groups are scheduled for execution on the compute units of devicesAlso explain the effects of divergence of work items within a group and its negative effect on performanceReasons why we discuss warps and wavefronts because even though they are not part of the OpenCL specificationServe as another hierarchy of threads and their implicit synchronization enables interesting implementations of algorithms on GPUsImplicit synchronization and write combining property in local memory used to implement warp votingWe discuss how predication is used for divergent work items even though all threads in a warp are issued in lockstep2Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 3.
    TopicsWavefronts and warpsThreadscheduling for both AMD and NVIDIA GPUsPredicationWarp voting and synchronizationPitfalls of wavefront/warp specific implementations3Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 4.
    Work Groups toHW ThreadsOpenCL kernels are structured into work groups that map to device compute unitsCompute units on GPUs consist of SIMT processing elementsWork groups automatically get broken down into hardware schedulable groups of threads for the SIMT hardwareThis “schedulable unit” is known as a warp (NVIDIA) or a wavefront (AMD)4Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 5.
    Work-Item SchedulingHardware createswavefronts by grouping threads of a work groupAlong the X dimension firstAll threads in a wavefront execute the same instructionThreads within a wavefront move in lockstepThreads have their own register state and are free to execute different control pathsThread masking used by HWPredication can be set by compilerWavefront 00,00,10,140,151,01,11,141,152,02,12,142,153,03,13,143,15Wavefront 14,04,14,144,157,147,07,17,15Wavefront 2Wavefront 3Grouping of work-group into wavefronts5Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 6.
    Wavefront Scheduling -AMDIssue and Branch Control UnitWavefront size is 64 threads Each thread executes a 5 way VLIW instruction issued by the common issue unitA Stream Core (SC) executes one VLIW instruction16 stream cores execute 16 VLIW instructions on each cycle A quarter wavefront is executed on each cycle, the entire wavefront is executed in four consecutive cyclesSIMD EngineSC 0SC 1SC 2Local Data ShareSC 3SC 4SC 156Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 7.
    Wavefront Scheduling -AMDIn the case of Read-After-Write (RAW) hazard, one wavefront will stall for four extra cyclesIf another wavefront is available it can be scheduled to hide latencyAfter eight total cycles have elapsed, the ALU result from the first wavefront is ready, so the first wavefront can continue executionTwo wavefronts (128 threads) completely hide a RAW latencyThe first wavefront executes for four cyclesAnother wavefront is scheduled for the next four cyclesThe first wavefront can then run againNote that two wavefronts are needed just to hide RAW latency, the latency to global memory is much greaterDuring this time, the compute unit can process other independent wavefronts, if they are available7Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 8.
    Warp Scheduling -NvidiaWarp 2Warp 0Warp 1Work groups are divided into 32-thread warps which are scheduled by a SMOn Nvidia GPUs half warps are issued each time and they interleave their execution through the pipeline The number of warps available for scheduling is dependent on the resources used by each blockSimilar to wavefronts in AMD hardware except for size differencesInstruction Fetch/Dispatcht32 – t63t64 – t95t0 – t31SPSPSPSPWork GroupSPSPSPSPStreaming MultiprocessorShared Memory8Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 9.
    Occupancy - TradeoffsLocalmemory and registers are persistent within compute unit when other work groups executeAllows for lower overhead context switchThe number of active wavefronts that can be supported per compute unit is limitedDecided by the local memory required per workgroup and register usage per threadThe number of active wavefronts possible on a compute unit can be expressed using a metric called occupancyLarger numbers of active wavefronts allow for better latency hiding on both AMD and NVIDIA hardwareOccupancy will be discussed in detail in Lecture 089Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 10.
    Divergent Control FlowInstructionsare issued in lockstep in a wavefront /warp for both AMD and NvidiaHowever each work item can execute a different path from other threads in the wavefrontIf work items within a wavefront go on divergent paths of flow control, the invalid paths of a work-items are masked by hardwareBranching should be limited to a wavefront granularity to prevent issuing of wasted instructions10Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 11.
    Predication and ControlFlowHow do we handle threads going down different execution paths when the same instruction is issued to all the work-items in a wavefront ?Predication is a method for mitigating the costs associated with conditional branches Beneficial in case of branches to short sections of codeBased on fact that executing an instruction and squashing its result may be as efficient as executing a conditionalCompilers may replace “switch” or “if then else” statements by using branch predication 11Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 12.
    Predication for GPUs__kernelvoid test() {inttid= get_local_id(0) ; if( tid %2 == 0)Do_Some_Work() ; elseDo_Other_Work() ; }Predicate is a condition code that is set to true or false based on a conditionalBoth cases of conditional flow get scheduled for executionInstructions with a true predicate are committedInstructions with a false predicate do not write results or read operandsBenefits performance only for very short conditionalsPredicate = True for threads 0,2,4….Predicate = False for threads 1,3,5….Predicates switched for the else condition12Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 13.
    Divergent Control FlowCase1: All odd threads will execute if conditional while all even threads execute the else conditional. The if and else block need to be issued for each wavefrontCase 2:All threads of the first wavefront will execute the if case while other wavefronts will execute the else case. In this case only one out of if or else is issued for each wavefrontCase 2Case 1inttid = get_local_id(0)if ( tid / 64 == 0) //Full First WavefrontDoSomeWork()else if (tid /64 == 1) //Full Second Wavefront DoSomeWork2()inttid = get_local_id(0)if ( tid % 2 == 0) //Even Work ItemsDoSomeWork()else DoSomeWork2()Conditional – With divergenceConditional – No divergence13Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 14.
    Effect of Predicationon PerformanceTime for Do_Some_Work = t1 (if case)Time for Do_Other _Work = t2 (else case)T = 0T = tstartif( tid %2 == 0)Do_Some_Work()t1Green colored threads have valid resultsSquash invalid results, invert maskT = tstart + t1Do_Other _Work()t2T = tstart + t1 + t2Squash invalid resultsGreen colored threads have valid resultsTotal Time taken = tstart +t1 + t2 14Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 15.
    Warp VotingImplicit synchronizationper instruction allows for techniques like warp votingUseful for devices without atomic shared memory operationsWe discuss warp voting with the 256-bin Histogram exampleFor 64 bin histogram, we build a sub histogram per threadLocal memory per work group for 256 bins256 bins * 4Bytes * 64 threads / block = 64KBG80 GPUs have only 16KB of shared memoryAlternatively, build per warp subhistogramLocal memory required per work group256 bins * 4Bytes * 2 warps / block = 2KBwork item jwork item kwork item iLocal memoryShared memory write combining on allows ONLY one write from work-items i,j or k to succeedBy tagging bits in local memory and rechecking the value a work-item could know if its previously attempted write succeeded15Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 16.
    Warp Voting forHistogram256Build per warp subhistogramCombine to per work group subhistogramLocal memory budget in per warp sub histogram technique allows us to have multiple work groups activeHandle conflicting writes by threads within a warp using warp votingTag writes to per warp subhistogram with intra-warp thread IDThis allows the threads to check if their writes were successful in the next iteration of the while loopWorst case : 32 iterations done when all 32 threads write to the same bin32 bit Uint5 bit tag27 bit tagvoid addData256( volatile __local uint * l_WarpHist, uint data, uintworkitemTag) { unsigned intcount; do{ // Read the current value from histogram count = l_WarpHist[data] & 0x07FFFFFFU; // Add the tag and incremented data to // the position in the histogram count = workitemTag | (count + 1);l_WarpHist[data] = count; } // Check if the value committed to local memory // If not go back in the loop and try againwhile(l_WarpHist[data] != count);}Source: Nvidia GPU Computing SDK Examples16Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 17.
    Pitfalls of usingWavefrontsOpenCL specification does not address warps/wavefronts or provide a means to query their size across platformsAMD GPUs (5870) have 64 threads per wavefront while NVIDIA has 32 threads per warpNVIDIA’s OpenCL extensions (discussed later) return warp size only for Nvidia hardwareMaintaining performance and correctness across devices becomes harderCode hardwired to 32 threads per warp when run on AMD hardware 64 threads will waste execution resourcesCode hardwired to 64 threads per warp when run on Nvidia hardware can lead to races and affects the local memory budgetWe have only discussed GPUs, the Cell doesn’t have wavefrontsMaintaining portability – assign warp size at JIT timeCheck if running AMD / Nvidia and add a –DWARP_SIZE Sizeto build command17Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 18.
    Warp-Based ImplementationImplicit synchronizationin warps at each instruction allows for expression of another thread hierarchy within work groupWarp specific implementations common in CUDA literatureE.g.: 256 Bin Histogram NVIDIA’s implementation allows building histograms in local memory for devices without atomic operation support and limited shared memorySynchronization in warps allows for implementing the voting discussed previously reducing local memory budget from N_THREADS*256 to N_WARPS_PER_BLOCK*256E.g.: CUDPP: CUDA Data Parallel PrimitivesUtilizes an efficient warp scan to construct a block scan which works on one block in CUDA18Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011
  • 19.
    SummaryDivergence within awork-group should be restricted to a wavefront/warp granularity for performanceA tradeoff between schemes to avoid divergence and simple code which can quickly be predicated Branches are usually highly biased and localized which leads to short predicated blocks The number of wavefronts active at any point in time should be maximized to allow latency hidingNumber of active wavefronts is determined by the requirements of resources like registers and local memoryWavefront specific implementations can enable more optimized implementations and enables more algorithms to GPUsMaintaining performance and correctness may be hard due to the different wavefront sizes on AMD and NVIDIA hardware19Perhaad Mistry & Dana Schaa, Northeastern Univ Computer Architecture Research Lab, with Ben Gaster, AMD © 2011

Editor's Notes

  • #5 A recap of how work groups are scheduled on GPUs
  • #6 Splitting of threads in a work group into wavefrontsWarp is a term based from CUDA terminology, while wavefront is a AMD term.
  • #7 Wavefront Scheduling - AMD
  • #8 Effect of wavefront scheduling.As seen in AMD hardware at least 2 wavefronts should always be actives
  • #9 Wavefront Scheduling - Nvidia
  • #10 Benefits of having multiple warps active at a time include better latency hiding
  • #11 Introducing divergent control flow
  • #12 An introduction to predication.A key point is that it is beneficial only for very short conditionals
  • #13 Predication example
  • #14 Two different cases of divergence in a work groupCase1: Odd threads go down one path and even threads go down another pathCase2: Entire wavefront goes down a similar path
  • #15 When using predication, all threads go down all paths and using masks the invalid OP results are squashedTime taken is simply sum of if and else block
  • #16 Warp voting can be implemented because of the implicit synchronization across work items is a warpBy using a per warp sub histogram, many work items within the active warp would attempt to increment the same locationAll writes in such cases will not succeed because shared memory write combining on allows ONLY one write from a work-item to succeedThis necessitates warp voting
  • #17 Tag is checked on the next pass through the loop to check if the write was successful
  • #18 Maintaining performance and correctness portability becomes harder with warp / wavefront constructs in your program
  • #19 Lots of examples in the CUDA SDK use the notion of warps to either enforce some communication or reduce shared memory requirements