mirror of
https://github.com/NVIDIA/nvbench.git
synced 2026-04-28 18:51:13 +00:00
Add int64_axis.
This commit is contained in:
@@ -1,3 +1,7 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.18)
|
||||||
|
|
||||||
|
project(nvbench CUDA)
|
||||||
|
|
||||||
include(CPM)
|
include(CPM)
|
||||||
|
|
||||||
CPMAddPackage(
|
CPMAddPackage(
|
||||||
@@ -23,9 +27,5 @@ CPMAddPackage(
|
|||||||
# properties...Resorting to brute force to unblock.
|
# properties...Resorting to brute force to unblock.
|
||||||
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAG} -std=c++17")
|
set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAG} -std=c++17")
|
||||||
|
|
||||||
add_library(nvbench INTERFACE)
|
add_subdirectory(nvbench)
|
||||||
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)
|
add_subdirectory(testing)
|
||||||
|
|||||||
13
nvbench/CMakeLists.txt
Normal file
13
nvbench/CMakeLists.txt
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
set(srcs
|
||||||
|
axis_base.cu
|
||||||
|
int64_axis.cu
|
||||||
|
)
|
||||||
|
|
||||||
|
# TODO shared may be a good idea to reduce compilation overhead for large
|
||||||
|
# benchmark libraries.
|
||||||
|
add_library(nvbench STATIC ${srcs})
|
||||||
|
# TODO generator expression for installed paths
|
||||||
|
target_include_directories(nvbench PUBLIC "${nvbench_SOURCE_DIR}")
|
||||||
|
target_link_libraries(nvbench PRIVATE fmt::fmt)
|
||||||
|
target_link_libraries(nvbench INTERFACE benchmark_main)
|
||||||
|
set_target_properties(nvbench PROPERTIES COMPILE_FEATURES cuda_std_17)
|
||||||
8
nvbench/axis_base.cu
Normal file
8
nvbench/axis_base.cu
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#include "axis_base.cuh"
|
||||||
|
|
||||||
|
namespace nvbench
|
||||||
|
{
|
||||||
|
|
||||||
|
axis_base::~axis_base() = default;
|
||||||
|
|
||||||
|
} // namespace nvbench
|
||||||
52
nvbench/axis_base.cuh
Normal file
52
nvbench/axis_base.cuh
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace nvbench
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class axis_type
|
||||||
|
{
|
||||||
|
type,
|
||||||
|
int64,
|
||||||
|
float64,
|
||||||
|
string
|
||||||
|
};
|
||||||
|
|
||||||
|
struct axis_base
|
||||||
|
{
|
||||||
|
virtual ~axis_base();
|
||||||
|
|
||||||
|
[[nodiscard]] const std::string &get_name() const { return m_name; }
|
||||||
|
|
||||||
|
[[nodiscard]] axis_type get_type() const { return m_type; }
|
||||||
|
|
||||||
|
[[nodiscard]] std::size_t get_size() const { return this->do_get_size(); }
|
||||||
|
|
||||||
|
[[nodiscard]] std::string get_user_string(std::size_t i) const
|
||||||
|
{
|
||||||
|
return this->do_get_user_string(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] std::string get_user_description(std::size_t i) const
|
||||||
|
{
|
||||||
|
return this->do_get_user_description(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
axis_base(std::string name, axis_type type)
|
||||||
|
: m_name{std::move(name)}
|
||||||
|
, m_type{type}
|
||||||
|
{}
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual std::size_t do_get_size() const = 0;
|
||||||
|
virtual std::string do_get_user_string(std::size_t) const = 0;
|
||||||
|
virtual std::string do_get_user_description(std::size_t) const = 0;
|
||||||
|
|
||||||
|
std::string m_name;
|
||||||
|
axis_type m_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nvbench
|
||||||
52
nvbench/int64_axis.cu
Normal file
52
nvbench/int64_axis.cu
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
#include <nvbench/int64_axis.cuh>
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <stdexcept>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace nvbench
|
||||||
|
{
|
||||||
|
|
||||||
|
int64_axis::~int64_axis() = default;
|
||||||
|
|
||||||
|
void int64_axis::set_inputs(const std::vector<int64_t> &inputs)
|
||||||
|
{
|
||||||
|
m_inputs = inputs;
|
||||||
|
if (!m_is_power_of_two)
|
||||||
|
{
|
||||||
|
m_values = inputs;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_values.resize(inputs.size());
|
||||||
|
|
||||||
|
auto conv = [](int64_t in) -> int64_t {
|
||||||
|
if (in < 0 || in >= 64)
|
||||||
|
{
|
||||||
|
throw std::runtime_error(fmt::format("{}:{}: Input value exceeds valid "
|
||||||
|
"range "
|
||||||
|
"for power-of-two mode. "
|
||||||
|
"Input={} ValidRange=[0, 63]",
|
||||||
|
__FILE__,
|
||||||
|
__LINE__,
|
||||||
|
in));
|
||||||
|
}
|
||||||
|
return 1ll << in;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::transform(inputs.cbegin(), inputs.cend(), m_values.begin(), conv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::string int64_axis::do_get_user_string(std::size_t i) const
|
||||||
|
{
|
||||||
|
return fmt::to_string(m_inputs[i]);
|
||||||
|
}
|
||||||
|
std::string int64_axis::do_get_user_description(std::size_t i) const
|
||||||
|
{
|
||||||
|
return m_is_power_of_two ? fmt::format("2^{} = {}", m_inputs[i], m_values[i])
|
||||||
|
: std::string{};
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nvbench
|
||||||
45
nvbench/int64_axis.cuh
Normal file
45
nvbench/int64_axis.cuh
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <nvbench/axis_base.cuh>
|
||||||
|
#include <nvbench/types.cuh>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace nvbench
|
||||||
|
{
|
||||||
|
|
||||||
|
struct int64_axis final : public axis_base
|
||||||
|
{
|
||||||
|
int64_axis(std::string name, bool is_power_of_two)
|
||||||
|
: axis_base{std::move(name), axis_type::int64}
|
||||||
|
, m_is_power_of_two{is_power_of_two}
|
||||||
|
{}
|
||||||
|
|
||||||
|
~int64_axis() final;
|
||||||
|
|
||||||
|
[[nodiscard]] bool get_is_power_of_two() const { return m_is_power_of_two; }
|
||||||
|
|
||||||
|
void set_inputs(const std::vector<int64_t> &inputs);
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<int64_t> &get_inputs() const
|
||||||
|
{
|
||||||
|
return m_inputs;
|
||||||
|
};
|
||||||
|
|
||||||
|
[[nodiscard]] const std::vector<int64_t> &get_values() const
|
||||||
|
{
|
||||||
|
return m_values;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::size_t do_get_size() const final { return m_inputs.size(); }
|
||||||
|
std::string do_get_user_string(std::size_t) const final;
|
||||||
|
std::string do_get_user_description(std::size_t) const final;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<int64_t> m_inputs;
|
||||||
|
std::vector<int64_t> m_values;
|
||||||
|
bool m_is_power_of_two;
|
||||||
|
};
|
||||||
|
|
||||||
|
} //
|
||||||
19
nvbench/types.cuh
Normal file
19
nvbench/types.cuh
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace nvbench
|
||||||
|
{
|
||||||
|
|
||||||
|
using int8_t = std::int8_t;
|
||||||
|
using int16_t = std::int16_t;
|
||||||
|
using int32_t = std::int32_t;
|
||||||
|
using int64_t = std::int64_t;
|
||||||
|
using uint8_t = std::uint8_t;
|
||||||
|
using uint16_t = std::uint16_t;
|
||||||
|
using uint32_t = std::uint32_t;
|
||||||
|
using uint64_t = std::uint64_t;
|
||||||
|
using float32_t = float;
|
||||||
|
using float64_t = double;
|
||||||
|
|
||||||
|
} // namespace nvbench
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
set(test_srcs
|
set(test_srcs
|
||||||
|
int64_axis.cu
|
||||||
type_list.cu
|
type_list.cu
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -6,7 +7,7 @@ foreach(test_src IN LISTS test_srcs)
|
|||||||
get_filename_component(test_name "${test_src}" NAME_WLE)
|
get_filename_component(test_name "${test_src}" NAME_WLE)
|
||||||
string(PREPEND test_name "nvbench.test.")
|
string(PREPEND test_name "nvbench.test.")
|
||||||
add_executable(${test_name} "${test_src}")
|
add_executable(${test_name} "${test_src}")
|
||||||
target_link_libraries(${test_name} PRIVATE nvbench)
|
target_link_libraries(${test_name} PRIVATE nvbench fmt)
|
||||||
set_target_properties(${test_name} PROPERTIES COMPILE_FEATURES cuda_std_17)
|
set_target_properties(${test_name} PROPERTIES COMPILE_FEATURES cuda_std_17)
|
||||||
add_test(NAME ${test_name} COMMAND "$<TARGET_FILE:${test_target}>")
|
add_test(NAME ${test_name} COMMAND "$<TARGET_FILE:${test_target}>")
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|||||||
58
testing/int64_axis.cu
Normal file
58
testing/int64_axis.cu
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include <nvbench/int64_axis.cuh>
|
||||||
|
|
||||||
|
#include "testing/test_asserts.cuh"
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
void test_basic()
|
||||||
|
{
|
||||||
|
nvbench::int64_axis axis{"BasicAxis", false};
|
||||||
|
ASSERT(axis.get_name() == "BasicAxis");
|
||||||
|
ASSERT(axis.get_type() == nvbench::axis_type::int64);
|
||||||
|
ASSERT(!axis.get_is_power_of_two());
|
||||||
|
|
||||||
|
axis.set_inputs({0, 1, 2, 3, 7, 6, 5, 4});
|
||||||
|
ASSERT(axis.get_size() == 8);
|
||||||
|
|
||||||
|
std::vector<nvbench::int64_t> ref{0, 1, 2, 3, 7, 6, 5, 4};
|
||||||
|
ASSERT(axis.get_inputs() == ref);
|
||||||
|
ASSERT(axis.get_values() == ref);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
ASSERT(axis.get_user_string(i) == fmt::to_string(ref[i]));
|
||||||
|
ASSERT(axis.get_user_description(i).empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_power_of_two()
|
||||||
|
{
|
||||||
|
nvbench::int64_axis axis{"POTAxis", true};
|
||||||
|
ASSERT(axis.get_name() == "POTAxis");
|
||||||
|
ASSERT(axis.get_type() == nvbench::axis_type::int64);
|
||||||
|
ASSERT(axis.get_is_power_of_two());
|
||||||
|
|
||||||
|
axis.set_inputs({0, 1, 2, 3, 7, 6, 5, 4});
|
||||||
|
ASSERT(axis.get_size() == 8);
|
||||||
|
|
||||||
|
std::vector<nvbench::int64_t> ref_inputs{0, 1, 2, 3, 7, 6, 5, 4};
|
||||||
|
std::vector<nvbench::int64_t> ref_values{1, 2, 4, 8, 128, 64, 32, 16};
|
||||||
|
ASSERT(axis.get_inputs() == ref_inputs);
|
||||||
|
ASSERT(axis.get_values() == ref_values);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
fmt::print("{}: {}\n", i, axis.get_user_description(i));
|
||||||
|
ASSERT(axis.get_user_string(i) == fmt::to_string(ref_inputs[i]));
|
||||||
|
ASSERT(axis.get_user_description(i) ==
|
||||||
|
fmt::format("2^{} = {}", ref_inputs[i], ref_values[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test_basic();
|
||||||
|
test_power_of_two();
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
||||||
31
testing/test_asserts.cuh
Normal file
31
testing/test_asserts.cuh
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
|
||||||
|
#define ASSERT(cond) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (cond) \
|
||||||
|
{} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
fmt::print("{}:{}: Assertion failed ({}).\n", __FILE__, __LINE__, #cond); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
#define ASSERT_MSG(cond, msg) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
if (cond) \
|
||||||
|
{} \
|
||||||
|
else \
|
||||||
|
{ \
|
||||||
|
fmt::print("{}:{}: Test assertion failed ({}) {}\n", \
|
||||||
|
__FILE__, \
|
||||||
|
__LINE__, \
|
||||||
|
#cond, \
|
||||||
|
msg); \
|
||||||
|
exit(EXIT_FAILURE); \
|
||||||
|
} \
|
||||||
|
} while (false)
|
||||||
Reference in New Issue
Block a user