Add int64_axis.

This commit is contained in:
Allison Vacanti
2020-12-21 20:31:12 -05:00
parent 48bd9c9dc4
commit 13dc404d56
10 changed files with 285 additions and 6 deletions

View File

@@ -1,3 +1,7 @@
cmake_minimum_required(VERSION 3.18)
project(nvbench CUDA)
include(CPM)
CPMAddPackage(
@@ -23,9 +27,5 @@ CPMAddPackage(
# 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(nvbench)
add_subdirectory(testing)

13
nvbench/CMakeLists.txt Normal file
View 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
View 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
View 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
View 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
View 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
View 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

View File

@@ -1,4 +1,5 @@
set(test_srcs
int64_axis.cu
type_list.cu
)
@@ -6,7 +7,7 @@ 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)
target_link_libraries(${test_name} PRIVATE nvbench fmt)
set_target_properties(${test_name} PROPERTIES COMPILE_FEATURES cuda_std_17)
add_test(NAME ${test_name} COMMAND "$<TARGET_FILE:${test_target}>")
endforeach()

58
testing/int64_axis.cu Normal file
View 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
View 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)