1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 3.0
6 // Copyright (2020) National Technology & Engineering
7 // Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44
45 #ifndef KOKKOS_EXPERIMENTAL_ERROR_REPORTER_HPP
46 #define KOKKOS_EXPERIMENTAL_ERROR_REPORTER_HPP
47
48 #include <vector>
49 #include <Kokkos_Core.hpp>
50 #include <Kokkos_View.hpp>
51 #include <Kokkos_DualView.hpp>
52
53 namespace Kokkos {
54 namespace Experimental {
55
56 template <typename ReportType, typename DeviceType>
57 class ErrorReporter {
58 public:
59 using report_type = ReportType;
60 using device_type = DeviceType;
61 using execution_space = typename device_type::execution_space;
62
ErrorReporter(int max_results)63 ErrorReporter(int max_results)
64 : m_numReportsAttempted(""),
65 m_reports("", max_results),
66 m_reporters("", max_results) {
67 clear();
68 }
69
getCapacity() const70 int getCapacity() const { return m_reports.h_view.extent(0); }
71
72 int getNumReports();
73
74 int getNumReportAttempts();
75
76 void getReports(std::vector<int> &reporters_out,
77 std::vector<report_type> &reports_out);
78 void getReports(
79 typename Kokkos::View<int *,
80 typename DeviceType::execution_space>::HostMirror
81 &reporters_out,
82 typename Kokkos::View<report_type *,
83 typename DeviceType::execution_space>::HostMirror
84 &reports_out);
85
86 void clear();
87
88 void resize(const size_t new_size);
89
full()90 bool full() { return (getNumReportAttempts() >= getCapacity()); }
91
92 KOKKOS_INLINE_FUNCTION
add_report(int reporter_id,report_type report) const93 bool add_report(int reporter_id, report_type report) const {
94 int idx = Kokkos::atomic_fetch_add(&m_numReportsAttempted(), 1);
95
96 if (idx >= 0 && (idx < static_cast<int>(m_reports.d_view.extent(0)))) {
97 m_reporters.d_view(idx) = reporter_id;
98 m_reports.d_view(idx) = report;
99 return true;
100 } else {
101 return false;
102 }
103 }
104
105 private:
106 using reports_view_t = Kokkos::View<report_type *, execution_space>;
107 using reports_dualview_t = Kokkos::DualView<report_type *, execution_space>;
108
109 using host_mirror_space = typename reports_dualview_t::host_mirror_space;
110 Kokkos::View<int, execution_space> m_numReportsAttempted;
111 reports_dualview_t m_reports;
112 Kokkos::DualView<int *, execution_space> m_reporters;
113 };
114
115 template <typename ReportType, typename DeviceType>
getNumReports()116 inline int ErrorReporter<ReportType, DeviceType>::getNumReports() {
117 int num_reports = 0;
118 Kokkos::deep_copy(num_reports, m_numReportsAttempted);
119 if (num_reports > static_cast<int>(m_reports.h_view.extent(0))) {
120 num_reports = m_reports.h_view.extent(0);
121 }
122 return num_reports;
123 }
124
125 template <typename ReportType, typename DeviceType>
getNumReportAttempts()126 inline int ErrorReporter<ReportType, DeviceType>::getNumReportAttempts() {
127 int num_reports = 0;
128 Kokkos::deep_copy(num_reports, m_numReportsAttempted);
129 return num_reports;
130 }
131
132 template <typename ReportType, typename DeviceType>
getReports(std::vector<int> & reporters_out,std::vector<report_type> & reports_out)133 void ErrorReporter<ReportType, DeviceType>::getReports(
134 std::vector<int> &reporters_out, std::vector<report_type> &reports_out) {
135 int num_reports = getNumReports();
136 reporters_out.clear();
137 reporters_out.reserve(num_reports);
138 reports_out.clear();
139 reports_out.reserve(num_reports);
140
141 if (num_reports > 0) {
142 m_reports.template sync<host_mirror_space>();
143 m_reporters.template sync<host_mirror_space>();
144
145 for (int i = 0; i < num_reports; ++i) {
146 reporters_out.push_back(m_reporters.h_view(i));
147 reports_out.push_back(m_reports.h_view(i));
148 }
149 }
150 }
151
152 template <typename ReportType, typename DeviceType>
getReports(typename Kokkos::View<int *,typename DeviceType::execution_space>::HostMirror & reporters_out,typename Kokkos::View<report_type *,typename DeviceType::execution_space>::HostMirror & reports_out)153 void ErrorReporter<ReportType, DeviceType>::getReports(
154 typename Kokkos::View<
155 int *, typename DeviceType::execution_space>::HostMirror &reporters_out,
156 typename Kokkos::View<report_type *,
157 typename DeviceType::execution_space>::HostMirror
158 &reports_out) {
159 int num_reports = getNumReports();
160 reporters_out =
161 typename Kokkos::View<int *, typename DeviceType::execution_space>::
162 HostMirror("ErrorReport::reporters_out", num_reports);
163 reports_out = typename Kokkos::
164 View<report_type *, typename DeviceType::execution_space>::HostMirror(
165 "ErrorReport::reports_out", num_reports);
166
167 if (num_reports > 0) {
168 m_reports.template sync<host_mirror_space>();
169 m_reporters.template sync<host_mirror_space>();
170
171 for (int i = 0; i < num_reports; ++i) {
172 reporters_out(i) = m_reporters.h_view(i);
173 reports_out(i) = m_reports.h_view(i);
174 }
175 }
176 }
177
178 template <typename ReportType, typename DeviceType>
clear()179 void ErrorReporter<ReportType, DeviceType>::clear() {
180 int num_reports = 0;
181 Kokkos::deep_copy(m_numReportsAttempted, num_reports);
182 m_reports.template modify<execution_space>();
183 m_reporters.template modify<execution_space>();
184 }
185
186 template <typename ReportType, typename DeviceType>
resize(const size_t new_size)187 void ErrorReporter<ReportType, DeviceType>::resize(const size_t new_size) {
188 m_reports.resize(new_size);
189 m_reporters.resize(new_size);
190 typename DeviceType::execution_space().fence();
191 }
192
193 } // namespace Experimental
194 } // namespace Kokkos
195
196 #endif
197