File: TestStdAlgorithmsMismatch.cpp

package info (click to toggle)
kokkos 4.7.01-2
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 16,636 kB
  • sloc: cpp: 223,676; sh: 2,446; makefile: 2,437; python: 91; fortran: 4; ansic: 2
file content (198 lines) | stat: -rw-r--r-- 6,902 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
//@HEADER
// ************************************************************************
//
//                        Kokkos v. 4.0
//       Copyright (2022) National Technology & Engineering
//               Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
// See https://kokkos.org/LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//@HEADER

#include <TestStdAlgorithmsCommon.hpp>
#include <iterator>
#include <algorithm>
#include <numeric>

namespace Test {
namespace stdalgos {
namespace Mismatch {

namespace KE = Kokkos::Experimental;

std::string value_type_to_string(int) { return "int"; }
std::string value_type_to_string(double) { return "double"; }

template <class Tag, class ValueType>
void print_scenario_details(std::size_t ext1, std::size_t ext2,
                            const std::string& flag) {
  std::cout << "mismatch: "
            << "ext1 = " << ext1 << ", "
            << "ext2 = " << ext2 << ", " << flag << ", "
            << view_tag_to_string(Tag{}) << ", "
            << value_type_to_string(ValueType()) << std::endl;
}

template <class Tag, class ViewType, class... Args>
void run_single_scenario(ViewType view1, ViewType view2,
                         const std::string& flag, Args... args) {
  using value_type = typename ViewType::value_type;
  using exe_space  = typename ViewType::execution_space;
  using aux_view_t = Kokkos::View<value_type*, exe_space>;

  const std::size_t ext1 = view1.extent(0);
  const std::size_t ext2 = view2.extent(0);
  // print_scenario_details<Tag, value_type>(ext1, ext2, flag);

  aux_view_t aux_view1("aux_view1", ext1);
  auto v1_h = create_mirror_view(Kokkos::HostSpace(), aux_view1);
  aux_view_t aux_view2("aux_view2", ext2);
  auto v2_h = create_mirror_view(Kokkos::HostSpace(), aux_view2);

  // note that the checks ext1>0 and ext2>0 are there
  // otherwise we get an error for CUDA NVCC DEBUG CI

  // view is is always filled with 8's
  if (ext1 > 0) {
    for (std::size_t i = 0; i < ext1; ++i) {
      v1_h(i) = static_cast<value_type>(8);
    }
  }

  if (flag == "fill-to-match") {
    if (ext2 > 0) {
      for (std::size_t i = 0; i < ext2; ++i) {
        v2_h(i) = static_cast<value_type>(8);
      }
    }
  }

  else if (flag == "fill-to-mismatch") {
    // need to make them mismatch, so we fill
    // with same value and only modifify the
    // second view arbitrarily at middle point

    if (ext2 > 0) {
      for (std::size_t i = 0; i < ext2; ++i) {
        v2_h(i) = static_cast<value_type>(8);
      }

      // make them mismatch at middle
      v2_h(ext2 / 2) = -5;
    }
  } else {
    FAIL() << "Kokkos: stdalgo: test: mismatch: Invalid string";
  }

  Kokkos::deep_copy(aux_view1, v1_h);
  CopyFunctor<aux_view_t, ViewType> F1(aux_view1, view1);
  Kokkos::parallel_for("copy1", view1.extent(0), F1);

  Kokkos::deep_copy(aux_view2, v2_h);
  CopyFunctor<aux_view_t, ViewType> F2(aux_view2, view2);
  Kokkos::parallel_for("copy2", view2.extent(0), F2);

  // run the std::mismatch on a host copy of the data
  auto view1_h         = create_host_space_copy(view1);
  auto view2_h         = create_host_space_copy(view2);
  auto f1_h            = KE::cbegin(view1_h);
  auto l1_h            = KE::cend(view1_h);
  auto f2_h            = KE::cbegin(view2_h);
  auto l2_h            = KE::cend(view2_h);
  auto std_res         = std::mismatch(f1_h, l1_h, f2_h, l2_h, args...);
  const auto std_diff1 = std_res.first - f1_h;
  const auto std_diff2 = std_res.second - f2_h;

  {
    // check our overloads with iterators
    auto f1      = KE::cbegin(view1);
    auto l1      = KE::cend(view1);
    auto f2      = KE::cbegin(view2);
    auto l2      = KE::cend(view2);
    auto my_res1 = KE::mismatch(exespace(), f1, l1, f2, l2, args...);
    auto my_res2 = KE::mismatch("label", exespace(), f1, l1, f2, l2, args...);
    const auto my_diff11 = my_res1.first - f1;
    const auto my_diff12 = my_res1.second - f2;
    const auto my_diff21 = my_res2.first - f1;
    const auto my_diff22 = my_res2.second - f2;
    ASSERT_EQ(my_diff11, std_diff1);
    ASSERT_EQ(my_diff12, std_diff2);
    ASSERT_EQ(my_diff21, std_diff1);
    ASSERT_EQ(my_diff22, std_diff2);
  }

  {
    // check our overloads with views
    auto my_res1 = KE::mismatch(exespace(), view1, view2, args...);
    auto my_res2 = KE::mismatch("label", exespace(), view1, view2, args...);
    const auto my_diff11 = my_res1.first - KE::begin(view1);
    const auto my_diff12 = my_res1.second - KE::begin(view2);
    const auto my_diff21 = my_res2.first - KE::begin(view1);
    const auto my_diff22 = my_res2.second - KE::begin(view2);
    ASSERT_EQ(my_diff11, std_diff1);
    ASSERT_EQ(my_diff12, std_diff2);
    ASSERT_EQ(my_diff21, std_diff1);
    ASSERT_EQ(my_diff22, std_diff2);
  }
}

template <class Tag, class ValueType>
void run_all_scenarios() {
  using vecs_t = std::vector<std::string>;

  const std::map<std::string, std::size_t> scenarios = {
      {"empty", 0},  {"one-element", 1}, {"two-elements", 2},
      {"small", 11}, {"medium", 21103},  {"large", 101513}};

  for (const auto& scenario : scenarios) {
    {
      const std::size_t view1_ext = scenario.second;
      auto view1 = create_view<ValueType>(Tag{}, view1_ext, "mismatch_view_1");

      // for each view1 scenario, I want to test the case of a
      // second view that is smaller, equal size and greater than the view1
      const vecs_t view2cases = (scenario.first != "empty")
                                    ? vecs_t({"smaller", "equalsize", "larger"})
                                    : vecs_t({"equalsize", "larger"});

      for (auto it2 : view2cases) {
        std::size_t view2_ext = view1_ext;

        // modify extent of view2 based on what we want
        if (std::string(it2) == "smaller") {
          view2_ext -= 1;
        } else if (std::string(it2) == "larger") {
          view2_ext += 3;
        }

        auto view2 =
            create_view<ValueType>(Tag{}, view2_ext, "mismatch_view_2");

        // and now we want to test both the case view1 and view2 match,
        // as well as the case where they don't match
        for (const auto& it3 : {"fill-to-match", "fill-to-mismatch"}) {
          // run to use default predicate
          run_single_scenario<Tag>(view1, view2, it3);

          // run using an arbitrary predicate
          using predicate_type = IsEqualFunctor<ValueType>;
          run_single_scenario<Tag>(view1, view2, it3, predicate_type());
        }
      }
    }
  }
}

TEST(std_algorithms_mismatch_test, test) {
  run_all_scenarios<DynamicTag, double>();
  run_all_scenarios<StridedThreeTag, int>();
}

}  // namespace Mismatch
}  // namespace stdalgos
}  // namespace Test