// MIT License // // Copyright (c) 2024-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_custom_type.hpp" #include "../common/utils_device_ptr.hpp" #include #include #include #include #include #ifndef BENCHMARK_CONFIG_TUNING #include #endif #include #include #include #ifdef BENCHMARK_CONFIG_TUNING #include #else #include #include #include #endif template struct type_arr { using type = First; using next = type_arr; }; template struct type_arr { using type = First; }; template using void_type = void; template constexpr bool is_type_arr_end = true; template constexpr bool is_type_arr_end> = false; template struct count_equal_to { std::string name() const { return "count_equal_to<" + std::to_string(Value) + ">"; } constexpr size_t resolve(size_t) const { return Value; } }; template struct count_is_percent_of_size { std::string name() const { return "count_is_percent_of_size<" + std::to_string(Value) + ">"; } constexpr size_t resolve(size_t items) const { return items * Value / 100; } }; 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("threshold", config.threshold); } } template struct device_search_n_benchmark : public primbench::benchmark_interface { primbench::json meta() const override { return primbench::json{} .add("lvl", "device") .add("algo", "device_search_n") .add("data_type", primbench::name()) .add("count_calculator", CountCalculator{}.name()) .add("cfg", config_name()); } void run(primbench::state& state) override { const auto& stream = state.stream; const auto& size_byte = state.size; InputType h_noise{0}; InputType h_value{1}; common::device_ptr d_temp_storage; size_t temp_storage_size = 0; size_t count; std::vector input{}; common::device_ptr d_input; common::device_ptr d_output(1); common::device_ptr d_value(std::vector{h_value}, stream); size_t items = size_byte / sizeof(InputType); count = CountCalculator{}.resolve(items); size_t cur_tile = 0; size_t last_tile = items / count - 1; input = std::vector(items, h_value); while(cur_tile != last_tile) { input[cur_tile * count + count - 1] = h_noise; ++cur_tile; } d_input.store_async(input, stream); auto launch_search_n = [&]() { HIP_CHECK(::rocprim::search_n(d_temp_storage.get(), temp_storage_size, d_input.get(), d_output.get(), items, count, d_value.get(), rocprim::equal_to{}, stream, false)); }; // allocate temp memory launch_search_n(); d_temp_storage.resize_async(temp_storage_size, stream); state.set_items(items); state.add_reads(items); state.run([&] { launch_search_n(); }); } }; #ifdef BENCHMARK_CONFIG_TUNING template struct device_search_n_benchmark_generator { static void create(std::vector>& storage) { using config = rocprim::search_n_config; storage.emplace_back( std::make_unique, config>>()); storage.emplace_back( std::make_unique, config>>()); storage.emplace_back( std::make_unique, config>>()); storage.emplace_back( std::make_unique, config>>()); storage.emplace_back( std::make_unique, config>>()); storage.emplace_back( std::make_unique< device_search_n_benchmark, config>>()); storage.emplace_back( std::make_unique< device_search_n_benchmark, config>>()); } }; #endif // BENCHMARK_CONFIG_TUNING