File: TestHIP_InterOp_Graph.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 (154 lines) | stat: -rw-r--r-- 4,801 bytes parent folder | download
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
//@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 <filesystem>
#include <fstream>
#include <regex>

#include <TestHIP_Category.hpp>
#include <Kokkos_Core.hpp>
#include <Kokkos_Graph.hpp>

#include <gtest/gtest.h>

namespace {

template <typename ViewType>
struct Increment {
  ViewType data;

  KOKKOS_FUNCTION
  void operator()(const int) const { ++data(); }
};

// This test checks the promises of Kokkos::Graph against its
// underlying HIP native objects.
TEST(TEST_CATEGORY, graph_promises_on_native_objects) {
#if !defined(KOKKOS_IMPL_HIP_NATIVE_GRAPH)
  GTEST_SKIP() << "This test will not work without native graph support";
#else
  Kokkos::Experimental::Graph<Kokkos::HIP> graph{};
  // Before instantiation, the HIP graph is valid, but the HIP executable
  // graph is still null.
  hipGraph_t hip_graph = graph.native_graph();

  ASSERT_NE(hip_graph, nullptr);
  ASSERT_EQ(graph.native_graph_exec(), nullptr);

  // After instantiation, both native objects are valid.
  graph.instantiate();

  hipGraphExec_t hip_graph_exec = graph.native_graph_exec();

  ASSERT_EQ(graph.native_graph(), hip_graph);
  ASSERT_NE(hip_graph_exec, nullptr);

  // Submission should not affect the underlying objects.
  graph.submit();

  ASSERT_EQ(graph.native_graph(), hip_graph);
  ASSERT_EQ(graph.native_graph_exec(), hip_graph_exec);
#endif
}

// Use native HIP graph to generate a DOT representation.
TEST(TEST_CATEGORY, graph_instantiate_and_debug_dot_print) {
#if !defined(KOKKOS_IMPL_HIP_NATIVE_GRAPH)
  GTEST_SKIP() << "This test will not work without native graph support";
#elif defined(_GLIBCXX_RELEASE) && _GLIBCXX_RELEASE < 9
  GTEST_SKIP()
      << "The GNU C++ Library (libstdc++) versions less than 9.1 "
         "require linking with `-lstdc++fs` when using std::filesystem";
#elif defined(_LIBCPP_VERSION) && _LIBCPP_VERSION < 110000
  GTEST_SKIP()
      << "The LLVM C++ Standard Library (libc++) versions less than "
         "11 require linking with `-lc++fs` when using std::filesystem";
#else
  using view_t = Kokkos::View<int, Kokkos::HIP>;

  const Kokkos::HIP exec{};

  view_t data(Kokkos::view_alloc(exec, "witness"));

  Kokkos::Experimental::Graph graph{exec};

  graph.root_node().then_parallel_for(1, Increment<view_t>{data});

  graph.instantiate();

  size_t num_nodes;

  KOKKOS_IMPL_HIP_SAFE_CALL(
      hipGraphGetNodes(graph.native_graph(), nullptr, &num_nodes));

  ASSERT_EQ(num_nodes, 2u);

  // hipGraphDebugDotPrint was introduced in ROCm 5.5
#if (HIP_VERSION_MAJOR > 5) || \
    ((HIP_VERSION_MAJOR > 5) && (HIP_VERSION_MINOR >= 5))
  const auto dot = std::filesystem::temp_directory_path() / "hip_graph.dot";

  KOKKOS_IMPL_HIP_SAFE_CALL(hipGraphDebugDotPrint(
      graph.native_graph(), dot.c_str(), hipGraphDebugDotFlagsVerbose));

  ASSERT_TRUE(std::filesystem::exists(dot));
  ASSERT_GT(std::filesystem::file_size(dot), 0u);

  // We could write a check against the full kernel's function signature, but
  // it would make the test rely too much on internal implementation details.
  // Therefore, we just look for the functor and policy. Note that the
  // signature is mangled in the 'dot' output.
  const std::string expected("[A-Za-z0-9_]+Increment[A-Za-z0-9_]+RangePolicy");

  std::stringstream buffer;
  buffer << std::ifstream(dot).rdbuf();

  ASSERT_TRUE(std::regex_search(buffer.str(), std::regex(expected)))
      << "Could not find expected signature regex " << std::quoted(expected)
      << " in " << dot;
#endif
#endif
}

// Build a Kokkos::Graph from an existing hipGraph_t.
TEST(TEST_CATEGORY, graph_construct_from_native) {
#if !defined(KOKKOS_IMPL_HIP_NATIVE_GRAPH)
  GTEST_SKIP() << "This test will not work without native graph support";
#else
  using view_t = Kokkos::View<int, Kokkos::HIPManagedSpace>;

  hipGraph_t native_graph = nullptr;
  KOKKOS_IMPL_HIP_SAFE_CALL(hipGraphCreate(&native_graph, 0));

  const Kokkos::HIP exec{};

  Kokkos::Experimental::Graph graph_from_native(exec, native_graph);

  ASSERT_EQ(native_graph, graph_from_native.native_graph());

  const view_t data(Kokkos::view_alloc(exec, "witness"));

  graph_from_native.root_node().then_parallel_for(1, Increment<view_t>{data});

  graph_from_native.submit(exec);

  exec.fence();

  ASSERT_EQ(data(), 1);
#endif
}

}  // namespace