- template <typename Number, typename Operation>
- __device__ void
- reduce_within_warp(volatile Number *result_buffer, size_type local_idx)
- {
- if (block_size >= 64)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + 32]);
- if (block_size >= 32)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + 16]);
- if (block_size >= 16)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + 8]);
- if (block_size >= 8)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + 4]);
- if (block_size >= 4)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + 2]);
- if (block_size >= 2)
- result_buffer[local_idx] =
- Operation::reduction_op(result_buffer[local_idx],
- result_buffer[local_idx + 1]);
- }
-
-
-
template <typename Number, typename Operation>
__device__ void
reduce(Number * result,
const size_type global_idx,
const size_type N)
{
- for (size_type s = block_size / 2; s > 32; s = s >> 1)
+ for (size_type s = block_size / 2; s > warp_size; s = s >> 1)
{
if (local_idx < s)
result_buffer[local_idx] =
__syncthreads();
}
- if (local_idx < 32)
- reduce_within_warp<Number, Operation>(result_buffer, local_idx);
+ if (local_idx < warp_size)
+ {
+ for (size_type s = warp_size; s > 0; s = s >> 1)
+ {
+ result_buffer[local_idx] =
+ Operation::reduction_op(result_buffer[local_idx],
+ result_buffer[local_idx + s]);
+ }
+ }
if (local_idx == 0)
Operation::atomic_op(result, result_buffer[0]);
#ifdef DEAL_II_COMPILER_CUDA_AWARE
+# include <deal.II/base/cuda_size.h>
# include <deal.II/base/mpi.h>
# include <deal.II/base/quadrature.h>
# include <deal.II/base/tensor.h>
cells_per_block_shmem(int dim, int fe_degree)
{
/* clang-format off */
- return dim==2 ? (fe_degree==1 ? 32 :
- fe_degree==2 ? 8 :
- fe_degree==3 ? 4 :
- fe_degree==4 ? 4 :
+ // We are limiting the number of threads according to the
+ // following formulas:
+ // - in 2D: `threads = cells * (k+1)^d <= 4*CUDAWrappers::warp_size`
+ // - in 3D: `threads = cells * (k+1)^d <= 2*CUDAWrappers::warp_size`
+ return dim==2 ? (fe_degree==1 ? CUDAWrappers::warp_size : // 128
+ fe_degree==2 ? CUDAWrappers::warp_size/4 : // 72
+ fe_degree==3 ? CUDAWrappers::warp_size/8 : // 64
+ fe_degree==4 ? CUDAWrappers::warp_size/8 : // 100
1) :
- dim==3 ? (fe_degree==1 ? 8 :
- fe_degree==2 ? 2 :
+ dim==3 ? (fe_degree==1 ? CUDAWrappers::warp_size/4 : // 64
+ fe_degree==2 ? CUDAWrappers::warp_size/16 : // 54
1) : 1;
/* clang-format on */
}