// SPDX-FileCopyrightText: Copyright (c) 2011-2026, NVIDIA CORPORATION. All rights reserved. // SPDX-License-Identifier: BSD-3 #pragma once #include #include #include #include "../policy_selector.h" template static void basic(nvbench::state& state, nvbench::type_list) try { using init_value_t = T; using accum_t [[maybe_unused]] = ::cuda::std::__accumulator_t; using offset_t = cub::detail::choose_offset_t; #if USES_LOOKAHEAD() static_assert(sizeof(offset_t) == sizeof(size_t)); // lookahead scan uses size_t internally #endif // USES_LOOKAHEAD() const auto elements = static_cast(state.get_int64("Elements{io}")); if (sizeof(offset_t) == 4 && elements > std::numeric_limits::max()) { state.skip("Skipping: input size exceeds 32-bit offset type capacity."); return; } thrust::device_vector input = generate(elements); thrust::device_vector output(elements); const T* d_input = thrust::raw_pointer_cast(input.data()); T* d_output = thrust::raw_pointer_cast(output.data()); state.add_element_count(elements); state.add_global_memory_reads(elements, "Size"); state.add_global_memory_writes(elements); caching_allocator_t alloc; state.exec(nvbench::exec_tag::gpu | nvbench::exec_tag::no_batch, [&](nvbench::launch& launch) { auto env = cub_bench_env( alloc, launch #if !TUNE_BASE , cuda::execution::tune(policy_selector{}) #endif // !TUNE_BASE ); _CCCL_TRY_CUDA_API( cub::DeviceScan::ExclusiveScan, "ExclusiveScan failed", d_input, d_output, op_t{}, init_value_t{}, static_cast(input.size()), env); }); } catch (const std::bad_alloc&) { state.skip("Skipping: out of memory."); } // __half and __nv_bfloat16 are added for full (non-tuning) runs; CUB has fast paths for them (see #9587). #ifdef TUNE_T using value_types = nvbench::type_list; #else using value_types = push_back_t; #endif NVBENCH_BENCH_TYPES(basic, NVBENCH_TYPE_AXES(value_types, scan_offset_types)) .set_name("base") .set_type_axes_names({"T{ct}", "OffsetT{ct}"}) .add_int64_power_of_two_axis("Elements{io}", nvbench::range(16, 32, 4));