Line data Source code
1 : //@HEADER
2 : // ************************************************************************
3 : //
4 : // Kokkos v. 4.0
5 : // Copyright (2022) National Technology & Engineering
6 : // Solutions of Sandia, LLC (NTESS).
7 : //
8 : // Under the terms of Contract DE-NA0003525 with NTESS,
9 : // the U.S. Government retains certain rights in this software.
10 : //
11 : // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 : // See https://kokkos.org/LICENSE for license information.
13 : // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 : //
15 : //@HEADER
16 :
17 : #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
18 : static_assert(false,
19 : "Including non-public Kokkos header files is not allowed.");
20 : #endif
21 :
22 : #ifndef KOKKOS_VIEW_CHECKING_HPP
23 : #define KOKKOS_VIEW_CHECKING_HPP
24 :
25 : #include <cstring>
26 : #include <Kokkos_Macros.hpp>
27 : #include <Kokkos_Concepts.hpp>
28 : #include <impl/Kokkos_SharedAlloc.hpp>
29 : #include <View/MDSpan/Kokkos_MDSpan_Header.hpp>
30 :
31 : namespace Kokkos::Impl {
32 : // primary template: memory space is accessible, do nothing.
33 : template <class MemorySpace, class AccessSpace,
34 : bool = SpaceAccessibility<AccessSpace, MemorySpace>::accessible>
35 : struct RuntimeCheckBasicViewMemoryAccessViolation {
36 : KOKKOS_FUNCTION RuntimeCheckBasicViewMemoryAccessViolation(
37 : Kokkos::Impl::SharedAllocationTracker const &) {}
38 : };
39 :
40 : // explicit specialization: memory access violation will occur, call abort with
41 : // the specified error message.
42 : template <class MemorySpace, class AccessSpace>
43 : struct RuntimeCheckBasicViewMemoryAccessViolation<MemorySpace, AccessSpace,
44 : false> {
45 : KOKKOS_FUNCTION RuntimeCheckBasicViewMemoryAccessViolation(
46 : Kokkos::Impl::SharedAllocationTracker const &tracker) {
47 : char err[256] =
48 : "Kokkos::View ERROR: attempt to access inaccessible memory space "
49 : "(label=\"";
50 :
51 : KOKKOS_IF_ON_HOST(({
52 : if (tracker.has_record()) {
53 : strncat(err, tracker.template get_label<void>().c_str(), 128);
54 : } else {
55 : strcat(err, "**UNMANAGED**");
56 : }
57 : }))
58 :
59 : KOKKOS_IF_ON_DEVICE(({
60 : strcat(err, "**UNAVAILABLE**");
61 : (void)tracker;
62 : }))
63 :
64 : strcat(err, "\")");
65 :
66 : Kokkos::abort(err);
67 : }
68 : };
69 :
70 : template <class MemorySpace>
71 : KOKKOS_FUNCTION void runtime_check_memory_access_violation(
72 : SharedAllocationTracker const &track) {
73 : KOKKOS_IF_ON_HOST(((void)RuntimeCheckBasicViewMemoryAccessViolation<
74 : MemorySpace, DefaultHostExecutionSpace>(track);))
75 : KOKKOS_IF_ON_DEVICE(((void)RuntimeCheckBasicViewMemoryAccessViolation<
76 : MemorySpace, DefaultExecutionSpace>(track);))
77 : }
78 :
79 : template <class IndexType, std::size_t... Extents, class... Indices,
80 : std::size_t... Enumerate>
81 : KOKKOS_FUNCTION bool within_range(
82 : Kokkos::extents<IndexType, Extents...> const &exts,
83 : std::index_sequence<Enumerate...>, Indices... indices) {
84 : // FIXME[CUDA11]: This is written so weirdly to avoid warnings with CUDA 11
85 : // Without the workaround this could just be written as:
86 : // return ((indices < exts.extent(Enumerate)) && ...) &&
87 : // ((std::is_unsigned_v<decltype(indices)> ||
88 : // (indices >= static_cast<decltype(indices)>(0))) &&
89 : // ...);
90 : [[maybe_unused]] auto check_index_min = [](auto idx) {
91 : if constexpr (!std::is_unsigned_v<decltype(idx)>) {
92 : return idx >= static_cast<decltype(idx)>(0);
93 : }
94 :
95 : return true;
96 : };
97 :
98 : return ((indices < exts.extent(Enumerate)) && ...) &&
99 : (check_index_min(indices) && ...);
100 : }
101 :
102 : template <class... Indices>
103 0 : KOKKOS_FUNCTION constexpr char *append_formatted_multidimensional_index(
104 : char *dest, Indices... indices) {
105 0 : char *d = dest;
106 0 : strcat(d, "[");
107 : (
108 0 : [&] {
109 0 : d += strlen(d);
110 0 : to_chars_i(d,
111 : d + 20, // 20 digits ought to be enough
112 0 : indices);
113 0 : strcat(d, ",");
114 0 : }(),
115 : ...);
116 0 : d[strlen(d) - 1] = ']'; // overwrite trailing comma
117 0 : return dest;
118 : }
119 :
120 : template <class IndexType, size_t... Extents, std::size_t... Enumerate>
121 : KOKKOS_FUNCTION void print_extents(
122 : char *dest, Kokkos::extents<IndexType, Extents...> const &exts,
123 : std::index_sequence<Enumerate...>) {
124 : append_formatted_multidimensional_index(dest, exts.extent(Enumerate)...);
125 : }
126 :
127 : template <class ExtentsType, class... IndexTypes>
128 : KOKKOS_INLINE_FUNCTION void view_verify_operator_bounds(
129 : SharedAllocationTracker const &tracker, const ExtentsType &exts,
130 : [[maybe_unused]] const void *data, IndexTypes... idx) {
131 : using idx_t = typename ExtentsType::index_type;
132 : if (!within_range(exts, std::make_index_sequence<sizeof...(IndexTypes)>(),
133 : idx...)) {
134 : char err[256] = "";
135 : strcat(err, "Kokkos::View ERROR: out of bounds access");
136 : strcat(err, " label=(\"");
137 : KOKKOS_IF_ON_HOST(
138 : if (tracker.has_record()) {
139 : strncat(err, tracker.template get_label<void>().c_str(), 128);
140 : } else { strcat(err, "**UNMANAGED**"); })
141 : KOKKOS_IF_ON_DEVICE([&] {
142 : if (!tracker.has_record()) {
143 : strcat(err, "**UNMANAGED**");
144 : return;
145 : }
146 : SharedAllocationHeader const *const header =
147 : SharedAllocationHeader::get_header(data);
148 : char const *const label = header->label();
149 : strcat(err, label);
150 : }();)
151 : strcat(err, "\") with indices ");
152 : append_formatted_multidimensional_index(err, static_cast<idx_t>(idx)...);
153 : strcat(err, " but extents ");
154 : print_extents(err, exts, std::make_index_sequence<sizeof...(IndexTypes)>());
155 : Kokkos::abort(err);
156 : }
157 : }
158 : } // namespace Kokkos::Impl
159 :
160 : #endif // KOKKOS_VIEW_CHECKING_HPP
|