Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_KokkosCounter.cpp
1 /*
2 // @HEADER
3 // ***********************************************************************
4 //
5 // Tpetra: Templated Linear Algebra Services Package
6 // Copyright (2008) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // ************************************************************************
39 // @HEADER
40 */
41 // clang-format off
43 #include "TpetraCore_config.h"
44 #include "Kokkos_Core.hpp"
45 #include "Teuchos_TestForException.hpp"
46 #include <cstring>
47 #include <string>
48 
49 namespace Tpetra {
50 namespace Details {
51 
52 
53  /***************************** Deep Copy *****************************/
54  namespace DeepCopyCounterDetails {
55  // Static variables
56  bool is_initialized=true;
57  size_t count_same=0;
58  size_t count_different=0;
59  bool count_active=false;
60 
61  void kokkosp_begin_deep_copy(Kokkos::Tools::SpaceHandle dst_handle, const char* dst_name, const void* dst_ptr,
62  Kokkos::Tools::SpaceHandle src_handle, const char* src_name, const void* src_ptr,
63  uint64_t size) {
64 
65  if(count_active) {
66  if(strcmp(dst_handle.name,src_handle.name))
67  count_different++;
68  else
69  count_same++;
70  }
71  }
72 
73  }// end DeepCopyCounterDetails
74 
75 
77  DeepCopyCounterDetails::count_active=true;
78  Kokkos::Tools::Experimental::set_begin_deep_copy_callback(DeepCopyCounterDetails::kokkosp_begin_deep_copy);
79  }
80 
82  DeepCopyCounterDetails::count_same=0;
83  DeepCopyCounterDetails::count_different=0;
84  }
85 
87  DeepCopyCounterDetails::count_active=false;
88  }
89 
91  return DeepCopyCounterDetails::count_same;
92  }
93 
95  return DeepCopyCounterDetails::count_different;
96  }
97 
98 
99 
100  /***************************** Fence *****************************/
101 
102 
103  namespace FenceCounterDetails {
104 
105  // Static variables
106  bool is_initialized=false;
107  bool count_active=false;
108  std::vector<size_t> count_instance;
109  std::vector<size_t> count_global;
110  int num_devices=0;
111 
112 
113  void kokkosp_begin_fence(const char* name, const uint32_t deviceId,
114  uint64_t* handle) {
115 
116  if(count_active) {
117  using namespace Kokkos::Tools::Experimental;
118  ExecutionSpaceIdentifier eid = identifier_from_devid(deviceId);
119 
120  // Figure out what count bin to stick this in
121  int idx = (int) eid.type;
122  if(eid.instance_id == Impl::int_for_synchronization_reason(SpecialSynchronizationCases::GlobalDeviceSynchronization))
123  count_global[idx]++;
124  else
125  count_instance[idx]++;
126  }
127  }
128 
129 
130  std::string get_label(int i) {
131  using namespace Kokkos::Tools::Experimental;
132  DeviceType i_type = devicetype_from_uint32t(i);
133  std::string device_label;
134  if (i_type == DeviceType::Serial) device_label="Serial";
135  else if (i_type == DeviceType::OpenMP) device_label="OpenMP";
136  else if (i_type == DeviceType::Cuda) device_label="Cuda";
137  else if (i_type == DeviceType::HIP) device_label="HIP";
138  else if (i_type == DeviceType::OpenMPTarget) device_label="OpenMPTarget";
139  else if (i_type == DeviceType::HPX) device_label="HPX";
140  else if (i_type == DeviceType::Threads) device_label="Threats";
141  else if (i_type == DeviceType::SYCL) device_label="SYCL";
142  else if (i_type == DeviceType::OpenACC) device_label="OpenACC";
143  else if (i_type == DeviceType::Unknown) device_label="Unknown";
144 
145  return device_label;
146  }
147 
148  void initialize() {
149  using namespace Kokkos::Tools::Experimental;
150  num_devices = (int) DeviceType::Unknown;
151  count_instance.resize(num_devices);
152  count_instance.assign(num_devices,0);
153  count_global.resize(num_devices);
154  count_global.assign(num_devices,0);
155  is_initialized=true;
156  }
157 
158  }// end FenceCounterDetails
159 
160 
161 
162 
164  if(!FenceCounterDetails::is_initialized)
165  FenceCounterDetails::initialize();
166  FenceCounterDetails::count_active=true;
167  Kokkos::Tools::Experimental::set_begin_fence_callback(FenceCounterDetails::kokkosp_begin_fence);
168  }
169 
171  FenceCounterDetails::count_instance.assign(FenceCounterDetails::num_devices,0);
172  FenceCounterDetails::count_global.assign(FenceCounterDetails::num_devices,0);
173  }
174 
176  FenceCounterDetails::count_active=false;
177  }
178 
179  size_t FenceCounter::get_count_global(const std::string & device) {
180  using namespace Kokkos::Tools::Experimental;
181  for(int i=0;i<FenceCounterDetails::num_devices; i++) {
182  std::string device_label = FenceCounterDetails::get_label(i);
183 
184  if(device == device_label)
185  return FenceCounterDetails::count_global[i];
186  }
187 
188  // Haven't found a device by this name
189  TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,std::string("Error: ") + device + std::string(" is not a device known to Tpetra"));
190  }
191 
192 
193  size_t FenceCounter::get_count_instance(const std::string & device) {
194  using namespace Kokkos::Tools::Experimental;
195  for(int i=0;i<FenceCounterDetails::num_devices; i++) {
196  std::string device_label = FenceCounterDetails::get_label(i);
197 
198  if(device == device_label)
199  return FenceCounterDetails::count_instance[i];
200  }
201 
202  // Haven't found a device by this name
203  TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,std::string("Error: ") + device + std::string(" is not a device known to Tpetra"));
204  }
205 
206 // clang-format on
207 namespace KokkosRegionCounterDetails {
208 std::vector<std::string> regions;
209 
210 void push_region_callback(const char *label) { regions.push_back(label); }
211 static_assert(std::is_same_v<decltype(&push_region_callback),
212  Kokkos_Profiling_pushFunction>,
213  "Unexpected Kokkos profiling interface API. This is an internal "
214  "Tpetra developer error, please report this.");
215 
216 } // namespace KokkosRegionCounterDetails
217 
219  Kokkos::Tools::Experimental::set_push_region_callback(
220  KokkosRegionCounterDetails::push_region_callback);
221 }
222 
224  KokkosRegionCounterDetails::regions.clear();
225 }
226 
228  Kokkos::Tools::Experimental::set_push_region_callback(nullptr);
229 }
230 
231 size_t
233  size_t count = 0;
234  for (const auto &region : KokkosRegionCounterDetails::regions) {
235  count += (region.find(needle) != std::string::npos);
236  }
237  return count;
238 }
239 
240 void KokkosRegionCounter::dump_regions(Teuchos::FancyOStream &os) {
241  for (const auto &region : KokkosRegionCounterDetails::regions) {
242  os << region << "\n";
243  }
244 }
245 
246 void KokkosRegionCounter::dump_regions(std::ostream &os) {
247  for (const auto &region : KokkosRegionCounterDetails::regions) {
248  os << region << "\n";
249  }
250 }
251 
252 
253 // clang-format off
254 
255 
256 } // namespace Details
257 } // namespace Tpetra
258 
void initialize(int *argc, char ***argv)
Initialize Tpetra.
void reset()
Reset the deep_copy counter.
Declaration of various tools for counting Kokkos calls of various types using the Kokkos Profiling Li...
void dump_regions(std::ostream &os)
Print all observed region labels, separated by newline.
size_t get_count_same_space()
Query the deep_copy counter for copies in the same space.
size_t get_count_global(const std::string &device)
Query the fence counter for given device, for an Kokkos::fence()
size_t get_count_region_contains(const std::string &substr)
How many regions containing substr have been seen.
void start()
Start the fence counter.
size_t get_count_different_space()
Query the deep_copy counter for copies between different spaces.
void reset()
Reset the fence counter.
void start()
Start the deep_copy counter.
size_t get_count_instance(const std::string &device)
Query the fence counter for given device, for an exec_space_instance.fence()
void stop()
Stop the deep_copy counter.