174 std::lock_guard< std::mutex > lock( mtx );
182 std::lock_guard< std::mutex > lock( mtx );
183 if ( !current->children.contains( name ) )
185 current->children[name] = std::make_shared< TimerNode >( name, current );
187 current = current->children[name].get();
193 std::lock_guard< std::mutex > lock( mtx );
194 current->total_time += elapsed;
196 if ( current->parent )
198 current = current->parent;
231 void aggregate_node(
TimerNode* node, MPI_Comm comm )
233 double local_time = node->total_time;
234 double root_time, min_time, max_time, sum_time;
236 root_time = local_time;
237 MPI_Bcast( &root_time, 1, MPI_DOUBLE, 0, MPI_COMM_WORLD );
238 MPI_Allreduce( &local_time, &min_time, 1, MPI_DOUBLE, MPI_MIN, comm );
239 MPI_Allreduce( &local_time, &max_time, 1, MPI_DOUBLE, MPI_MAX, comm );
240 MPI_Allreduce( &local_time, &sum_time, 1, MPI_DOUBLE, MPI_SUM, comm );
243 MPI_Comm_size( comm, &size );
244 node->root_time = root_time;
245 node->sum_time = sum_time;
246 node->min_time = min_time;
247 node->max_time = max_time;
248 node->avg_time = sum_time / size;
251 const auto union_children = gather_union_child_names( node, comm );
256 for (
const auto& name : union_children )
258 auto it = node->children.find( name );
259 if ( it == node->children.end() )
261 node->children[name] = std::make_shared< TimerNode >( name, node );
262 it = node->children.find( name );
264 aggregate_node( it->second.get(), comm );
273 std::set< std::string > gather_union_child_names(
const TimerNode* node, MPI_Comm comm )
275 int rank = 0, size = 0;
276 MPI_Comm_rank( comm, &rank );
277 MPI_Comm_size( comm, &size );
283 local.reserve( 256 );
284 for (
const auto& name : node->children | std::ranges::views::keys )
286 local.append( std::to_string( name.size() ) );
287 local.push_back(
':' );
288 local.append( name );
289 local.push_back(
'|' );
292 int local_bytes =
static_cast< int >( local.size() );
293 std::vector< int > counts( size ), displs( size );
294 MPI_Allgather( &local_bytes, 1, MPI_INT, counts.data(), 1, MPI_INT, comm );
296 for (
int r = 0;
r < size; ++
r ) { displs[
r] = total; total += counts[
r]; }
298 std::string all( total,
'\0' );
299 MPI_Allgatherv( local.data(), local_bytes, MPI_CHAR,
300 all.data(), counts.data(), displs.data(), MPI_CHAR, comm );
302 std::set< std::string > names;
304 while ( i < all.size() )
306 size_t colon = all.find(
':', i );
307 if ( colon == std::string::npos )
break;
308 const int nlen = std::stoi( all.substr( i, colon - i ) );
309 names.insert( all.substr( colon + 1, nlen ) );
310 i = colon + 1 + nlen + 1;