// MIT License // // Copyright (c) 2022-2026 Advanced Micro Devices, Inc. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include "primbench.hpp" #include "benchmark_utils.hpp" #include "../common/utils_device_ptr.hpp" #include #include #include #include #include #include #include #include #include constexpr const char* get_reduce_method_name(rocprim::block_reduce_algorithm alg) { switch(alg) { case rocprim::block_reduce_algorithm::raking_reduce: return "raking_reduce"; case rocprim::block_reduce_algorithm::raking_reduce_commutative_only: return "raking_reduce_commutative_only"; case rocprim::block_reduce_algorithm::using_warp_reduce: return "using_warp_reduce"; // Not using `default: ...` because it kills effectiveness of -Wswitch } return "unknown_algorithm"; } template constexpr auto config_name() { if constexpr(std::is_same_v) { return std::string("default"); } else { auto config = Config(); return primbench::json{} .add("bs", config.kernel_config.block_size) .add("ipt", config.kernel_config.items_per_thread) .add("method", get_reduce_method_name(config.block_reduce_method)); } } template, typename Config = rocprim::default_config> struct device_reduce_benchmark : public primbench::benchmark_interface { primbench::json meta() const override { return primbench::json{} .add("lvl", "device") .add("algo", "device_reduce") .add("key_type", primbench::name()) .add("cfg", config_name()); } void run(primbench::state& state) override { const auto& stream = state.stream; const auto& bytes = state.size; const auto& seed = state.seed; size_t items = bytes / sizeof(T); BinaryFunction reduce_op{}; const auto random_range = limit_random_range(0, 1000); std::vector input = get_random_data(items, random_range.first, random_range.second, seed); common::device_ptr d_input(input); common::device_ptr d_output(1); // Allocate temporary storage memory size_t temp_storage_size_bytes; // Get size of d_temp_storage HIP_CHECK(rocprim::reduce(nullptr, temp_storage_size_bytes, d_input.get(), d_output.get(), T(), items, reduce_op, stream)); common::device_ptr d_temp_storage(temp_storage_size_bytes); state.set_items(items); state.add_reads(items); state.run( [&] { HIP_CHECK(rocprim::reduce(d_temp_storage.get(), temp_storage_size_bytes, d_input.get(), d_output.get(), T(), items, reduce_op, stream)); }); } };