From 9f6404bac66d813ff084c3a1b8323e18933b7923 Mon Sep 17 00:00:00 2001 From: Allison Vacanti Date: Tue, 16 Mar 2021 15:12:53 -0400 Subject: [PATCH] Pad range max for floating point types. This avoids an annoying case where the max value is dropped due to rounding errors. Adds a few other missing test cases for `nvbench::range`, too. Fixes #3. --- nvbench/range.cuh | 4 +++ testing/CMakeLists.txt | 1 + testing/range.cu | 82 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+) create mode 100644 testing/range.cu diff --git a/nvbench/range.cuh b/nvbench/range.cuh index 12d4d2d..f0e8255 100644 --- a/nvbench/range.cuh +++ b/nvbench/range.cuh @@ -38,6 +38,10 @@ template > auto range(InT start, InT end, InT stride = InT{1}) { + if constexpr (std::is_floating_point_v) + { // Pad end to account for floating point errors: + end += (stride / InT{2}); + } using result_t = std::vector; result_t result; for (; start <= end; start += stride) diff --git a/testing/CMakeLists.txt b/testing/CMakeLists.txt index a983dba..93dda8e 100644 --- a/testing/CMakeLists.txt +++ b/testing/CMakeLists.txt @@ -9,6 +9,7 @@ set(test_srcs int64_axis.cu named_values.cu option_parser.cu + range.cu runner.cu state.cu state_generator.cu diff --git a/testing/range.cu b/testing/range.cu new file mode 100644 index 0000000..35e158e --- /dev/null +++ b/testing/range.cu @@ -0,0 +1,82 @@ +/* + * Copyright 2021 NVIDIA Corporation + * + * Licensed under the Apache License, Version 2.0 with the LLVM exception + * (the "License"); you may not use this file except in compliance with + * the License. + * + * You may obtain a copy of the License at + * + * http://llvm.org/foundation/relicensing/LICENSE.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include "test_asserts.cuh" + +void test_basic() +{ + ASSERT((nvbench::range(0, 6) == + std::vector{0, 1, 2, 3, 4, 5, 6})); + ASSERT((nvbench::range(0, 6, 1) == + std::vector{0, 1, 2, 3, 4, 5, 6})); + ASSERT( + (nvbench::range(0, 6, 2) == std::vector{0, 2, 4, 6})); + ASSERT((nvbench::range(0, 6, 3) == std::vector{0, 3, 6})); + ASSERT((nvbench::range(0, 6, 4) == std::vector{0, 4})); + ASSERT((nvbench::range(0, 6, 5) == std::vector{0, 5})); + ASSERT((nvbench::range(0, 6, 7) == std::vector{0})); +} + +void test_result_type() +{ + // All ints should turn into int64 by default: + ASSERT((std::is_same_v>)); + ASSERT((std::is_same_v>)); + ASSERT((std::is_same_v>)); + + // All floats should turn into float64 by default: + ASSERT((std::is_same_v>)); + ASSERT((std::is_same_v>)); + + // Other types may be explicitly specified: + ASSERT((std::is_same_v(0.f, 1.f)), + std::vector>)); + ASSERT((std::is_same_v< + decltype(nvbench::range(0, 1)), + std::vector>)); +} + +void test_fp_tolerance() +{ + // Make sure that the range is padded a bit for floats to prevent rounding + // errors from skipping `end`. This test will trigger failures without + // the padding. + const nvbench::float32_t start = 0.1; + const nvbench::float32_t stride = 1e-4; + for (std::size_t size = 1; size < 1024; ++size) + { + const nvbench::float32_t end = start + stride * (size - 1); + ASSERT_MSG(nvbench::range(start, end, stride).size() == size, + "size={}", size); + } +} + +int main() +{ + test_basic(); + test_result_type(); + test_fp_tolerance(); +}