mirror of
https://github.com/NVIDIA/nvbench.git
synced 2026-04-19 22:38:52 +00:00
Add nvbench::type_list.
This commit is contained in:
@@ -13,6 +13,13 @@ CPMAddPackage(
|
||||
"RUN_HAVE_STD_REGEX 0"
|
||||
)
|
||||
|
||||
# Why does CMake make it so difficult to enable cuda C++17 with interface
|
||||
# properties...Resorting to brute force to unblock.
|
||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAG} -std=c++17")
|
||||
|
||||
add_library(nvbench INTERFACE)
|
||||
target_include_directories(nvbench INTERFACE "${CMAKE_CURRENT_LIST_DIR}")
|
||||
target_link_libraries(nvbench INTERFACE benchmark_main)
|
||||
set_target_properties(nvbench PROPERTIES INTERFACE_COMPILE_FEATURES cuda_std_17)
|
||||
|
||||
add_subdirectory(testing)
|
||||
|
||||
84
nvbench/detail/type_list_impl.h
Normal file
84
nvbench/detail/type_list_impl.h
Normal file
@@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <tuple>
|
||||
|
||||
namespace nvbench
|
||||
{
|
||||
|
||||
template <typename... Ts>
|
||||
struct type_list;
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <std::size_t I, typename... Ts>
|
||||
auto get(nvbench::type_list<Ts...>)
|
||||
-> std::tuple_element_t<I, std::tuple<Ts...>>;
|
||||
|
||||
template <typename... Ts, typename... Us>
|
||||
auto concat(nvbench::type_list<Ts...>, nvbench::type_list<Us...>)
|
||||
-> nvbench::type_list<Ts..., Us...>;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <typename T, typename TLs>
|
||||
struct prepend_each;
|
||||
|
||||
template <typename T>
|
||||
struct prepend_each<T, nvbench::type_list<>>
|
||||
{
|
||||
using type = nvbench::type_list<>;
|
||||
};
|
||||
|
||||
template <typename T, typename TL, typename... TLTail>
|
||||
struct prepend_each<T, nvbench::type_list<TL, TLTail...>>
|
||||
{
|
||||
using cur = decltype(detail::concat(nvbench::type_list<T>{}, TL{}));
|
||||
using next =
|
||||
typename detail::prepend_each<T, nvbench::type_list<TLTail...>>::type;
|
||||
using type = decltype(detail::concat(nvbench::type_list<cur>{}, next{}));
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
template <typename TLs>
|
||||
struct cartesian_product;
|
||||
|
||||
template <>
|
||||
struct cartesian_product<nvbench::type_list<>>
|
||||
{
|
||||
using type = nvbench::type_list<>;
|
||||
};
|
||||
|
||||
template <typename... TLTail>
|
||||
struct cartesian_product<nvbench::type_list<nvbench::type_list<>, TLTail...>>
|
||||
{
|
||||
using type = nvbench::type_list<>;
|
||||
};
|
||||
|
||||
template <typename T, typename... Ts>
|
||||
struct cartesian_product<nvbench::type_list<nvbench::type_list<T, Ts...>>>
|
||||
{
|
||||
using cur = nvbench::type_list<nvbench::type_list<T>>;
|
||||
using next = typename detail::cartesian_product<
|
||||
nvbench::type_list<nvbench::type_list<Ts...>>>::type;
|
||||
using type = decltype(detail::concat(cur{}, next{}));
|
||||
};
|
||||
|
||||
template <typename T, typename... Tail, typename TL, typename... TLTail>
|
||||
struct cartesian_product<
|
||||
nvbench::type_list<nvbench::type_list<T, Tail...>, TL, TLTail...>>
|
||||
{
|
||||
using tail_prod =
|
||||
typename detail::cartesian_product<nvbench::type_list<TL, TLTail...>>::type;
|
||||
using cur = typename detail::prepend_each<T, tail_prod>::type;
|
||||
using next = typename detail::cartesian_product<
|
||||
nvbench::type_list<nvbench::type_list<Tail...>, TL, TLTail...>>::type;
|
||||
using type = decltype(detail::concat(cur{}, next{}));
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace tl
|
||||
} // namespace nvbench
|
||||
93
nvbench/type_list.h
Normal file
93
nvbench/type_list.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#pragma once
|
||||
|
||||
#include "detail/type_list_impl.h"
|
||||
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
|
||||
namespace nvbench
|
||||
{
|
||||
|
||||
template <typename... Ts>
|
||||
struct type_list
|
||||
{};
|
||||
|
||||
namespace tl
|
||||
{
|
||||
|
||||
/**
|
||||
* Get the TypeList entry at the specified index.
|
||||
*
|
||||
* ```c++
|
||||
* using TL = nvbench::type_list<T0, T1, T2, T3, T4>;
|
||||
* static_assert(std::is_same_v<nvbench::tl::get<0, TL>, T0>);
|
||||
* static_assert(std::is_same_v<nvbench::tl::get<1, TL>, T1>);
|
||||
* static_assert(std::is_same_v<nvbench::tl::get<2, TL>, T2>);
|
||||
* static_assert(std::is_same_v<nvbench::tl::get<3, TL>, T3>);
|
||||
* static_assert(std::is_same_v<nvbench::tl::get<4, TL>, T4>);
|
||||
* ```
|
||||
*/
|
||||
template <std::size_t Index, typename TypeList>
|
||||
using get = decltype(detail::get<Index>(TypeList{}));
|
||||
|
||||
/**
|
||||
* Concatenate two type_lists.
|
||||
*
|
||||
* ```c++
|
||||
* using TL01 = nvbench::type_list<T0, T1>;
|
||||
* using TL23 = nvbench::type_list<T2, T3>;
|
||||
* using TL0123 = nvbench::type_list<T0, T1, T2, T3>;
|
||||
* static_assert(std::is_same_v<nvbench::tl::concat<TL01, TL23>, T0123>);
|
||||
* ```
|
||||
*/
|
||||
template <typename TypeList1, typename TypeList2>
|
||||
using concat = decltype(detail::concat(TypeList1{}, TypeList2{}));
|
||||
|
||||
/**
|
||||
* Given a type `T` and a type_list of type_lists `TypeLists`, create
|
||||
* a new type_list containing each entry from TypeLists prepended with T.
|
||||
*
|
||||
* ```c++
|
||||
* using TypeLists = type_list<type_list<T0, T1>,
|
||||
* type_list<T2, T3>>;
|
||||
* using Result = nvbench::tl::prepend_each<T, TypeLists>;
|
||||
* using Reference = type_list<type_list<T, T0, T1>,
|
||||
* type_list<T, T2, T3>>;
|
||||
* static_assert(std::is_same_v<Result, Reference>);
|
||||
* ```
|
||||
*/
|
||||
template <typename T, typename TypeLists>
|
||||
using prepend_each = typename detail::prepend_each<T, TypeLists>::type;
|
||||
|
||||
/**
|
||||
* Given a type_list of type_lists, compute the cartesian product across all
|
||||
* nested type_lists. Supports arbitrary numbers and sizes of nested type_lists.
|
||||
*
|
||||
* Beware that the result grows very quickly in size.
|
||||
*
|
||||
* ```c++
|
||||
* using T01 = type_list<T0, T1>;
|
||||
* using U012 = type_list<U0, U1, U2>;
|
||||
* using V01 = type_list<V0, V1>;
|
||||
* using TLs = type_list<T01, U012, V01>;
|
||||
* using CartProd = type_list<type_list<T0, U0, V0>,
|
||||
* type_list<T0, U0, V1>,
|
||||
* type_list<T0, U1, V0>,
|
||||
* type_list<T0, U1, V1>,
|
||||
* type_list<T0, U2, V0>,
|
||||
* type_list<T0, U2, V1>,
|
||||
* type_list<T1, U0, V0>,
|
||||
* type_list<T1, U0, V1>,
|
||||
* type_list<T1, U1, V0>,
|
||||
* type_list<T1, U1, V1>,
|
||||
* type_list<T1, U2, V0>,
|
||||
* type_list<T1, U2, V1>>;
|
||||
* static_assert(std::is_same_v<bench::tl::cartesian_product<TLs>, CartProd>);
|
||||
* ```
|
||||
*/
|
||||
template <typename TLs>
|
||||
using cartesian_product = typename detail::cartesian_product<TLs>::type;
|
||||
|
||||
} // namespace tl
|
||||
|
||||
} // namespace nvbench
|
||||
12
testing/CMakeLists.txt
Normal file
12
testing/CMakeLists.txt
Normal file
@@ -0,0 +1,12 @@
|
||||
set(test_srcs
|
||||
type_list.cu
|
||||
)
|
||||
|
||||
foreach(test_src IN LISTS test_srcs)
|
||||
get_filename_component(test_name "${test_src}" NAME_WLE)
|
||||
string(PREPEND test_name "nvbench.test.")
|
||||
add_executable(${test_name} "${test_src}")
|
||||
target_link_libraries(${test_name} PRIVATE nvbench)
|
||||
set_target_properties(${test_name} PROPERTIES COMPILE_FEATURES cuda_std_17)
|
||||
add_test(NAME ${test_name} COMMAND "$<TARGET_FILE:${test_target}>")
|
||||
endforeach()
|
||||
84
testing/type_list.cu
Normal file
84
testing/type_list.cu
Normal file
@@ -0,0 +1,84 @@
|
||||
#include <nvbench/type_list.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
// Unique, numbered types for testing type_list functionality.
|
||||
using T0 = std::integral_constant<std::size_t, 0>;
|
||||
using T1 = std::integral_constant<std::size_t, 1>;
|
||||
using T2 = std::integral_constant<std::size_t, 2>;
|
||||
using T3 = std::integral_constant<std::size_t, 3>;
|
||||
using T4 = std::integral_constant<std::size_t, 4>;
|
||||
using T5 = std::integral_constant<std::size_t, 5>;
|
||||
using T6 = std::integral_constant<std::size_t, 6>;
|
||||
using T7 = std::integral_constant<std::size_t, 7>;
|
||||
|
||||
struct test_get
|
||||
{
|
||||
using TL = nvbench::type_list<T0, T1, T2, T3, T4, T5>;
|
||||
static_assert(std::is_same_v<T0, nvbench::tl::get<0, TL>>);
|
||||
static_assert(std::is_same_v<T1, nvbench::tl::get<1, TL>>);
|
||||
static_assert(std::is_same_v<T2, nvbench::tl::get<2, TL>>);
|
||||
static_assert(std::is_same_v<T3, nvbench::tl::get<3, TL>>);
|
||||
static_assert(std::is_same_v<T4, nvbench::tl::get<4, TL>>);
|
||||
static_assert(std::is_same_v<T5, nvbench::tl::get<5, TL>>);
|
||||
};
|
||||
|
||||
struct test_concat
|
||||
{
|
||||
using TLEmpty = nvbench::type_list<>;
|
||||
using TL012 = nvbench::type_list<T0, T1, T2>;
|
||||
using TL765 = nvbench::type_list<T7, T6, T5>;
|
||||
|
||||
struct empty_tests
|
||||
{
|
||||
static_assert(
|
||||
std::is_same_v<nvbench::tl::concat<TLEmpty, TLEmpty>, TLEmpty>);
|
||||
static_assert(std::is_same_v<nvbench::tl::concat<TLEmpty, TL012>, TL012>);
|
||||
static_assert(std::is_same_v<nvbench::tl::concat<TL012, TLEmpty>, TL012>);
|
||||
};
|
||||
|
||||
static_assert(std::is_same_v<nvbench::tl::concat<TL012, TL765>,
|
||||
nvbench::type_list<T0, T1, T2, T7, T6, T5>>);
|
||||
};
|
||||
|
||||
struct test_prepend_each
|
||||
{
|
||||
using T = void;
|
||||
using T01 = nvbench::type_list<T0, T1>;
|
||||
using T23 = nvbench::type_list<T2, T3>;
|
||||
using TLs = nvbench::type_list<T01, T23>;
|
||||
|
||||
using Expected = nvbench::type_list<nvbench::type_list<T, T0, T1>,
|
||||
nvbench::type_list<T, T2, T3>>;
|
||||
static_assert(std::is_same_v<nvbench::tl::prepend_each<T, TLs>, Expected>);
|
||||
};
|
||||
|
||||
struct test_cartesian_product
|
||||
{
|
||||
using U0 = T2;
|
||||
using U1 = T3;
|
||||
using U2 = T4;
|
||||
using V0 = T5;
|
||||
using V1 = T6;
|
||||
using T01 = nvbench::type_list<T0, T1>;
|
||||
using U012 = nvbench::type_list<U0, U1, U2>;
|
||||
using V01 = nvbench::type_list<V0, V1>;
|
||||
using TLs = nvbench::type_list<T01, U012, V01>;
|
||||
using CartProd = nvbench::type_list<nvbench::type_list<T0, U0, V0>,
|
||||
nvbench::type_list<T0, U0, V1>,
|
||||
nvbench::type_list<T0, U1, V0>,
|
||||
nvbench::type_list<T0, U1, V1>,
|
||||
nvbench::type_list<T0, U2, V0>,
|
||||
nvbench::type_list<T0, U2, V1>,
|
||||
nvbench::type_list<T1, U0, V0>,
|
||||
nvbench::type_list<T1, U0, V1>,
|
||||
nvbench::type_list<T1, U1, V0>,
|
||||
nvbench::type_list<T1, U1, V1>,
|
||||
nvbench::type_list<T1, U2, V0>,
|
||||
nvbench::type_list<T1, U2, V1>>;
|
||||
static_assert(std::is_same_v<nvbench::tl::cartesian_product<TLs>, CartProd>);
|
||||
};
|
||||
|
||||
// This test only has static asserts.
|
||||
int main() {}
|
||||
Reference in New Issue
Block a user