| 612 | |
| 613 | template <int32_t THREADS_PER_CTA, int32_t THREADS_PER_PIXEL, int32_t ELEMENTS_PER_LDG> |
| 614 | DEVICE_FUNCTION void parallelSums(float* smem, float (&x)[ELEMENTS_PER_LDG], int32_t nhw) |
| 615 | { |
| 616 | |
| 617 | // The size of a warp. |
| 618 | int32_t const THREADS_PER_WARP = 32; |
| 619 | // The number of warps in a CTA. |
| 620 | int32_t const WARPS_PER_CTA = THREADS_PER_CTA / THREADS_PER_WARP; |
| 621 | // The number of pixels computed by a single warp. |
| 622 | int32_t const PIXELS_PER_WARP = THREADS_PER_WARP / THREADS_PER_PIXEL; |
| 623 | |
| 624 | // The position in the warp. |
| 625 | int32_t const nhw_in_warp = nhw % PIXELS_PER_WARP; |
| 626 | // The C in the warp. |
| 627 | int32_t const c_in_warp = threadIdx.x % THREADS_PER_PIXEL; |
| 628 | |
| 629 | // Store the values to shared memory. |
| 630 | writeToSmem(smem, threadIdx.x, x); |
| 631 | |
| 632 | // Compute the parallel sums. |
| 633 | for (int32_t offset = PIXELS_PER_WARP / 2; offset > 0; offset /= 2) |
| 634 | { |
| 635 | |
| 636 | if ((WARPS_PER_CTA * THREADS_PER_WARP) / THREADS_PER_PIXEL > THREADS_PER_WARP) |
| 637 | { |
| 638 | __syncthreads(); |
| 639 | } |
| 640 | else |
| 641 | { |
| 642 | // NOP. |
| 643 | __syncwarp(); |
| 644 | } |
| 645 | |
| 646 | // Read the running sum from the other thread. |
| 647 | float y[ELEMENTS_PER_LDG]; |
| 648 | if (nhw_in_warp < offset) |
| 649 | { |
| 650 | readFromSmem(y, smem, threadIdx.x + offset * THREADS_PER_PIXEL); |
| 651 | } |
| 652 | |
| 653 | // Compute the updated sum. |
| 654 | add(x, y); |
| 655 | |
| 656 | if ((WARPS_PER_CTA * THREADS_PER_WARP) / THREADS_PER_PIXEL > THREADS_PER_WARP) |
| 657 | { |
| 658 | __syncthreads(); |
| 659 | } |
| 660 | else |
| 661 | { |
| 662 | // NOP. |
| 663 | __syncwarp(); |
| 664 | } |
| 665 | |
| 666 | // Update the sum in SMEM. |
| 667 | if (offset > 1 && nhw_in_warp < offset) |
| 668 | { |
| 669 | writeToSmem(smem, threadIdx.x, x); |
| 670 | } |
| 671 | } |
nothing calls this directly
no test coverage detected