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.
serialization.hpp
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#pragma once
26
27#include "timemory/backends/dmp.hpp"
28#include "timemory/backends/process.hpp"
34#include "timemory/tpls/cereal/archives.hpp"
35
36#include <cctype>
37#include <map>
38#include <vector>
39
40namespace tim
41{
42namespace operation
43{
44//
45//--------------------------------------------------------------------------------------//
46/// \struct tim::operation::extra_serialization
47/// \brief Provides a hook to add additional serialization data for the type. Examples
48/// include the roofline components adding roofline data. Note that this is data for the
49/// component type, not data for a component entry in the call-graph.
50///
51template <typename Tp>
53{
54 using PrettyJson_t = cereal::PrettyJSONOutputArchive;
55 using MinimalJson_t = cereal::MinimalJSONOutputArchive;
56
57 TIMEMORY_DEFAULT_OBJECT(extra_serialization)
58
59 explicit extra_serialization(PrettyJson_t& ar, unsigned int ver = 0)
60 {
61 (*this)(ar, ver);
62 }
63
64 explicit extra_serialization(MinimalJson_t& ar, unsigned int ver = 0)
65 {
66 (*this)(ar, ver);
67 }
68
69 template <typename Archive>
70 explicit extra_serialization(Archive& ar, unsigned int ver = 0)
71 {
72 (*this)(ar, ver);
73 }
74
75 auto operator()(PrettyJson_t& ar, unsigned int ver = 0) const
76 {
77 sfinae(ar, ver, 0, 0);
78 }
79
80 auto operator()(MinimalJson_t& ar, unsigned int ver = 0) const
81 {
82 sfinae(ar, ver, 0, 0);
83 }
84
85 template <typename Archive>
86 auto operator()(Archive& ar, unsigned int ver = 0) const
87 {
88 sfinae(ar, ver, 0, 0);
89 }
90
91private:
92 template <typename Archive, typename Up = Tp>
93 auto sfinae(Archive& ar, unsigned int ver, int, int) const
94 -> decltype(Up::extra_serialization(ar, ver), void())
95 {
96 Up::extra_serialization(ar, ver);
97 }
98
99 template <typename Archive, typename Up = Tp>
100 auto sfinae(Archive& ar, unsigned int, int, long) const
101 -> decltype(Up::extra_serialization(ar), void())
102 {
103 Up::extra_serialization(ar);
104 }
105
106 template <typename Archive, typename Up = Tp>
107 auto sfinae(Archive&, unsigned int, long, long) const
108 {}
109};
110//
111namespace internal
112{
113//
114template <typename Tp>
115struct serialization_base
116{
117 using type = Tp;
118
119 struct metadata
120 {};
121
122 struct mpi_data
123 {};
124
125 struct upcxx_data
126 {};
127
128 TIMEMORY_DEFAULT_OBJECT(serialization_base)
129
130public:
131 static std::string to_lower(std::string _inp)
132 {
133 for(auto& itr : _inp)
134 itr = std::tolower(itr);
135 return _inp;
136 }
137
138 static std::string get_identifier(const type& _obj = type{})
139 {
142 : "";
143 if(idstr.empty())
144 idstr = get_identifier_sfinae(_obj, 0);
145 if(idstr.empty())
146 idstr = demangle<type>();
147 return idstr;
148 }
149
150 static auto get_label(const type& _obj = type{})
151 {
152 return get_label_sfinae(_obj, 0, 0);
153 }
154
155 static auto get_description(const type& _obj = type{})
156 {
157 return get_description_sfinae(_obj, 0, 0);
158 }
159
160 static auto get_unit(const type& _obj = type{})
161 {
162 return get_unit_sfinae(_obj, 0, 0);
163 }
164
165 static auto get_display_unit(const type& _obj = type{})
166 {
167 return get_display_unit_sfinae(_obj, 0, 0);
168 }
169
170private:
171 template <typename Up>
172 static auto get_identifier_sfinae(const Up& _data, int) -> decltype(_data.label())
173 {
174 return _data.label();
175 }
176
177 template <typename Up>
178 static auto get_identifier_sfinae(const Up&, long)
179 {
180 return std::string{};
181 }
182
183private:
184 template <typename Up>
185 static auto get_label_sfinae(const Up& _data, int, int)
186 -> decltype(_data.label_array())
187 {
188 return _data.label_array();
189 }
190
191 template <typename Up>
192 static auto get_label_sfinae(const Up& _data, int, long) -> decltype(_data.label())
193 {
194 return _data.label();
195 }
196
197 template <typename Up>
198 static auto get_label_sfinae(const Up&, long, long)
199 {
200 return std::string{};
201 }
202
203private:
204 template <typename Up>
205 static auto get_description_sfinae(const Up& _data, int, int)
206 -> decltype(_data.description_array())
207 {
208 return _data.description_array();
209 }
210
211 template <typename Up>
212 static auto get_description_sfinae(const Up& _data, int, long)
213 -> decltype(_data.description())
214 {
215 return _data.description();
216 }
217
218 template <typename Up>
219 static auto get_description_sfinae(const Up&, long, long)
220 {
221 return std::string{};
222 }
223
224private:
225 template <typename Up>
226 static auto get_unit_sfinae(const Up& _data, int, int) -> decltype(_data.unit_array())
227 {
228 return _data.unit_array();
229 }
230
231 template <typename Up>
232 static auto get_unit_sfinae(const Up& _data, int, long) -> decltype(_data.unit())
233
234 {
235 return _data.unit();
236 }
237
238 template <typename Up>
239 static auto get_unit_sfinae(const Up&, long, long) -> int64_t
240 {
241 return 0;
242 }
243
244private:
245 template <typename Up>
246 static auto get_display_unit_sfinae(const Up& _data, int, int)
247 -> decltype(_data.display_unit_array())
248 {
249 return _data.display_unit_array();
250 }
251
252 template <typename Up>
253 static auto get_display_unit_sfinae(const Up& _data, int, long)
254 -> decltype(_data.display_unit())
255
256 {
257 return _data.display_unit();
258 }
259
260 template <typename Up>
261 static auto get_display_unit_sfinae(const Up&, long, long)
262 {
263 return std::string{};
264 }
265};
266//
267//--------------------------------------------------------------------------------------//
268//
269template <typename Tp, bool AvailV = is_enabled<Tp>::value>
270struct serialization;
271//
272//--------------------------------------------------------------------------------------//
273//
274template <typename Tp>
275struct serialization<Tp, false> : public serialization_base<Tp>
276{
277 using type = Tp;
278 using base_type = serialization_base<Tp>;
279 using metadata = typename base_type::metadata;
280
281 TIMEMORY_DEFAULT_OBJECT(serialization)
282
283 template <typename... Args>
284 serialization(Args&&...)
285 {}
286
287 template <typename... Args>
288 auto operator()(Args&&...) const
289 {}
290};
291//
292//--------------------------------------------------------------------------------------//
293//
294template <typename Tp>
295struct serialization<Tp, true> : public serialization_base<Tp>
296{
297 static constexpr bool value = true;
298 using type = Tp;
299 using base_type = serialization_base<Tp>;
300 using tree_type = node::tree<type>;
301 using graph_node = node::graph<type>;
302 using result_node = node::result<type>;
303 using result_type = std::vector<result_node>;
304 using distrib_type = std::vector<result_type>;
305 using storage_type = impl::storage<type, value>;
306 using graph_type = graph<graph_node>;
307 using hierarchy_type = std::vector<uint64_t>;
308 using basic_tree_type = basic_tree<node::tree<type>>;
309 using basic_tree_vector_type = std::vector<basic_tree_type>;
310 using metadata = typename base_type::metadata;
311 using mpi_data = typename base_type::mpi_data;
312 using basic_tree_map_type =
313 std::map<std::string, std::vector<basic_tree_vector_type>>;
314
315 using base_type::get_description;
316 using base_type::get_display_unit;
317 using base_type::get_identifier;
318 using base_type::get_label;
319 using base_type::get_unit;
320
321 TIMEMORY_DEFAULT_OBJECT(serialization)
322
323private:
324 static constexpr bool component_is_specialized()
325 {
327 }
328
329 template <typename Archive>
330 static constexpr bool is_specialized()
331 {
332 return is_one_of<
333 decay_t<Archive>,
334 type_list<cereal::JSONInputArchive, cereal::MinimalJSONOutputArchive,
335 cereal::PrettyJSONOutputArchive>>::value;
336 }
337
338 template <typename DataT>
339 static constexpr bool is_supported_dtype()
340 {
341 return is_one_of<
342 decay_t<DataT>,
343 type_list<basic_tree_vector_type, std::vector<basic_tree_vector_type>,
344 result_type, distrib_type, basic_tree_map_type>>::value;
345 }
346
347public:
348 // template overloads -- do not get instantiated in extern template
349 template <typename Archive>
350 TIMEMORY_COLD serialization(const Tp& obj, Archive& ar, const unsigned int version,
351 enable_if_t<!is_specialized<Archive>(), int> = 0)
352 {
353 static_assert(!is_specialized<Archive>(),
354 "Error! Calling template function instead of specialized function");
355 impl(obj, ar, version);
356 }
357
358 template <typename Archive>
359 TIMEMORY_COLD void operator()(const Tp& obj, Archive& ar, const unsigned int version,
360 enable_if_t<!is_specialized<Archive>(), int> = 0) const
361 {
362 static_assert(!is_specialized<Archive>(),
363 "Error! Calling template function instead of specialized function");
364 impl(obj, ar, version);
365 }
366
367 template <typename Archive>
368 TIMEMORY_COLD void operator()(Archive& ar, metadata data,
369 enable_if_t<!is_specialized<Archive>(), int> = 0) const
370 {
371 static_assert(!is_specialized<Archive>(),
372 "Error! Calling template function instead of specialized function");
373 impl(ar, data);
374 }
375
376 template <typename Archive, typename DataT>
377 TIMEMORY_COLD void operator()(
378 Archive& ar, const DataT& data,
379 enable_if_t<!is_specialized<Archive>() && is_supported_dtype<DataT>(), int> =
380 0) const
381 {
382 static_assert(!is_specialized<Archive>(),
383 "Error! Calling template function instead of specialized function");
384 impl(ar, data);
385 }
386
387 template <typename Archive, typename DataT>
388 TIMEMORY_COLD void operator()(
389 Archive& ar, DataT& data,
390 enable_if_t<!is_specialized<Archive>() && is_supported_dtype<DataT>(), int> =
391 0) const
392 {
393 static_assert(!is_specialized<Archive>(),
394 "Error! Calling template function instead of specialized function");
395 static_assert(!(std::is_same<decay_t<DataT>, basic_tree_map_type>::value &&
396 concepts::is_input_archive<decay_t<Archive>>::value),
397 "Error! basic_tree_map_type does not support input serialization");
398 impl(ar, data);
399 }
400
401public:
402 // MinimalJSONOutputArchive overloads -- get instantiated in extern template
403 TIMEMORY_COLD serialization(const Tp& obj, cereal::MinimalJSONOutputArchive& ar,
404 const unsigned int version, ...);
405
406 TIMEMORY_COLD void operator()(const Tp& obj, cereal::MinimalJSONOutputArchive& ar,
407 const unsigned int version, ...) const;
408
409 TIMEMORY_COLD void operator()(cereal::MinimalJSONOutputArchive& ar, metadata,
410 ...) const;
411
412 TIMEMORY_COLD void operator()(cereal::MinimalJSONOutputArchive& ar,
413 const basic_tree_vector_type& data, ...) const;
414
415 TIMEMORY_COLD void operator()(cereal::MinimalJSONOutputArchive& ar,
416 const std::vector<basic_tree_vector_type>& data,
417 ...) const;
418
419 TIMEMORY_COLD void operator()(cereal::MinimalJSONOutputArchive& ar,
420 const basic_tree_map_type& data, ...) const;
421
422 TIMEMORY_COLD void operator()(cereal::MinimalJSONOutputArchive& ar,
423 const result_type& data, ...) const;
424
425 TIMEMORY_COLD void operator()(cereal::MinimalJSONOutputArchive& ar,
426 const distrib_type& data, ...) const;
427
428public:
429 // PrettyJSONOutputArchive overloads -- get instantiated in extern template
430 TIMEMORY_COLD serialization(const Tp& obj, cereal::PrettyJSONOutputArchive& ar,
431 const unsigned int version, ...);
432
433 TIMEMORY_COLD void operator()(const Tp& obj, cereal::PrettyJSONOutputArchive& ar,
434 const unsigned int version, ...) const;
435
436 TIMEMORY_COLD void operator()(cereal::PrettyJSONOutputArchive& ar, metadata,
437 ...) const;
438
439 TIMEMORY_COLD void operator()(cereal::PrettyJSONOutputArchive& ar,
440 const basic_tree_vector_type& data, ...) const;
441
442 TIMEMORY_COLD void operator()(cereal::PrettyJSONOutputArchive& ar,
443 const std::vector<basic_tree_vector_type>& data,
444 ...) const;
445
446 TIMEMORY_COLD void operator()(cereal::PrettyJSONOutputArchive& ar,
447 const basic_tree_map_type& data, ...) const;
448
449 TIMEMORY_COLD void operator()(cereal::PrettyJSONOutputArchive& ar,
450 const result_type& data, ...) const;
451
452 TIMEMORY_COLD void operator()(cereal::PrettyJSONOutputArchive& ar,
453 const distrib_type& data, ...) const;
454
455public:
456 // JSONInputArchive overloads -- get instantiated in extern template
457 TIMEMORY_COLD void operator()(cereal::JSONInputArchive& ar,
458 basic_tree_vector_type& data, ...) const;
459
460 TIMEMORY_COLD void operator()(cereal::JSONInputArchive& ar,
461 std::vector<basic_tree_vector_type>& data, ...) const;
462
463 TIMEMORY_COLD void operator()(cereal::JSONInputArchive& ar, result_type& data,
464 ...) const;
465
466 TIMEMORY_COLD void operator()(cereal::JSONInputArchive& ar, distrib_type& data,
467 ...) const;
468
469public:
470 template <typename ValueT>
471 std::vector<decay_t<ValueT>> operator()(mpi_data, mpi::comm_t comm,
472 const ValueT& entry,
473 int32_t comm_target = 0) const;
474
475private:
476 template <typename Archive>
477 TIMEMORY_COLD void impl(const Tp& obj, Archive& ar, const unsigned int) const;
478
479 template <typename Archive>
480 TIMEMORY_COLD void impl(Archive& ar, metadata) const;
481
482 template <typename Archive>
483 TIMEMORY_COLD void impl(
484 Archive& ar, const basic_tree_vector_type& data,
486
487 template <typename Archive>
488 TIMEMORY_COLD void impl(
489 Archive& ar, const std::vector<basic_tree_vector_type>& data,
491
492 template <typename Archive>
493 TIMEMORY_COLD void impl(
494 Archive& ar, const basic_tree_map_type& data,
496
497 template <typename Archive>
498 TIMEMORY_COLD void impl(
499 Archive& ar, const result_type& data,
501
502 template <typename Archive>
503 TIMEMORY_COLD void impl(
504 Archive& ar, const distrib_type& data,
506
507 // input
508 template <typename Archive>
509 TIMEMORY_COLD void impl(
510 Archive& ar, basic_tree_vector_type& data,
512
513 template <typename Archive>
514 TIMEMORY_COLD void impl(
515 Archive& ar, std::vector<basic_tree_vector_type>& data,
517
518 template <typename Archive>
519 TIMEMORY_COLD void impl(
520 Archive& ar, result_type& data,
522
523 template <typename Archive>
524 TIMEMORY_COLD void impl(
525 Archive& ar, distrib_type& data,
527};
528//
529template <typename Tp>
530template <typename Archive>
531void
532serialization<Tp, true>::impl(const Tp& obj, Archive& ar, const unsigned int) const
533{
534 auto try_catch = [&ar](const char* key, const auto& val) {
535 try
536 {
537 ar(cereal::make_nvp(key, val));
538 } catch(cereal::Exception& e)
539 {
540 fprintf(stderr, "Warning! '%s' threw exception: %s\n", key, e.what());
541 }
542 };
543
544 try_catch("laps", obj.get_laps());
545 try_catch("value", obj.get_value());
546 IF_CONSTEXPR(trait::base_has_accum<Tp>::value)
547 {
548 try_catch("accum", obj.get_accum());
549 }
550 IF_CONSTEXPR(trait::base_has_last<Tp>::value) { try_catch("last", obj.get_last()); }
551 try_catch("repr_data", obj.get());
552 try_catch("repr_display", obj.get_display());
553}
554//
555template <typename Tp>
556template <typename Archive>
557void
558serialization<Tp, true>::impl(Archive& ar, metadata) const
559{
560 bool _thread_scope_only = trait::thread_scope_only<type>::value;
561 auto _num_thr_count = manager::get_thread_count();
562 auto _num_pid_count = dmp::size();
563
564 ar(cereal::make_nvp("properties", component::properties<type>{}));
565 ar(cereal::make_nvp("type", get_label()));
566 ar(cereal::make_nvp("description", get_description()));
567 ar(cereal::make_nvp("unit_value", get_unit()));
568 ar(cereal::make_nvp("unit_repr", get_display_unit()));
569 ar(cereal::make_nvp("thread_scope_only", _thread_scope_only));
570 ar(cereal::make_nvp("thread_count", _num_thr_count));
571 ar(cereal::make_nvp("mpi_size", mpi::size()));
572 ar(cereal::make_nvp("upcxx_size", upc::size()));
573 ar(cereal::make_nvp("process_count", _num_pid_count));
574 ar(cereal::make_nvp("num_ranks", dmp::size())); // backwards-compat
575 ar(cereal::make_nvp("concurrency", _num_thr_count)); // backwards-compat
576}
577//
578template <typename Tp>
579template <typename Archive>
580void
581serialization<Tp, true>::impl(
582 Archive& ar, const basic_tree_vector_type& data,
584{
585 auto idstr = get_identifier();
586 ar.setNextName(idstr.c_str());
587 ar.startNode();
588 impl(ar, metadata{});
589 extra_serialization<Tp>{ ar };
590 ar(cereal::make_nvp("graph", data));
591 ar.finishNode();
592}
593//
594template <typename Tp>
595template <typename Archive>
596void
597serialization<Tp, true>::impl(
598 Archive& ar, const std::vector<basic_tree_vector_type>& data,
600{
601 auto idstr = get_identifier();
602 ar.setNextName(idstr.c_str());
603 ar.startNode();
604 impl(ar, metadata{});
605 extra_serialization<Tp>{ ar };
606 ar(cereal::make_nvp("graph", data));
607 ar.finishNode();
608}
609//
610template <typename Tp>
611template <typename Archive>
612void
613serialization<Tp, true>::impl(
614 Archive& ar, const basic_tree_map_type& data,
616{
617 auto idstr = get_identifier();
618 ar.setNextName(idstr.c_str());
619 ar.startNode();
620 impl(ar, metadata{});
621 extra_serialization<Tp>{ ar };
622 auto pitr = data.find("process");
623 if(pitr != data.end())
624 {
625 ar(cereal::make_nvp("graph", pitr->second));
626 }
627 else
628 {
629 for(const auto& itr : data)
630 ar(cereal::make_nvp(itr.first, itr.second));
631 }
632 ar.finishNode();
633}
634//
635template <typename Tp>
636template <typename Archive>
637void
638serialization<Tp, true>::impl(
639 Archive& ar, const result_type& data,
641{
642 // node
643 std::string _name = get_identifier();
644 ar.setNextName(_name.c_str());
645 ar.startNode();
646 impl(ar, metadata{});
647 extra_serialization<Tp>{ ar };
648 cereal::save(ar, data);
649 ar.finishNode(); // ranks
650 ar.finishNode(); // name
651}
652//
653template <typename Tp>
654template <typename Archive>
655void
656serialization<Tp, true>::impl(
657 Archive& ar, const distrib_type& data,
659{
660 // node
661 std::string _name = get_identifier();
662 ar.setNextName(_name.c_str());
663 ar.startNode();
664 impl(ar, metadata{});
665 extra_serialization<Tp>{ ar };
666 ar.setNextName("ranks");
667 ar.startNode();
668 ar.makeArray();
669 for(uint64_t i = 0; i < data.size(); ++i)
670 {
671 if(data.at(i).empty())
672 continue;
673
674 ar.startNode();
675
676 ar(cereal::make_nvp("rank", i));
677 cereal::save(ar, data.at(i));
678
679 ar.finishNode();
680 }
681 ar.finishNode(); // ranks
682 ar.finishNode(); // name
683}
684//
685template <typename Tp>
686template <typename Archive>
687void
688serialization<Tp, true>::impl(
689 Archive& ar, basic_tree_vector_type& data,
691{
692 auto idstr = get_identifier();
693 ar.setNextName(idstr.c_str());
694 ar.startNode();
695 ar(cereal::make_nvp("graph", data));
696 ar.finishNode();
697}
698//
699template <typename Tp>
700template <typename Archive>
701void
702serialization<Tp, true>::impl(
703 Archive& ar, std::vector<basic_tree_vector_type>& data,
705{
706 auto idstr = get_identifier();
707 ar.setNextName(idstr.c_str());
708 ar.startNode();
709 std::stringstream _msg;
710 for(const auto* name : { "graph", "mpi", "upcxx" })
711 {
712 try
713 {
714 std::vector<basic_tree_vector_type> _data{};
715 ar(tim::cereal::make_nvp(name, _data));
716 data.reserve(data.size() + _data.size());
717 for(auto&& itr : _data)
718 data.emplace_back(itr);
719 } catch(tim::cereal::Exception& e)
720 {
721 _msg << e.what() << '\n';
722 }
723 }
724 ar.finishNode();
725 if(data.empty())
726 throw std::runtime_error(_msg.str());
727}
728//
729template <typename Tp>
730template <typename Archive>
731void
732serialization<Tp, true>::impl(
733 Archive& ar, result_type& data,
735{
736 // node
737 std::string _name = get_identifier();
738 ar.setNextName(_name.c_str());
739 ar.startNode();
740 cereal::load(ar, data);
741 ar.finishNode(); // ranks
742 ar.finishNode(); // name
743}
744//
745template <typename Tp>
746template <typename Archive>
747void
748serialization<Tp, true>::impl(
749 Archive& ar, distrib_type& data,
751{
752 // node
753 std::string _name = get_identifier();
754 ar.setNextName(_name.c_str());
755 ar.startNode();
756
757 // node
758 cereal::size_type _nranks = 0;
759 ar.setNextName("ranks");
760 ar.startNode();
761 ar.loadSize(_nranks);
762
763 data.clear();
764 data.resize(_nranks);
765 for(uint64_t i = 0; i < data.size(); ++i)
766 {
767 ar.startNode();
768 ar(cereal::make_nvp("rank", i));
769 try
770 {
771 cereal::load(ar, data.at(i));
772 } catch(std::exception& e)
773 {
774 fprintf(stderr, "%s\n", e.what());
775 }
776 ar.finishNode();
777 }
778
779 ar.finishNode(); // ranks
780 ar.finishNode(); // name
781}
782//
783template <typename Tp>
784template <typename ValueT>
785std::vector<decay_t<ValueT>>
786serialization<Tp, true>::operator()(mpi_data, mpi::comm_t comm, const ValueT& entry,
787 int32_t comm_target) const
788{
789 using data_type = std::vector<decay_t<ValueT>>;
790
791#if !defined(TIMEMORY_USE_MPI)
792 consume_parameters(comm, comm_target);
793 return data_type(1, entry);
794#else
795 using value_type = ValueT;
796 // not yet implemented
797 // auto comm =
798 // (settings::mpi_output_per_node()) ? mpi::get_node_comm() :
799 // mpi::comm_world_v;
800 mpi::barrier(comm);
801
802 int comm_rank = mpi::rank(comm);
803 int comm_size = mpi::size(comm);
804
805 //------------------------------------------------------------------------------//
806 // Used to convert a result to a serialization
807 //
808 auto send_serialize = [&](const value_type& src) {
809 std::stringstream ss;
810 {
811 auto oa = policy::output_archive<cereal::MinimalJSONOutputArchive,
813 (*oa)(cereal::make_nvp("data", src));
814 }
815 return ss.str();
816 };
817
818 //------------------------------------------------------------------------------//
819 // Used to convert the serialization to a result
820 //
821 auto recv_serialize = [&](const std::string& src) {
822 value_type ret{};
823 std::stringstream ss;
824 ss << src;
825 {
826 auto ia =
828 (*ia)(cereal::make_nvp("data", ret));
829 }
830 return ret;
831 };
832
833 if(comm_rank == comm_target)
834 {
835 auto _data = data_type(comm_size);
836 //
837 // The target rank receives data from all non-root ranks and reports all data
838 //
839 for(int i = 1; i < comm_size; ++i)
840 {
841 std::string str{};
842 mpi::recv(str, i, 0, comm);
843 _data[i] = recv_serialize(str);
844 }
845 _data[comm_rank] = entry;
846 return _data;
847 }
848 else
849 {
850 auto str_ret = send_serialize(entry);
851 //
852 // The non-target rank sends its data to the root rank and only reports own
853 // data
854 //
855 mpi::send(str_ret, 0, 0, comm);
856 return data_type(1, entry);
857 }
858#endif
859}
860//
861} // namespace internal
862//
863//--------------------------------------------------------------------------------------//
864//
865template <typename Tp>
866struct serialization : public internal::serialization<Tp, is_enabled<Tp>::value>
867{
868 using type = Tp;
869 using base_type = internal::serialization<Tp, is_enabled<Tp>::value>;
870 using metadata = typename base_type::metadata;
871
872 TIMEMORY_DEFAULT_OBJECT(serialization)
873
874 template <typename... Args>
875 serialization(Args&&... args)
876 : base_type{ std::forward<Args>(args)... }
877 {}
878
879 using base_type::operator();
880 using base_type::get_description;
881 using base_type::get_display_unit;
882 using base_type::get_identifier;
883 using base_type::get_label;
884 using base_type::get_unit;
885};
886//
887//--------------------------------------------------------------------------------------//
888//
889} // namespace operation
890} // namespace tim
891
892#define TIMEMORY_OPERATIONS_TYPES_SERIALIZATION_HPP_
894#undef TIMEMORY_OPERATIONS_TYPES_SERIALIZATION_HPP_
static int32_t get_thread_count()
This effectively provides the total number of threads which collected data. It is only "decremented" ...
Definition: manager.hpp:182
#define IF_CONSTEXPR(...)
Definition: language.hpp:72
STL namespace.
void load(Archive &ar, tim::node::graph< Tp > &d)
Definition: node.hpp:520
void save(Archive &ar, std::shared_ptr< tim::tsettings< Tp, Tp & > > obj)
Definition: tsettings.hpp:471
return false
Definition: definition.hpp:326
std::bitset< scope_count > data_type
Definition: types.hpp:399
data::entry entry
Definition: stream.hpp:980
Definition: kokkosp.cpp:39
typename std::enable_if< B, T >::type enable_if_t
Alias template for enable_if.
Definition: types.hpp:190
tim::mpl::apply< std::string > string
Definition: macros.hpp:53
typename impl::is_one_of< Tp, Types > is_one_of
check if type is in expansion
Definition: types.hpp:777
auto get(const auto_bundle< Tag, Types... > &_obj)
void consume_parameters(ArgsT &&...)
Definition: types.hpp:285
The declaration for the types for operations without definitions.
Include the macros for operations.
Declare the operations types.
static constexpr const char * enum_string()
Definition: properties.hpp:220
static constexpr bool specialized()
Definition: properties.hpp:219
static constexpr bool value
Definition: concepts.hpp:459
static constexpr bool value
Definition: concepts.hpp:435
Provides a hook to add additional serialization data for the type. Examples include the roofline comp...
auto operator()(PrettyJson_t &ar, unsigned int ver=0) const
extra_serialization(Archive &ar, unsigned int ver=0)
auto operator()(Archive &ar, unsigned int ver=0) const
auto operator()(MinimalJson_t &ar, unsigned int ver=0) const
extra_serialization(MinimalJson_t &ar, unsigned int ver=0)
cereal::PrettyJSONOutputArchive PrettyJson_t
cereal::MinimalJSONOutputArchive MinimalJson_t
typename base_type::metadata metadata
internal::serialization< Tp, is_enabled< Tp >::value > base_type
static pointer get(std::istream &is)
Definition: policy.hpp:96
type_list
Definition: types.hpp:211