11 #include "TpetraCore_config.h"
13 #include "Kokkos_Core.hpp"
14 #include "Teuchos_TimeMonitor.hpp"
15 #include "Teuchos_Time.hpp"
16 #include "Teuchos_RCP.hpp"
17 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
18 #include "Teuchos_StackedTimer.hpp"
28 std::string deviceIdToString(
const uint32_t deviceId) {
29 using namespace Kokkos::Tools::Experimental;
30 std::string device_label(
"(");
31 ExecutionSpaceIdentifier eid = identifier_from_devid(deviceId);
32 if (eid.type == DeviceType::Serial)
33 device_label +=
"Serial";
34 else if (eid.type == DeviceType::OpenMP)
35 device_label +=
"OpenMP";
36 else if (eid.type == DeviceType::Cuda)
37 device_label +=
"Cuda";
38 else if (eid.type == DeviceType::HIP)
39 device_label +=
"HIP";
40 else if (eid.type == DeviceType::OpenMPTarget)
41 device_label +=
"OpenMPTarget";
42 else if (eid.type == DeviceType::HPX)
43 device_label +=
"HPX";
44 else if (eid.type == DeviceType::Threads)
45 device_label +=
"Threads";
46 else if (eid.type == DeviceType::SYCL)
47 device_label +=
"SYCL";
48 else if (eid.type == DeviceType::OpenACC)
49 device_label +=
"OpenACC";
50 else if (eid.type == DeviceType::Unknown)
51 device_label +=
"Unknown";
53 device_label +=
"Unknown to Tpetra";
54 if (eid.instance_id == int_for_synchronization_reason(SpecialSynchronizationCases::GlobalDeviceSynchronization))
55 device_label +=
" All Instances)";
56 else if (eid.instance_id == int_for_synchronization_reason(SpecialSynchronizationCases::DeepCopyResourceSynchronization))
57 device_label +=
" DeepCopyResource)";
59 device_label +=
" Instance " + std::to_string(eid.instance_id) +
")";
64 void overlappingWarning() {
65 std::ostringstream warning;
66 warning <<
"\n*********************************************************************\n"
67 "WARNING: Overlapping timers detected!\n"
68 "A TimeMonitor timer was stopped before a nested subtimer was\n"
69 "stopped. This is not allowed by the StackedTimer. This corner case\n"
70 "typically occurs if the TimeMonitor is stored in an RCP and the RCP is\n"
71 "assigned to a new timer. To disable this warning, either fix the\n"
72 "ordering of timer creation and destuction or disable the StackedTimer\n";
73 std::cout << warning.str() << std::endl;
81 namespace DeepCopyTimerInjection {
82 Teuchos::RCP<Teuchos::Time> timer_;
84 bool initialized_ =
false;
86 void kokkosp_begin_deep_copy(Kokkos::Tools::SpaceHandle dst_handle,
const char* dst_name,
const void* dst_ptr,
87 Kokkos::Tools::SpaceHandle src_handle,
const char* src_name,
const void* src_ptr,
90 std::string extra_label;
92 extra_label = std::string(
" {") + src_name +
"=>" + dst_name +
"}";
94 extra_label = std::string(
" {") + src_name +
"=>" + dst_name +
"," + std::to_string(size) +
"}";
97 if (timer_ != Teuchos::null)
98 std::cout <<
"WARNING: Kokkos::deep_copy() started within another Kokkos::deep_copy(). Timers will be in error" << std::endl;
101 if (!strcmp(src_name,
"Scalar") || !strcmp(src_name,
"(none)"))
102 label_ = std::string(
"Kokkos::deep_copy_scalar [") + src_handle.name +
"=>" + dst_handle.name +
"]" + extra_label;
105 label_ = std::string(
"Kokkos::deep_copy_small [") + src_handle.name +
"=>" + dst_handle.name +
"]" + extra_label;
107 label_ = std::string(
"Kokkos::deep_copy [") + src_handle.name +
"=>" + dst_handle.name +
"]" + extra_label;
109 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
110 if (!Teuchos::TimeMonitor::stackedTimerNameIsDefault()) {
111 const auto stackedTimer = Teuchos::TimeMonitor::getStackedTimer();
112 stackedTimer->start(label_);
116 timer_ = Teuchos::TimeMonitor::getNewTimer(label_);
118 timer_->incrementNumCalls();
122 void kokkosp_end_deep_copy() {
123 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
124 if (!Teuchos::TimeMonitor::stackedTimerNameIsDefault()) {
126 const auto stackedTimer = Teuchos::TimeMonitor::getStackedTimer();
127 stackedTimer->stop(label_);
129 }
catch (std::runtime_error&) {
130 overlappingWarning();
131 Teuchos::TimeMonitor::setStackedTimer(Teuchos::null);
136 if (timer_ != Teuchos::null) {
139 timer_ = Teuchos::null;
145 void AddKokkosDeepCopyToTimeMonitor(
bool force) {
146 if (!DeepCopyTimerInjection::initialized_) {
148 Kokkos::Tools::Experimental::set_begin_deep_copy_callback(DeepCopyTimerInjection::kokkosp_begin_deep_copy);
149 Kokkos::Tools::Experimental::set_end_deep_copy_callback(DeepCopyTimerInjection::kokkosp_end_deep_copy);
150 DeepCopyTimerInjection::initialized_ =
true;
155 namespace FenceTimerInjection {
156 Teuchos::RCP<Teuchos::Time> timer_;
157 bool initialized_ =
false;
158 uint64_t active_handle;
159 std::string label_ =
"";
161 void kokkosp_begin_fence(
const char* name,
const uint32_t deviceId,
167 active_handle = (active_handle + 1) % 1024;
168 *handle = active_handle;
170 std::string device_label = deviceIdToString(deviceId);
172 label_ = std::string(
"Kokkos::fence ") + name +
" " + device_label;
174 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
175 if (!Teuchos::TimeMonitor::stackedTimerNameIsDefault()) {
176 const auto stackedTimer = Teuchos::TimeMonitor::getStackedTimer();
177 stackedTimer->start(label_);
181 timer_ = Teuchos::TimeMonitor::getNewTimer(label_);
183 timer_->incrementNumCalls();
187 void kokkosp_end_fence(
const uint64_t handle) {
188 if (handle == active_handle) {
189 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
190 if (!Teuchos::TimeMonitor::stackedTimerNameIsDefault()) {
192 const auto stackedTimer = Teuchos::TimeMonitor::getStackedTimer();
193 stackedTimer->stop(label_);
196 }
catch (std::runtime_error&) {
197 overlappingWarning();
198 Teuchos::TimeMonitor::setStackedTimer(Teuchos::null);
203 if (timer_ != Teuchos::null) {
206 timer_ = Teuchos::null;
214 void AddKokkosFenceToTimeMonitor(
bool force) {
215 if (!FenceTimerInjection::initialized_) {
217 Kokkos::Tools::Experimental::set_begin_fence_callback(FenceTimerInjection::kokkosp_begin_fence);
218 Kokkos::Tools::Experimental::set_end_fence_callback(FenceTimerInjection::kokkosp_end_fence);
219 FenceTimerInjection::initialized_ =
true;
224 namespace FunctionsTimerInjection {
225 Teuchos::RCP<Teuchos::Time> timer_;
226 bool initialized_ =
false;
229 void kokkosp_begin_kernel(
const char* kernelName,
const char* kernelPrefix,
const uint32_t devID,
230 uint64_t* kernelID) {
232 if (timer_ != Teuchos::null)
234 std::string device_label = deviceIdToString(devID);
236 label_ = std::string(
"Kokkos::") + kernelName +
" " + kernelPrefix +
" " + device_label;
238 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
239 if (!Teuchos::TimeMonitor::stackedTimerNameIsDefault()) {
240 const auto stackedTimer = Teuchos::TimeMonitor::getStackedTimer();
241 stackedTimer->start(label_);
245 timer_ = Teuchos::TimeMonitor::getNewTimer(label_);
247 timer_->incrementNumCalls();
251 void kokkosp_begin_for(
const char* kernelPrefix,
const uint32_t devID, uint64_t* kernelID) {
252 kokkosp_begin_kernel(
"parallel_for", kernelPrefix, devID, kernelID);
255 void kokkosp_begin_scan(
const char* kernelPrefix,
const uint32_t devID, uint64_t* kernelID) {
256 kokkosp_begin_kernel(
"parallel_scan", kernelPrefix, devID, kernelID);
259 void kokkosp_begin_reduce(
const char* kernelPrefix,
const uint32_t devID, uint64_t* kernelID) {
260 kokkosp_begin_kernel(
"parallel_reduce", kernelPrefix, devID, kernelID);
263 void kokkosp_end_kernel(
const uint64_t handle) {
264 #ifdef HAVE_TEUCHOS_ADD_TIME_MONITOR_TO_STACKED_TIMER
265 if (!Teuchos::TimeMonitor::stackedTimerNameIsDefault()) {
267 const auto stackedTimer = Teuchos::TimeMonitor::getStackedTimer();
268 stackedTimer->stop(label_);
270 }
catch (std::runtime_error&) {
271 overlappingWarning();
272 Teuchos::TimeMonitor::setStackedTimer(Teuchos::null);
277 if (timer_ != Teuchos::null) {
280 timer_ = Teuchos::null;
285 void AddKokkosFunctionsToTimeMonitor(
bool force) {
286 if (!FunctionsTimerInjection::initialized_) {
288 Kokkos::Tools::Experimental::set_begin_parallel_for_callback(FunctionsTimerInjection::kokkosp_begin_for);
289 Kokkos::Tools::Experimental::set_begin_parallel_reduce_callback(FunctionsTimerInjection::kokkosp_begin_reduce);
290 Kokkos::Tools::Experimental::set_begin_parallel_scan_callback(FunctionsTimerInjection::kokkosp_begin_scan);
293 Kokkos::Tools::Experimental::set_end_parallel_for_callback(FunctionsTimerInjection::kokkosp_end_kernel);
294 Kokkos::Tools::Experimental::set_end_parallel_reduce_callback(FunctionsTimerInjection::kokkosp_end_kernel);
295 Kokkos::Tools::Experimental::set_end_parallel_scan_callback(FunctionsTimerInjection::kokkosp_end_kernel);
296 FunctionsTimerInjection::initialized_ =
true;
static bool timeKokkosFunctions()
Add Teuchos timers for all host calls to Kokkos::parallel_for(), Kokkos::parallel_reduce() and Kokkos...
Declaration functions that use Kokkos' profiling library to add deep copies between memory spaces...
static bool timeKokkosDeepCopyVerbose2()
Adds verbose output to Kokkos deep_copy timers by appending source, destination, and size...
static bool timeKokkosDeepCopyVerbose1()
Adds verbose output to Kokkos deep_copy timers by appending source and destination. This is especially useful for identifying host/device data transfers.
static bool timeKokkosFence()
Add Teuchos timers for all host calls to Kokkos::fence().
static bool timeKokkosDeepCopy()
Add Teuchos timers for all host calls to Kokkos::deep_copy(). This is especially useful for identifyi...
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.