Implement/test mutable int64_axis.

This commit is contained in:
Allison Vacanti
2021-02-03 13:32:19 -05:00
parent 36de02d2be
commit e732e50120
4 changed files with 271 additions and 15 deletions

View File

@@ -40,8 +40,8 @@ void axes_metadata::add_int64_axis(std::string name,
std::vector<nvbench::int64_t> data,
nvbench::int64_axis_flags flags)
{
auto axis = std::make_unique<nvbench::int64_axis>(std::move(name), flags);
axis->set_inputs(std::move(data));
auto axis = std::make_unique<nvbench::int64_axis>(std::move(name));
axis->set_inputs(std::move(data), flags);
m_axes.push_back(std::move(axis));
}

View File

@@ -11,9 +11,11 @@ namespace nvbench
int64_axis::~int64_axis() = default;
void int64_axis::set_inputs(std::vector<int64_t> inputs)
void int64_axis::set_inputs(std::vector<int64_t> inputs, int64_axis_flags flags)
{
m_inputs = std::move(inputs);
m_flags = flags;
if (!this->is_power_of_two())
{
m_values = m_inputs;

View File

@@ -26,11 +26,11 @@ namespace nvbench
struct int64_axis final : public axis_base
{
int64_axis(std::string name, int64_axis_flags flags = int64_axis_flags::none)
explicit int64_axis(std::string name)
: axis_base{std::move(name), axis_type::int64}
, m_inputs{}
, m_values{}
, m_flags{flags}
, m_flags{int64_axis_flags::none}
{}
~int64_axis() final;
@@ -40,34 +40,36 @@ struct int64_axis final : public axis_base
return static_cast<bool>(m_flags & int64_axis_flags::power_of_two);
}
void set_inputs(std::vector<int64_t> inputs);
void set_inputs(std::vector<int64_t> inputs,
int64_axis_flags flags = int64_axis_flags::none);
[[nodiscard]] const std::vector<int64_t> &get_inputs() const
{
return m_inputs;
};
[[nodiscard]] int64_t get_value(std::size_t i) const
{
return m_values[i];
};
[[nodiscard]] int64_t get_value(std::size_t i) const { return m_values[i]; };
[[nodiscard]] const std::vector<int64_t> &get_values() const
{
return m_values;
};
int64_axis_flags get_flags() const { return m_flags; }
// Helper functions for pow2 conversions:
static nvbench::int64_t compute_pow2(nvbench::int64_t exponent)
{
return 1ll << exponent;
}
// UB if value < 0.
static nvbench::int64_t compute_log2(nvbench::int64_t value)
{
// TODO use <bit> functions in C++20
nvbench::uint64_t bits = static_cast<nvbench::uint64_t>(value);
// TODO use <bit> functions in C++20?
nvbench::uint64_t bits = static_cast<nvbench::int64_t>(value);
nvbench::int64_t exponent = 0;
while (bits >>= 1)
while ((bits >>= 1) != 0ull)
{
++exponent;
}

View File

@@ -68,8 +68,9 @@ void test_basic()
void test_power_of_two()
{
nvbench::int64_axis axis{"POTAxis", nvbench::int64_axis_flags::power_of_two};
axis.set_inputs({0, 1, 2, 3, 7, 6, 5, 4});
nvbench::int64_axis axis{"POTAxis"};
axis.set_inputs({0, 1, 2, 3, 7, 6, 5, 4},
nvbench::int64_axis_flags::power_of_two);
const std::vector<nvbench::int64_t> ref_inputs{0, 1, 2, 3, 7, 6, 5, 4};
const std::vector<nvbench::int64_t> ref_values{1, 2, 4, 8, 128, 64, 32, 16};
@@ -108,11 +109,262 @@ void test_power_of_two()
}
}
void test_update_none_to_none()
{
nvbench::int64_axis axis{"TestAxis"};
const std::vector<nvbench::int64_t> ref{0, 1, 2, 3, 7, 6, 5, 4};
axis.set_inputs(ref);
{ // Update a clone with empty values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
clone->set_inputs({});
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(!clone->is_power_of_two());
ASSERT(clone->get_size() == 0);
ASSERT(clone->get_inputs().empty());
ASSERT(clone->get_values().empty());
}
{ // Update a clone with new values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
const std::vector<nvbench::int64_t> update_ref{2, 5, 7, 9};
clone->set_inputs(update_ref);
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(!clone->is_power_of_two());
ASSERT(clone->get_size() == 4);
ASSERT(clone->get_inputs() == update_ref);
ASSERT(clone->get_values() == update_ref);
for (size_t i = 0; i < update_ref.size(); ++i)
{
ASSERT(clone->get_input_string(i) == fmt::to_string(update_ref[i]));
ASSERT(clone->get_description(i).empty());
}
}
// Check that the original axis is unchanged:
ASSERT(axis.get_name() == "TestAxis");
ASSERT(axis.get_type() == nvbench::axis_type::int64);
ASSERT(!axis.is_power_of_two());
ASSERT(axis.get_size() == 8);
ASSERT(axis.get_inputs() == ref);
ASSERT(axis.get_values() == ref);
for (size_t i = 0; i < 8; ++i)
{
ASSERT(axis.get_input_string(i) == fmt::to_string(ref[i]));
ASSERT(axis.get_description(i).empty());
}
}
void test_update_none_to_pow2()
{
nvbench::int64_axis axis{"TestAxis"};
const std::vector<nvbench::int64_t> ref{0, 1, 2, 3, 7, 6, 5, 4};
axis.set_inputs(ref);
{ // Update a clone with empty values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
clone->set_inputs({}, nvbench::int64_axis_flags::power_of_two);
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(clone->is_power_of_two());
ASSERT(clone->get_size() == 0);
ASSERT(clone->get_inputs().empty());
ASSERT(clone->get_values().empty());
}
{ // Update a clone with new values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
const std::vector<nvbench::int64_t> update_inputs{2, 5, 7, 9};
const std::vector<nvbench::int64_t> update_values{4, 32, 128, 512};
clone->set_inputs(update_inputs, nvbench::int64_axis_flags::power_of_two);
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(clone->is_power_of_two());
ASSERT(clone->get_size() == 4);
ASSERT(clone->get_inputs() == update_inputs);
ASSERT(clone->get_values() == update_values);
for (size_t i = 0; i < update_inputs.size(); ++i)
{
ASSERT(clone->get_input_string(i) == fmt::to_string(update_inputs[i]));
ASSERT(clone->get_description(i) ==
fmt::format("2^{} = {}", update_inputs[i], update_values[i]));
}
}
// Check that the original axis is unchanged:
ASSERT(axis.get_name() == "TestAxis");
ASSERT(axis.get_type() == nvbench::axis_type::int64);
ASSERT(!axis.is_power_of_two());
ASSERT(axis.get_size() == 8);
ASSERT(axis.get_inputs() == ref);
ASSERT(axis.get_values() == ref);
for (size_t i = 0; i < 8; ++i)
{
ASSERT(axis.get_input_string(i) == fmt::to_string(ref[i]));
ASSERT(axis.get_description(i).empty());
}
}
void test_update_pow2_to_none()
{
nvbench::int64_axis axis{"TestAxis"};
axis.set_inputs({0, 1, 2, 3, 7, 6, 5, 4},
nvbench::int64_axis_flags::power_of_two);
const std::vector<nvbench::int64_t> ref_inputs{0, 1, 2, 3, 7, 6, 5, 4};
const std::vector<nvbench::int64_t> ref_values{1, 2, 4, 8, 128, 64, 32, 16};
{ // Update a clone with empty values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
clone->set_inputs({});
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(!clone->is_power_of_two());
ASSERT(clone->get_size() == 0);
ASSERT(clone->get_inputs().empty());
ASSERT(clone->get_values().empty());
}
{ // Update a clone with new values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
const std::vector<nvbench::int64_t> update_ref{2, 5, 7, 9};
clone->set_inputs(update_ref);
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(!clone->is_power_of_two());
ASSERT(clone->get_size() == 4);
ASSERT(clone->get_inputs() == update_ref);
ASSERT(clone->get_values() == update_ref);
for (size_t i = 0; i < update_ref.size(); ++i)
{
ASSERT(clone->get_input_string(i) == fmt::to_string(update_ref[i]));
ASSERT(clone->get_description(i).empty());
}
}
// Check that the original axis is unchanged:
ASSERT(axis.get_name() == "TestAxis");
ASSERT(axis.get_type() == nvbench::axis_type::int64);
ASSERT(axis.is_power_of_two());
ASSERT(axis.get_size() == 8);
ASSERT(axis.get_inputs() == ref_inputs);
ASSERT(axis.get_values() == ref_values);
for (size_t i = 0; i < 8; ++i)
{
ASSERT(axis.get_input_string(i) == fmt::to_string(ref_inputs[i]));
ASSERT(axis.get_description(i) ==
fmt::format("2^{} = {}", ref_inputs[i], ref_values[i]));
}
}
void test_update_pow2_to_pow2()
{
nvbench::int64_axis axis{"TestAxis"};
axis.set_inputs({0, 1, 2, 3, 7, 6, 5, 4},
nvbench::int64_axis_flags::power_of_two);
const std::vector<nvbench::int64_t> ref_inputs{0, 1, 2, 3, 7, 6, 5, 4};
const std::vector<nvbench::int64_t> ref_values{1, 2, 4, 8, 128, 64, 32, 16};
{ // Update a clone with empty values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
clone->set_inputs({}, nvbench::int64_axis_flags::power_of_two);
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(clone->is_power_of_two());
ASSERT(clone->get_size() == 0);
ASSERT(clone->get_inputs().empty());
ASSERT(clone->get_values().empty());
}
{ // Update a clone with new values
auto clone_base = axis.clone();
ASSERT(clone_base.get() != nullptr);
auto *clone = dynamic_cast<nvbench::int64_axis *>(clone_base.get());
ASSERT(clone != nullptr);
const std::vector<nvbench::int64_t> update_inputs{2, 5, 7, 9};
const std::vector<nvbench::int64_t> update_values{4, 32, 128, 512};
clone->set_inputs(update_inputs, nvbench::int64_axis_flags::power_of_two);
ASSERT(clone->get_name() == "TestAxis");
ASSERT(clone->get_type() == nvbench::axis_type::int64);
ASSERT(clone->is_power_of_two());
ASSERT(clone->get_size() == 4);
ASSERT(clone->get_inputs() == update_inputs);
ASSERT(clone->get_values() == update_values);
for (size_t i = 0; i < update_inputs.size(); ++i)
{
ASSERT(clone->get_input_string(i) == fmt::to_string(update_inputs[i]));
ASSERT(clone->get_description(i) ==
fmt::format("2^{} = {}", update_inputs[i], update_values[i]));
}
}
// Check that the original axis is unchanged:
ASSERT(axis.get_name() == "TestAxis");
ASSERT(axis.get_type() == nvbench::axis_type::int64);
ASSERT(axis.is_power_of_two());
ASSERT(axis.get_size() == 8);
ASSERT(axis.get_inputs() == ref_inputs);
ASSERT(axis.get_values() == ref_values);
for (size_t i = 0; i < 8; ++i)
{
ASSERT(axis.get_input_string(i) == fmt::to_string(ref_inputs[i]));
ASSERT(axis.get_description(i) ==
fmt::format("2^{} = {}", ref_inputs[i], ref_values[i]));
}
}
int main()
{
test_empty();
test_basic();
test_power_of_two();
test_update_none_to_none();
test_update_none_to_pow2();
test_update_pow2_to_none();
test_update_pow2_to_pow2();
return EXIT_SUCCESS;
}