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.
basic_tree.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
28#include "timemory/tpls/cereal/cereal.hpp"
30
31#include <iterator>
32#include <set>
33#include <vector>
34
35namespace tim
36{
37/// \struct tim::basic_tree
38/// \tparam Tp Component type
39///
40/// \brief Basic hierarchical tree implementation. Expects population from
41/// \ref tim::graph
42template <typename Tp>
44{
46 using value_type = Tp;
48 using child_pointer = std::shared_ptr<child_type>;
49 using children_type = std::vector<child_pointer>;
50 using children_base = std::vector<child_type>;
51
52 TIMEMORY_DEFAULT_OBJECT(basic_tree)
53
54 /// construction from `tim::graph<Tp>`
55 template <typename GraphT, typename ItrT>
56 TIMEMORY_COLD this_type& operator()(const GraphT& g, ItrT root);
57
58 TIMEMORY_COLD this_type& operator+=(const this_type& rhs);
59 TIMEMORY_COLD this_type& operator-=(const this_type& rhs);
60
61 template <typename Archive>
62 TIMEMORY_COLD void save(Archive& ar, const unsigned int) const;
63
64 template <typename Archive>
65 TIMEMORY_COLD void load(Archive& ar, const unsigned int);
66
67 /// return the current tree node
68 auto& get_value() { return m_value; }
69 /// return the array of child nodes
70 auto& get_children() { return m_children; }
71
72 const auto& get_value() const { return m_value; }
73 const auto& get_children() const { return m_children; }
74
75 friend bool operator==(const this_type& lhs, const this_type& rhs)
76 {
77 // auto _lhash = get_hash_id(get_hash_aliases(), lhs.m_value.hash());
78 // auto _rhash = get_hash_id(get_hash_aliases(), rhs.m_value.hash());
79 return (lhs.m_value.hash() == rhs.m_value.hash());
80 }
81
82 friend bool operator!=(const this_type& lhs, const this_type& rhs)
83 {
84 return !(lhs == rhs);
85 }
86
87private:
88 value_type m_value = {};
89 children_type m_children = {};
90};
91//
92template <typename Tp>
93template <typename GraphT, typename ItrT>
94basic_tree<Tp>&
95basic_tree<Tp>::operator()(const GraphT& g, ItrT root)
96{
97 using iterator_t = typename GraphT::sibling_iterator;
98 using entry_type = std::decay_t<decltype(std::declval<ItrT>()->data())>;
99
100 m_value = *root;
101 iterator_t _begin = g.begin(root);
102 iterator_t _end = g.end(root);
103 auto nchildren = std::distance(_begin, _end);
104 if(nchildren > 0)
105 {
106 m_children.reserve(nchildren);
107 for(auto itr = _begin; itr != _end; ++itr)
108 {
109 if(!itr->is_dummy() &&
111 {
112 m_value.exclusive().data() -= itr->data();
113 m_value.exclusive().stats() -= itr->stats();
114 m_children.emplace_back(std::make_shared<child_type>());
115 m_children.back()->operator()(g, itr);
116 }
117 else
118 {
119 iterator_t _dbegin = g.begin(itr);
120 iterator_t _dend = g.end(itr);
121 for(auto ditr = _dbegin; ditr != _dend; ++ditr)
122 {
123 if(!ditr->is_dummy())
124 {
125 m_children.emplace_back(std::make_shared<child_type>());
126 m_children.back()->operator()(g, ditr);
127 }
128 }
129 }
130 }
131 }
132 return *this;
133}
134
135template <typename Tp>
138{
139 if(*this == rhs)
140 {
141 m_value += rhs.m_value;
142 }
143 if(false)
144 {
145 for(auto& ritr : rhs.m_children)
146 m_children.insert(m_children.end(), ritr);
147 }
148 else
149 {
150 std::set<size_t> found{};
151 auto nitr = std::min<size_t>(m_children.size(), rhs.m_children.size());
152 // add identical entries
153 for(size_t i = 0; i < nitr; ++i)
154 {
155 if((*m_children.at(i)) == (*rhs.m_children.at(i)))
156 {
157 found.insert(i);
158 (*m_children.at(i)) += (*rhs.m_children.at(i));
159 }
160 }
161 // add to first matching entry
162 for(size_t i = 0; i < rhs.m_children.size(); ++i)
163 {
164 if(found.find(i) != found.end())
165 continue;
166 for(size_t j = 0; j < m_children.size(); ++j)
167 {
168 if((*m_children.at(j)) == (*rhs.m_children.at(i)))
169 {
170 found.insert(i);
171 (*m_children.at(j)) += (*rhs.m_children.at(i));
172 }
173 }
174 }
175 // append to end if not found anywhere
176 for(size_t i = 0; i < rhs.m_children.size(); ++i)
177 {
178 if(found.find(i) != found.end())
179 continue;
180 m_children.insert(m_children.end(), rhs.m_children.at(i));
181 }
182 }
183 return *this;
184}
185
186template <typename Tp>
189{
190 if(*this == rhs)
191 {
192 m_value -= rhs.m_value;
193 }
194
195 std::set<size_t> found{};
196 auto nitr = std::min<size_t>(m_children.size(), rhs.m_children.size());
197 // add identical entries
198 for(size_t i = 0; i < nitr; ++i)
199 {
200 if((*m_children.at(i)) == (*rhs.m_children.at(i)))
201 {
202 found.insert(i);
203 m_children.at(i) -= rhs.m_children.at(i);
204 }
205 }
206 // add to first matching entry
207 for(size_t i = 0; i < rhs.m_children.size(); ++i)
208 {
209 if(found.find(i) != found.end())
210 continue;
211 for(size_t j = 0; j < m_children.size(); ++j)
212 {
213 if((*m_children.at(j)) == (*rhs.m_children.at(i)))
214 {
215 found.insert(i);
216 m_children.at(j) -= rhs.m_children.at(i);
217 }
218 }
219 }
220 return *this;
221}
222
223template <typename Tp>
224template <typename Archive>
225void
226basic_tree<Tp>::save(Archive& ar, const unsigned int) const
227{
228 // this is for backward compatiblity
229 children_base _children{};
230 for(const auto& itr : m_children)
231 _children.emplace_back(*itr);
232 ar(cereal::make_nvp("node", m_value), cereal::make_nvp("children", _children));
233}
234
235template <typename Tp>
236template <typename Archive>
237void
238basic_tree<Tp>::load(Archive& ar, const unsigned int)
239{
240 // this is for backward compatiblity
241 children_base _children{};
242 ar(cereal::make_nvp("node", m_value), cereal::make_nvp("children", _children));
243 for(auto&& itr : _children)
244 m_children.emplace_back(std::make_shared<child_type>(std::move(itr)));
245}
246//
247} // namespace tim
Definition: kokkosp.cpp:39
Basic hierarchical tree implementation. Expects population from tim::graph.
Definition: basic_tree.hpp:44
const auto & get_value() const
Definition: basic_tree.hpp:72
void load(Archive &ar, const unsigned int)
Definition: basic_tree.hpp:238
this_type & operator()(const GraphT &g, ItrT root)
construction from tim::graph<Tp>
friend bool operator==(const this_type &lhs, const this_type &rhs)
Definition: basic_tree.hpp:75
friend bool operator!=(const this_type &lhs, const this_type &rhs)
Definition: basic_tree.hpp:82
this_type & operator-=(const this_type &rhs)
Definition: basic_tree.hpp:188
void save(Archive &ar, const unsigned int) const
Definition: basic_tree.hpp:226
std::shared_ptr< child_type > child_pointer
Definition: basic_tree.hpp:48
const auto & get_children() const
Definition: basic_tree.hpp:73
this_type & operator+=(const this_type &rhs)
Definition: basic_tree.hpp:137
basic_tree< Tp > this_type
Definition: basic_tree.hpp:45
auto & get_value()
return the current tree node
Definition: basic_tree.hpp:68
auto & get_children()
return the array of child nodes
Definition: basic_tree.hpp:70
std::vector< child_type > children_base
Definition: basic_tree.hpp:50
std::vector< child_pointer > children_type
Definition: basic_tree.hpp:49
This operation attempts to call a member function which provides whether or not the component is in a...
Definition: types.hpp:673