timemory 3.3.0
Modular C++ Toolkit for Performance Analysis and Logging. Profiling API and Tools for C, C++, CUDA, Fortran, and Python. The C++ template API is essentially a framework to creating tools: it is designed to provide a unifying interface for recording various performance measurements alongside data logging and interfaces to other tools.
trace.cpp
Go to the documentation of this file.
1// MIT License
2//
3// Copyright (c) 2020, The Regents of the University of California,
4// through Lawrence Berkeley National Laboratory (subject to receipt of any
5// required approvals from the U.S. Dept. of Energy). All rights reserved.
6//
7// Permission is hereby granted, free of charge, to any person obtaining a copy
8// of this software and associated documentation files (the "Software"), to deal
9// in the Software without restriction, including without limitation the rights
10// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11// copies of the Software, and to permit persons to whom the Software is
12// furnished to do so, subject to the following conditions:
13//
14// The above copyright notice and this permission notice shall be included in all
15// copies or substantial portions of the Software.
16//
17// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23// SOFTWARE.
24
25#if !defined(TIMEMORY_LIBRARY_SOURCE)
26# define TIMEMORY_LIBRARY_SOURCE 1
27#endif
28
29#include "timemory/trace.hpp"
30
32#include "timemory/library.h"
34#include "timemory/timemory.hpp"
36
37#if defined(TIMEMORY_USE_MPI)
38# include "timemory/backends/types/mpi/extern.hpp"
39#endif
40
41#include <cstdarg>
42#include <cstdlib>
43#include <deque>
44#include <iostream>
45#include <unordered_map>
46
47using namespace tim::component;
48
50using overhead_map_t = std::unordered_map<size_t, std::pair<wall_clock, size_t>>;
51using throttle_set_t = std::set<size_t>;
53using trace_map_t = std::unordered_map<size_t, std::deque<traceset_t>>;
54
55//======================================================================================//
56
57static std::atomic<uint32_t> library_trace_count{ 0 };
58
59//--------------------------------------------------------------------------------------//
60
61static auto&
62get_overhead() TIMEMORY_VISIBILITY("default");
63static auto&
64get_throttle() TIMEMORY_VISIBILITY("default");
65static trace_map_t&
66get_trace_map() TIMEMORY_VISIBILITY("default");
67
68//--------------------------------------------------------------------------------------//
69
70static auto&
71get_overhead()
72{
73 static thread_local auto _instance = std::make_unique<overhead_map_t>();
74 return _instance;
75}
76
77//--------------------------------------------------------------------------------------//
78
79static auto&
80get_throttle()
81{
82 static thread_local auto _instance = std::make_unique<throttle_set_t>();
83 return _instance;
84}
85
86//--------------------------------------------------------------------------------------//
87
88static trace_map_t&
89get_trace_map()
90{
91 static thread_local trace_map_t _instance;
92 return _instance;
93}
94
95//--------------------------------------------------------------------------------------//
96
97extern std::array<bool, 2>&
99
100//--------------------------------------------------------------------------------------//
101
102static bool use_mpi_gotcha = false;
103
104//--------------------------------------------------------------------------------------//
105
106#if defined(TIMEMORY_MPI_GOTCHA)
107
108static bool mpi_is_attached = false;
109
110//--------------------------------------------------------------------------------------//
111// query environment setting for whether to enable finalization via MPI_Comm_create_keyval
112//
113extern "C" bool
114timemory_mpi_finalize_comm_keyval()
115{
116 return tim::get_env<bool>("TIMEMORY_MPI_FINALIZE_COMM_KEYVAL", true);
117}
118
119//--------------------------------------------------------------------------------------//
120// query environment setting for whether to enable finalization via gotcha wrapper
121//
122extern "C" bool
123timemory_mpi_finalize_gotcha_wrapper()
124{
125 return tim::get_env<bool>("TIMEMORY_MPI_FINALIZE_GOTCHA_WRAPPER", false);
126}
127
128//--------------------------------------------------------------------------------------//
129
130static int&
131timemory_trace_mpi_comm_key()
132{
133 static int comm_key = -1;
134 return comm_key;
135}
136
137static int
138timemory_trace_mpi_copy(MPI_Comm, int, void*, void*, void*, int*)
139{
140 return MPI_SUCCESS;
141}
142
143static int
144timemory_trace_mpi_finalize(MPI_Comm, int, void*, void*)
145{
146 // only execute once
147 static bool once = false;
148 if(once || tim::mpi::is_finalized())
149 return MPI_SUCCESS;
150 once = true;
151 // do finalization
153 PRINT_HERE("%s", "comm keyval finalization started");
156 PRINT_HERE("%s", "comm keyval finalization complete");
157 return MPI_SUCCESS;
158}
159
160//--------------------------------------------------------------------------------------//
161
162struct mpi_trace_gotcha : tim::component::base<mpi_trace_gotcha, void>
163{
164 static void set_attr()
165 {
166 if(!timemory_mpi_finalize_comm_keyval())
167 return;
169 auto _state = tim::settings::enabled();
170 tim::settings::enabled() = false;
171 auto ret =
172 MPI_Comm_create_keyval(&timemory_trace_mpi_copy, &timemory_trace_mpi_finalize,
173 &timemory_trace_mpi_comm_key(), nullptr);
174 if(ret == MPI_SUCCESS)
175 MPI_Comm_set_attr(MPI_COMM_SELF, timemory_trace_mpi_comm_key(), nullptr);
176 tim::settings::enabled() = _state;
177 }
178
179 // MPI_Init
180 int operator()(int* argc, char*** argv)
181 {
182 if(recursive())
183 return MPI_Init(argc, argv);
184 recursive() = true;
185 auto ret = MPI_Init(argc, argv);
186
187 set_attr();
188 auto mode = tim::get_env<std::string>("TIMEMORY_INSTRUMENTATION_MODE", "trace");
189 if(mode == "trace")
190 timemory_push_trace("MPI_Init(int*, char**)");
191 else if(mode == "region")
192 timemory_push_region("MPI_Init(int*, char**)");
193 recursive() = false;
194 return ret;
195 }
196
197 // MPI_Init_thread
198 int operator()(int* argc, char*** argv, int req, int* prov)
199 {
200 if(recursive())
201 return MPI_Init_thread(argc, argv, req, prov);
202 recursive() = true;
203 auto ret = MPI_Init_thread(argc, argv, req, prov);
204
205 set_attr();
206 auto mode = tim::get_env<std::string>("TIMEMORY_INSTRUMENTATION_MODE", "trace");
207 if(mode == "trace")
208 timemory_push_trace("MPI_Init_thread(int*, char**, int, int*)");
209 else if(mode == "region")
210 timemory_push_region("MPI_Init_thread(int*, char**, int, int*)");
211 recursive() = false;
212 return ret;
213 }
214
215 // MPI_Finalize
216 int operator()()
217 {
218 if(recursive() || tim::mpi::is_finalized())
219 return MPI_SUCCESS;
220 recursive() = true;
221 if(!timemory_mpi_finalize_gotcha_wrapper())
222 {
223 auto ret = MPI_Finalize();
224 recursive() = false;
225 return ret;
226 }
227
228 if(mpi_is_attached)
229 {
230 auto mode =
231 tim::get_env<std::string>("TIMEMORY_INSTRUMENTATION_MODE", "trace");
232 if(mode == "trace")
233 {
234 timemory_pop_trace("MPI_Init(int*, char**)");
235 timemory_pop_trace("MPI_Init_thread(int*, char**, int, int*)");
236 }
237 else
238 {
239 timemory_pop_region("MPI_Init(int*, char**)");
240 timemory_pop_region("MPI_Init_thread(int*, char**, int, int*)");
241 }
242 }
244 PRINT_HERE("%s", "finalizing trace");
245 timemory_trace_mpi_finalize(MPI_COMM_WORLD, 0, nullptr, nullptr);
247 PRINT_HERE("%s", "finalizing MPI");
248
249 auto ret = MPI_Finalize();
250 recursive() = false;
251 return ret;
252 }
253
254 static std::string& get_trace_components()
255 {
256 static auto _instance =
257 tim::get_env<std::string>("TIMEMORY_TRACE_COMPONENTS", "");
258 return _instance;
259 }
260
261 static bool& recursive()
262 {
263 static bool _instance = false;
264 return _instance;
265 }
266
267 static bool& read_command_line()
268 {
269 static bool _instance = true;
270 return _instance;
271 }
272
273 static std::string& get_command()
274 {
275 static std::string _instance = "";
276 return _instance;
277 }
278};
279
280//--------------------------------------------------------------------------------------//
281
284
285//--------------------------------------------------------------------------------------//
286
287bool
289{
290 mpi_trace_gotcha_t::get_initializer() = []() {
291 TIMEMORY_C_GOTCHA(mpi_trace_gotcha_t, 0, MPI_Init);
292 TIMEMORY_C_GOTCHA(mpi_trace_gotcha_t, 1, MPI_Init_thread);
293 if(mpi_is_attached || timemory_mpi_finalize_gotcha_wrapper())
294 TIMEMORY_C_GOTCHA(mpi_trace_gotcha_t, 2, MPI_Finalize);
295 };
296 return true;
297}
298
299//--------------------------------------------------------------------------------------//
300
302
303//--------------------------------------------------------------------------------------//
304
305#else
306
307//--------------------------------------------------------------------------------------//
308
309struct mpi_trace_gotcha : tim::component::base<mpi_trace_gotcha, void>
310{
311 static void set_attr() {}
312
313 static std::string& get_trace_components()
314 {
315 static auto _instance =
316 tim::get_env<std::string>("TIMEMORY_TRACE_COMPONENTS", "");
317 return _instance;
318 }
319
320 static bool& read_command_line()
321 {
322 static bool _instance = true;
323 return _instance;
324 }
325
326 static std::string& get_command()
327 {
328 static std::string _instance{};
329 return _instance;
330 }
331};
332
333//--------------------------------------------------------------------------------------//
334
336
337//--------------------------------------------------------------------------------------//
338
339bool
341{
342 return false;
343}
344
345//--------------------------------------------------------------------------------------//
346
347#endif
348
349//--------------------------------------------------------------------------------------//
350
351static bool mpi_gotcha_configured = setup_mpi_gotcha();
352static std::shared_ptr<mpi_trace_bundle_t> mpi_gotcha_handle{ nullptr };
353static std::map<size_t, string_t> master_hash_ids;
354
355//--------------------------------------------------------------------------------------//
356//
357// timemory symbols
358//
359//--------------------------------------------------------------------------------------//
360
361extern "C"
362{
363 //
364 //----------------------------------------------------------------------------------//
365 //
367 {
368 return (get_library_state()[0] &&
369 library_trace_count.load(std::memory_order_relaxed) > 0);
370 }
371 //
372 //----------------------------------------------------------------------------------//
373 //
374 bool timemory_is_throttled(const char* name)
375 {
376 size_t _id = tim::get_hash_id(name);
377 return (get_throttle()->count(_id) > 0);
378 }
379 //
380 //----------------------------------------------------------------------------------//
381 //
382 void timemory_reset_throttle(const char* name)
383 {
384 size_t _id = tim::get_hash_id(name);
385 auto itr = get_throttle()->find(_id);
386 if(itr != get_throttle()->end())
387 get_throttle()->erase(itr);
388 }
389 //
390 //----------------------------------------------------------------------------------//
391 //
392 void timemory_add_hash_id(uint64_t id, const char* name)
393 {
395 if(!lk)
396 {
398 fprintf(stderr,
399 "[timemory-trace]> timemory_add_hash_id failed: locked...\n");
400 return;
401 }
403 fprintf(stderr, "[timemory-trace]> adding '%s' with hash %lu...\n", name,
404 (unsigned long) id);
405 auto _id = tim::add_hash_id(name);
406 if(_id != id)
407 tim::add_hash_id(_id, id);
408
409 // master thread adds the ids
410 if(tim::threading::get_id() == 0)
411 {
412 master_hash_ids[id] = name;
413 if(_id != id)
414 master_hash_ids[_id] = name;
415 }
416 }
417 //
418 //----------------------------------------------------------------------------------//
419 //
420 void timemory_add_hash_ids(uint64_t nentries, uint64_t* ids, const char** names)
421 {
423 fprintf(stderr, "[timemory-trace]> adding %lu hash ids...\n",
424 (unsigned long) nentries);
425 for(uint64_t i = 0; i < nentries; ++i)
426 timemory_add_hash_id(ids[i], names[i]);
427 }
428 //
429 //----------------------------------------------------------------------------------//
430 //
432 {
434 static thread_local bool once_per_thread = false;
435 if(!once_per_thread && tim::threading::get_id() > 0)
436 {
438 fprintf(stderr, "[timemory-trace]> copying hash ids...\n");
439 once_per_thread = true;
440 auto _master_ids = master_hash_ids;
441 for(const auto& itr : _master_ids)
442 timemory_add_hash_id(itr.first, itr.second.c_str());
443 }
444 }
445 //
446 //----------------------------------------------------------------------------------//
447 //
448 void timemory_push_trace_hash(uint64_t id)
449 {
451 timemory_trace_init("", true, "");
452
453 static thread_local auto _copied = (timemory_copy_hash_ids(), true);
455
457
458 if(!lk)
459 {
460#if defined(DEBUG) || !defined(NDEBUG)
462 PRINT_HERE("Tracing is locked: %s", (lk) ? "Y" : "N");
463#endif
464 return;
465 }
466
468 {
469#if defined(DEBUG) || !defined(NDEBUG)
471 PRINT_HERE("Invalid library state: init = %s, fini = %s, enabled = %s",
472 (get_library_state()[0]) ? "Y" : "N",
473 (get_library_state()[1]) ? "Y" : "N",
474 (tim::settings::enabled()) ? "Y" : "N");
475#endif
476 return;
477 }
478
479 if(get_throttle()->count(id) > 0)
480 {
481#if defined(DEBUG) || !defined(NDEBUG)
483 PRINT_HERE("trace %llu is throttled", (unsigned long long) id);
484#endif
485 return;
486 }
487
488 auto& _trace_map = get_trace_map();
489 auto& _overh_map = *get_overhead();
490
491 if(tim::get_hash_ids()->find(id) == tim::get_hash_ids()->end())
492 return;
493
495 {
496 int64_t n = _trace_map[id].size();
497 auto itr = tim::get_hash_ids()->find(id);
498 string_t name = (itr != tim::get_hash_ids()->end()) ? itr->second : "unknown";
499 fprintf(stderr,
500 "beginning trace for '%s' (id = %llu, offset = %lli, rank = %i, pid "
501 "= %i, thread = %i)...\n",
502 name.c_str(), (long long unsigned) id, (long long int) n,
503 tim::dmp::rank(), (int) tim::process::get_id(),
504 (int) tim::threading::get_id());
505 }
506
507 _trace_map[id].emplace_back(traceset_t{ id });
508 _trace_map[id].back().start();
509 _overh_map[id].first.start();
510 }
511 //
512 //----------------------------------------------------------------------------------//
513 //
514 void timemory_pop_trace_hash(uint64_t id)
515 {
517 if(!get_library_state()[0] || get_library_state()[1])
518 return;
519
520 auto& _trace_map = get_trace_map();
521 if(!tim::settings::enabled() && _trace_map.empty())
522 {
523 if(tim::settings::debug() && _trace_map.empty())
524 fprintf(stderr,
525 "[timemory-trace]> timemory_pop_trace_hash(%lu) failed. "
526 "trace_map empty...\n",
527 (unsigned long) id);
528 return;
529 }
530
531 int64_t ntotal = _trace_map[id].size();
532 int64_t offset = ntotal - 1;
533
535 {
536 auto itr = tim::get_hash_ids()->find(id);
537 string_t name = (itr != tim::get_hash_ids()->end()) ? itr->second : "unknown";
538 fprintf(stderr,
539 "ending trace for '%s' (id = %llu, offset = %lli, rank = %i, pid = "
540 "%i, thread = %i)...\n",
541 name.c_str(), (long long unsigned) id, (long long int) offset,
542 tim::dmp::rank(), (int) tim::process::get_id(),
543 (int) tim::threading::get_id());
544 }
545
546 (*get_overhead())[id].first.stop();
547
548 // if there were no entries, return (pop called without a push)
549 if(offset < 0)
550 return;
551
552 if(offset >= 0 && ntotal > 0)
553 {
554 _trace_map[id].back().stop();
555 _trace_map[id].pop_back();
556 }
557
558 if(get_throttle() && get_throttle()->count(id) > 0)
559 return;
560
561 auto _count = ++(get_overhead()->at(id).second);
562
563 if(_count % tim::settings::throttle_count() == 0)
564 {
565 auto _accum = get_overhead()->at(id).first.get_accum() / _count;
566 if(_accum < tim::settings::throttle_value())
567 {
569 {
570 auto name = tim::get_hash_ids()->find(id)->second;
571 fprintf(
572 stderr,
573 "[timemory-trace]> Throttling all future calls to '%s' on rank = "
574 "%i, pid = "
575 "%i, thread = %i. avg runtime = %lu ns from %lu invocations... "
576 "Consider eliminating from instrumentation...\n",
577 name.c_str(), tim::dmp::rank(), (int) tim::process::get_id(),
578 (int) tim::threading::get_id(), (unsigned long) _accum,
579 (unsigned long) _count);
580 }
581 get_throttle()->insert(id);
582 }
583 else
584 {
585 if(_accum < (10 * tim::settings::throttle_value()) &&
587 {
588 auto name = tim::get_hash_ids()->find(id)->second;
589 fprintf(
590 stderr,
591 "[timemory-trace]> Warning! function call '%s' within an order "
592 "of magnitude of threshold for throttling value on rank = %i, "
593 "pid = "
594 "%i, thread = %i. avg runtime = %lu ns from %lu invocations... "
595 "Consider eliminating from instrumentation...\n",
596 name.c_str(), tim::dmp::rank(), (int) tim::process::get_id(),
597 (int) tim::threading::get_id(), (unsigned long) _accum,
598 (unsigned long) _count);
599 }
600 }
601 get_overhead()->at(id).first.reset();
602 get_overhead()->at(id).second = 0;
603 }
604 }
605 //
606 //----------------------------------------------------------------------------------//
607 //
608 void timemory_push_trace(const char* name)
609 {
611 timemory_trace_init("", true, "");
612
613 uint64_t _hash = std::numeric_limits<uint64_t>::max();
614 {
617 PRINT_HERE("rank = %i, pid = %i, thread = %i, name = %s",
618 tim::dmp::rank(), (int) tim::process::get_id(),
619 (int) tim::threading::get_id(), name);
620
621 if(!get_library_state()[0] || get_library_state()[1] ||
623 return;
624
625 _hash = tim::add_hash_id(name);
626 }
628 }
629 //
630 //----------------------------------------------------------------------------------//
631 //
632 void timemory_pop_trace(const char* name)
633 {
634 uint64_t _hash = std::numeric_limits<uint64_t>::max();
635 {
637 if(!get_library_state()[0] || get_library_state()[1])
638 return;
639 _hash = tim::get_hash_id(name);
640 }
642 }
643 //
644 //----------------------------------------------------------------------------------//
645 //
646#if defined(TIMEMORY_MPI_GOTCHA)
647 //
648 void timemory_trace_set_mpi(bool use, bool attached)
649 {
650 use_mpi_gotcha = use;
651 mpi_is_attached = attached;
652 }
653 //
654#endif
655 //
656 //----------------------------------------------------------------------------------//
657 //
658 void timemory_trace_set_env(const char* env_var, const char* env_val)
659 {
661 tim::set_env<std::string>(env_var, env_val, 0);
662 if(get_library_state()[0])
663 {
665 user_trace_bundle::global_init(true);
666 }
667 }
668 //
669 //----------------------------------------------------------------------------------//
670 //
671 void timemory_trace_init(const char* comps, bool read_command_line, const char* cmd)
672 {
674 if(!tim::manager::instance() || tim::manager::instance()->is_finalized())
675 return;
676
677 // configures the output path
678 auto _configure_output_path = [&]() {
679 static bool _performed_explicit = false;
680 if(_performed_explicit || tim::settings::output_path() != "timemory-output")
681 return;
683 {
684 auto _init = [](int _ac, char** _av) { timemory_init_library(_ac, _av); };
686 }
687 else
688 {
689 std::string exe_name = (cmd) ? cmd : "";
690 if(!exe_name.empty())
691 _performed_explicit = true;
692
693 while(exe_name.find('\\') != std::string::npos)
694 exe_name = exe_name.substr(exe_name.find_last_of('\\') + 1);
695 while(exe_name.find('/') != std::string::npos)
696 exe_name = exe_name.substr(exe_name.find_last_of('/') + 1);
697
698 static const std::vector<std::string> _exe_suffixes = { ".py", ".exe" };
699 for(const auto& ext : _exe_suffixes)
700 {
701 if(exe_name.find(ext) != std::string::npos)
702 exe_name.erase(exe_name.find(ext), ext.length() + 1);
703 }
704
705 exe_name = std::string("timemory-") + exe_name + "-output";
706 for(auto& itr : exe_name)
707 {
708 if(itr == '_')
709 itr = '-';
710 }
711
713 }
715 tim::manager::instance()->update_metadata_prefix();
716 };
717
718 // write the info about the rank/pid/thread/command
719 auto _write_info = [&]() {
720 std::stringstream _info;
721 _info << "[timemory_trace_init]> ";
722 if(tim::dmp::is_initialized())
723 _info << "rank = " << tim::dmp::rank() << ", ";
724 _info << "pid = " << tim::process::get_id() << ", ";
725 _info << "tid = " << tim::threading::get_id();
726 if(cmd && strlen(cmd) > 0)
727 _info << ", command: " << cmd;
728 if(comps && strlen(comps) > 0)
729 _info << ", default components: " << comps;
730 fprintf(stderr, "%s\n", _info.str().c_str());
731 };
732
733 // configures the tracing components
734 auto _configure_components = [&]() {
735 if(comps && strlen(comps) > 0)
736 {
737 _write_info();
738 tim::set_env<std::string>("TIMEMORY_TRACE_COMPONENTS", comps, 0);
741 }
742
744
745 // configure bundle
746 user_trace_bundle::global_init(true);
747 // tim::operation::init<user_trace_bundle>(
748 // tim::operation::mode_constant<tim::operation::init_mode::global>{});
749 };
750
751 if(!get_library_state()[0] && library_trace_count++ == 0)
752 {
753 _configure_components();
754 _configure_output_path();
755
757 get_library_state()[0] = true;
758
759 auto _exit_action = [](int nsig) {
760 auto _manager = tim::manager::master_instance();
761 if(_manager && !_manager->is_finalized() && !_manager->is_finalizing())
762 {
763 std::cout << "Finalizing after signal: " << nsig << " :: "
765 static_cast<tim::sys_signal>(nsig))
766 << std::endl;
768 }
769 };
771 std::atexit(&timemory_trace_finalize);
772#if !defined(TIMEMORY_MACOS)
773 // Apple clang version 11.0.3 (clang-1103.0.32.62) doesn't seem to have this
774 // function
775 std::at_quick_exit(&tim::timemory_finalize);
776#endif
777
778#if defined(TIMEMORY_MPI_GOTCHA)
779 if(!mpi_gotcha_handle.get())
780 {
781 mpi_gotcha_handle =
782 std::make_shared<mpi_trace_bundle_t>("timemory_trace_mpi_gotcha");
783 mpi_trace_gotcha::get_trace_components() = comps;
785 mpi_trace_gotcha::get_command() = (cmd) ? cmd : "";
786 if(mpi_is_attached)
787 mpi_trace_gotcha::set_attr();
788 mpi_gotcha_handle->start();
789 }
790 else if(mpi_gotcha_handle.get())
791 {
792 tim::manager::instance()->update_metadata_prefix();
793 }
794#endif
795 }
796 else
797 {
799 PRINT_HERE("trace already initialized: %s",
800 (get_library_state()[0]) ? "Y" : "N");
801
802 _configure_components();
803 }
804 }
805 //
806 //----------------------------------------------------------------------------------//
807 //
809 {
811 if(library_trace_count.load() == 0)
812 return;
813
814 auto _manager = tim::manager::master_instance();
816 if(!_manager || !_settings)
817 return;
818
819 auto _debug = _settings->get_debug();
820 if(_settings->get_verbose() > 1 || _settings->get_debug())
821 PRINT_HERE("rank = %i, pid = %i, thread = %i", tim::dmp::rank(),
822 (int) tim::process::get_id(), (int) tim::threading::get_id());
823
824 CONDITIONAL_PRINT_HERE(_debug, "%s", "getting count");
825 // do the finalization
826 auto _count = --library_trace_count;
827
828 if(_count > 0)
829 {
830 CONDITIONAL_PRINT_HERE(_debug, "%s", "positive count");
831 // have the manager finalize
833 tim::manager::instance()->finalize();
834 CONDITIONAL_PRINT_HERE(_debug, "%s", "returning");
835 return;
836 }
837
838 CONDITIONAL_PRINT_HERE(_debug, "%s", "secondary lock");
839 tim::auto_lock_t lock(tim::type_mutex<TIMEMORY_API>());
840
841 CONDITIONAL_PRINT_HERE(_debug, "%s", "setting state");
842 // tim::settings::enabled() = false;
843 get_library_state()[1] = true;
844
845 CONDITIONAL_PRINT_HERE(_debug, "%s", "barrier");
846 tim::mpi::barrier();
847
848 CONDITIONAL_PRINT_HERE(_debug, "%s", "resetting");
849 // reset traces just in case
851
852 // if already finalized
853 bool _skip_stop = false;
854 if(!_manager || _manager->is_finalized())
855 _skip_stop = true;
856
857 // clean up any remaining entries
858 if(!_skip_stop)
859 {
860 CONDITIONAL_PRINT_HERE(_debug, "%s", "cleaning trace map");
861 for(auto& itr : get_trace_map())
862 {
863 for(auto& eitr : itr.second)
864 eitr.stop();
865 // delete all the records
866 itr.second.clear();
867 }
868 CONDITIONAL_PRINT_HERE(_debug, "%s", "clearing trace map");
869 // delete all the records
870 get_trace_map().clear();
871 }
872
873 CONDITIONAL_PRINT_HERE(_debug, "%s", "resetting mpi gotcha");
874 // deactivate the gotcha wrappers
875 if(use_mpi_gotcha)
876 mpi_gotcha_handle.reset();
877
878 CONDITIONAL_PRINT_HERE(_debug, "%s", "finalizing library");
879 // finalize the library
881
882 CONDITIONAL_PRINT_HERE(_debug, "%s", "finalized trace");
883 }
884 //
885 //----------------------------------------------------------------------------------//
886 //
887} // extern "C"
This is a variadic component wrapper where all components are allocated on the stack and cannot be di...
static pointer_t instance()
Get a shared pointer to the instance for the current thread.
static pointer_t master_instance()
Get a shared pointer to the instance on the primary thread.
static void use_exit_hook(bool val)
Enable setting std::exit callback.
Definition: manager.hpp:176
static std::string str(const sys_signal &)
Definition: signals.hpp:147
static void set_exit_action(signal_function_t _f)
Definition: signals.hpp:280
void timemory_push_region(const char *name)
Definition: library.cpp:573
std::string string_t
Definition: library.cpp:57
void timemory_pop_region(const char *name)
Definition: library.cpp:587
void timemory_init_library(int argc, char **argv)
Initializes timemory. Not strictly necessary but highly recommended.
Definition: library.cpp:212
void timemory_finalize_library(void)
Finalizes timemory. Output will be generated. Any attempt to store data within timemory storage is un...
Definition: library.cpp:253
#define TIMEMORY_C_GOTCHA(...)
Definition: macros.hpp:323
::tim::statistics< Tp > max(::tim::statistics< Tp > lhs, const Tp &rhs)
Definition: statistics.hpp:320
void read_command_line(Func &&_func)
this only works on Linux where there is a /proc/<PID>/cmdline file
Definition: config.hpp:65
return _hash_map end()
hash_value_t add_hash_id(hash_map_ptr_t &_hash_map, string_view_cref_t _prefix)
add an string to the given hash-map (if it doesn't already exist) and return the hash
Definition: types.hpp:190
hash_map_ptr_t & get_hash_ids()
hash_value_t get_hash_id(Tp &&_prefix)
Definition: types.hpp:143
void reset(TupleT< Tp... > &obj, Args &&... args)
Definition: functional.cpp:599
A lightweight synchronization object for preventing recursion. The first template parameter should ha...
Definition: trace.hpp:135
throttle_value
Definition: settings.cpp:1680
std::unique_lock< mutex_t > auto_lock_t
Unique lock type around mutex_t.
Definition: locking.hpp:42
void timemory_finalize()
finalization of the specified types
std::string exe_name
Definition: config.cpp:77
sys_signal
Definition: declaration.hpp:69
std::vector< std::string > read_command_line(pid_t _pid)
Definition: utility.cpp:114
char ** argv
Definition: config.cpp:55
char argparse::argument_parser tim::settings * _settings
Definition: config.cpp:255
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
output_path
Definition: settings.cpp:1661
throttle_count
Definition: settings.cpp:1678
trace_components
Definition: settings.cpp:1694
void consume_parameters(ArgsT &&...)
Definition: types.hpp:285
This is a variadic component wrapper which combines the features of tim::component_tuple<T....
Definition: types.hpp:63
The gotcha component rewrites the global offset table such that calling the wrapped function actually...
Definition: components.hpp:179
static void parse(settings *=instance< TIMEMORY_API >())
Definition: settings.cpp:410
static settings * instance()
Definition: settings.hpp:536
void timemory_trace_init(const char *comps, bool read_command_line, const char *cmd)
Definition: trace.cpp:671
std::set< size_t > throttle_set_t
Definition: trace.cpp:51
bool setup_mpi_gotcha()
Definition: trace.cpp:340
void timemory_push_trace_hash(uint64_t id)
Definition: trace.cpp:448
void timemory_push_trace(const char *name)
Definition: trace.cpp:608
bool timemory_is_throttled(const char *name)
Definition: trace.cpp:374
void timemory_pop_trace(const char *name)
Definition: trace.cpp:632
std::unordered_map< size_t, std::pair< wall_clock, size_t > > overhead_map_t
Definition: trace.cpp:50
void timemory_trace_set_env(const char *env_var, const char *env_val)
Definition: trace.cpp:658
void timemory_pop_trace_hash(uint64_t id)
Definition: trace.cpp:514
bool timemory_trace_is_initialized()
Definition: trace.cpp:366
std::array< bool, 2 > & get_library_state()
Definition: library.cpp:127
void timemory_copy_hash_ids()
Definition: trace.cpp:431
void timemory_trace_finalize(void)
Definition: trace.cpp:808
void timemory_add_hash_ids(uint64_t nentries, uint64_t *ids, const char **names)
Definition: trace.cpp:420
std::unordered_map< size_t, std::deque< traceset_t > > trace_map_t
Definition: trace.cpp:53
void timemory_add_hash_id(uint64_t id, const char *name)
Definition: trace.cpp:392
void timemory_reset_throttle(const char *name)
Definition: trace.cpp:382
#define CONDITIONAL_PRINT_HERE(CONDITION,...)
Definition: macros.hpp:183
#define PRINT_HERE(...)
Definition: macros.hpp:152