From f999a09aea1d4ab341f113faf34b9fe83155cfe2 Mon Sep 17 00:00:00 2001 From: Caleb Schilly Date: Tue, 18 Jun 2024 15:58:11 -0400 Subject: [PATCH 1/4] #78: fix max load and max volume bugs for multiple phases --- src/vt-tv/api/info.h | 58 +++++++++++++++++++++++++++----------- src/vt-tv/render/render.cc | 6 ++++ 2 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/vt-tv/api/info.h b/src/vt-tv/api/info.h index 708c335865..39270efca5 100644 --- a/src/vt-tv/api/info.h +++ b/src/vt-tv/api/info.h @@ -92,6 +92,10 @@ struct Info { ranks_.try_emplace(r.getRankID(), std::move(r)); } + void setSelectedPhase(PhaseType selected_phase) { + selected_phase_ = selected_phase; + } + /** * \brief Get all object info * @@ -395,14 +399,23 @@ struct Info { the maximum volume by iterated through object ids. */ auto n_phases = this->getNumPhases(); - for (PhaseType phase = 0; phase < n_phases; phase++) { - auto const& objects = this->getPhaseObjects(phase); - for (auto const& [obj_id, obj_work] : objects) { - auto obj_max_v = obj_work.getMaxVolume(); - if (obj_max_v > ov_max) ov_max = obj_max_v; + + if (selected_phase_ != std::numeric_limits::max()) { + auto const& objects = this->getPhaseObjects(selected_phase_); + for (auto const& [obj_id, obj_work] : objects) { + auto obj_max_v = obj_work.getMaxVolume(); + if (obj_max_v > ov_max) ov_max = obj_max_v; + } + } else { + for (PhaseType phase = 0; phase < n_phases; phase++) {{ + auto const& objects = this->getPhaseObjects(phase); + for (auto const& [obj_id, obj_work] : objects) { + auto obj_max_v = obj_work.getMaxVolume(); + if (obj_max_v > ov_max) ov_max = obj_max_v; + } + } } } - return ov_max; } @@ -415,14 +428,22 @@ struct Info { double ol_max = 0.; auto n_phases = this->getNumPhases(); - for (PhaseType phase = 0; phase < n_phases; phase++) { - auto const& objects = this->getPhaseObjects(phase); + + if (selected_phase_ != std::numeric_limits::max()) { + auto const& objects = this->getPhaseObjects(selected_phase_); for (auto const& [obj_id, obj_work] : objects) { auto obj_load = obj_work.getLoad(); if (obj_load > ol_max) ol_max = obj_load; } + } else { + for (PhaseType phase = 0; phase < n_phases; phase++) { + auto const& objects = this->getPhaseObjects(phase); + for (auto const& [obj_id, obj_work] : objects) { + auto obj_load = obj_work.getLoad(); + if (obj_load > ol_max) ol_max = obj_load; + } + } } - return ol_max; } @@ -569,25 +590,25 @@ struct Info { } // loop through ranks and add communications - fmt::print("Updating communications for phase {}.\n", phase); + // fmt::print("Updating communications for phase {}.\n", phase); for (auto &[rank_id, rank]: ranks_) { - fmt::print(" Checking objects in rank {}.\n", rank_id); + // fmt::print(" Checking objects in rank {}.\n", rank_id); auto &phaseWork = rank.getPhaseWork(); auto &phaseWorkAtPhase = phaseWork.at(phase); auto &objects = phaseWorkAtPhase.getObjectWork(); for (auto &[obj_id, obj_work]: objects) { - fmt::print(" Checking if object {} needs to be updated.\n", obj_id); - fmt::print(" Communications to update:\n"); + // fmt::print(" Checking if object {} needs to be updated.\n", obj_id); + // fmt::print(" Communications to update:\n"); uint64_t i = 0; for (auto &[object_to_update, sender_id, recipient_id, bytes]: communications_to_add) { - fmt::print(" {} needs to be updated in {} -> {} communication of {} bytes.\n", object_to_update, - sender_id, recipient_id, bytes); + // fmt::print(" {} needs to be updated in {} -> {} communication of {} bytes.\n", object_to_update, + // sender_id, recipient_id, bytes); if (object_to_update == "sender" && sender_id == obj_id) { - fmt::print(" Sender to be updated is object on this rank. Updating.\n"); + // fmt::print(" Sender to be updated is object on this rank. Updating.\n"); rank.addObjectSentCommunicationAtPhase(phase, obj_id, recipient_id, bytes); communications_to_add.erase(communications_to_add.begin() + i); } else if (object_to_update == "recipient" && recipient_id == obj_id) { - fmt::print(" Recipient to be updated is object on this rank. Updating.\n"); + // fmt::print(" Recipient to be updated is object on this rank. Updating.\n"); rank.addObjectReceivedCommunicationAtPhase(phase, obj_id, sender_id, bytes); communications_to_add.erase(communications_to_add.begin() + i); } @@ -875,6 +896,9 @@ struct Info { /// Work for each rank across phases std::unordered_map ranks_; + + /// The current phase (or indication to use all phases) + PhaseType selected_phase_; }; } /* end namespace vt::tv */ diff --git a/src/vt-tv/render/render.cc b/src/vt-tv/render/render.cc index 5f9bc1301d..4bfb248b1b 100644 --- a/src/vt-tv/render/render.cc +++ b/src/vt-tv/render/render.cc @@ -76,6 +76,9 @@ Render::Render(Info in_info) } max_o_per_dim_ = 0; + // Set the info selected_phase + this->info_.setSelectedPhase(selected_phase_); + // Normalize communication edges for(PhaseType phase = 0; phase < this->n_phases_; phase++) { if ( selected_phase_ == std::numeric_limits::max() or @@ -144,6 +147,9 @@ Render::Render( } max_o_per_dim_ = 0; + // Set the info selected_phase + this->info_.setSelectedPhase(selected_phase_); + // Normalize communication edges for(PhaseType phase = 0; phase < this->n_phases_; phase++) { if ( From e0e9c7e14c5c05e98f6f48f290d20d2ba67dbde7 Mon Sep 17 00:00:00 2001 From: Caleb Schilly Date: Tue, 18 Jun 2024 16:14:27 -0400 Subject: [PATCH 2/4] #78: handle case where selected_phase is not given --- src/vt-tv/render/render.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/vt-tv/render/render.cc b/src/vt-tv/render/render.cc index 4bfb248b1b..9d64c05c81 100644 --- a/src/vt-tv/render/render.cc +++ b/src/vt-tv/render/render.cc @@ -56,8 +56,10 @@ Render::Render(Info in_info) , n_ranks_(in_info.getNumRanks()) , n_phases_(in_info.getNumPhases()) { - // Generically set rank grid dimensions according to the total number of ranks + // If selected_phase is not provided, use all phases + selected_phase_ = std::numeric_limits::max(); + // Generically set rank grid dimensions according to the total number of ranks grid_size_[2] = 1; // we assume 2D representation int sqrt_n_ranks = std::sqrt(n_ranks_); From 28d28dfdfd63401e67d8be0c960666315158562d Mon Sep 17 00:00:00 2001 From: Caleb Schilly Date: Tue, 18 Jun 2024 16:59:13 -0400 Subject: [PATCH 3/4] #78: fix phase looping in render.cc --- src/vt-tv/render/render.cc | 115 +++++++++++++++++++++++++++++-------- 1 file changed, 90 insertions(+), 25 deletions(-) diff --git a/src/vt-tv/render/render.cc b/src/vt-tv/render/render.cc index 9d64c05c81..bcd62d1fc4 100644 --- a/src/vt-tv/render/render.cc +++ b/src/vt-tv/render/render.cc @@ -82,9 +82,10 @@ Render::Render(Info in_info) this->info_.setSelectedPhase(selected_phase_); // Normalize communication edges - for(PhaseType phase = 0; phase < this->n_phases_; phase++) { - if ( selected_phase_ == std::numeric_limits::max() or - selected_phase_ == phase ) { + if (selected_phase_ != std::numeric_limits::max()) { + this->info_.normalizeEdges(selected_phase_); + } else { + for (PhaseType phase = 0; phase < this->n_phases_; phase++) { this->info_.normalizeEdges(phase); } } @@ -136,10 +137,6 @@ Render::Render( , save_pngs_(in_save_pngs) , selected_phase_(in_selected_phase) { - if (selected_phase_ != std::numeric_limits::max()) { - n_phases_ = std::max(selected_phase_ + 1, n_phases_); - } - // initialize number of ranks n_ranks_ = info_.getNumRanks(); @@ -153,12 +150,11 @@ Render::Render( this->info_.setSelectedPhase(selected_phase_); // Normalize communication edges - for(PhaseType phase = 0; phase < this->n_phases_; phase++) { - if ( - selected_phase_ == std::numeric_limits::max() or - selected_phase_ == phase - ) { - this->info_.normalizeEdges(phase); + if (selected_phase_ != std::numeric_limits::max()) { + this->info_.normalizeEdges(selected_phase_); + } else { + for (PhaseType phase = 0; phase < this->n_phases_; phase++) { + this->info_.normalizeEdges(phase); } } @@ -194,11 +190,28 @@ std::variant, std::set>> Rend std::set> oq_all; // Iterate over all ranks - for(PhaseType phase = 0; phase < this->n_phases_; phase++) { - if ( - selected_phase_ == std::numeric_limits::max() or - selected_phase_ == phase - ) { + if (selected_phase_ != std::numeric_limits::max()) { + auto const& objects = this->info_.getPhaseObjects(selected_phase_); + for (auto const& [obj_id, obj_work] : objects) { + // Update maximum object qoi + oq = info_.getObjectQoi(obj_id, selected_phase_, this->object_qoi_); + if (!continuous_object_qoi_) { + // Allow for integer categorical QOI (i.e. rank_id) + if (oq == static_cast(oq)) { + oq_all.insert(static_cast(oq)); + } else { + oq_all.insert(oq); + } + if(oq_all.size() > 20) { + oq_all.clear(); + continuous_object_qoi_ = true; + } + } + if (oq > oq_max) oq_max = oq; + if (oq < oq_min) oq_min = oq; + } + } else { + for (PhaseType phase = 0; phase < this->n_phases_; phase++) { auto const& objects = this->info_.getPhaseObjects(phase); for (auto const& [obj_id, obj_work] : objects) { // Update maximum object qoi @@ -928,8 +941,12 @@ void Render::renderPNG( // Add field data text information to render // Create text std::stringstream ss; - ss << "Phase: " << phase << "/" << (this->n_phases_ - 1) << "\n" - << "Load Imbalance: " << std::fixed << std::setprecision(2) << this->info_.getImbalance(phase); + if (selected_phase_ != std::numeric_limits::max()) { + ss << "Phase: " << phase << "\n"; + } else { + ss << "Phase: " << phase << "/" << (this->n_phases_ - 1) << "\n"; + } + ss << "Load Imbalance: " << std::fixed << std::setprecision(2) << this->info_.getImbalance(phase); // Setup text actor vtkSmartPointer text_actor = vtkSmartPointer::New(); text_actor->SetInput(ss.str().c_str()); @@ -983,11 +1000,59 @@ void Render::generate(uint64_t font_size, uint64_t win_size) { fmt::print("selected phase={}\n", selected_phase_); - for(PhaseType phase = 0; phase < this->n_phases_; phase++) { - if ( - selected_phase_ == std::numeric_limits::max() or - selected_phase_ == phase - ) { + if (selected_phase_ != std::numeric_limits::max()) { + vtkNew object_mesh = this->createObjectMesh_(selected_phase_); + vtkNew rank_mesh = this->createRankMesh_(selected_phase_); + + if (save_meshes_){ + fmt::print("== Writing object mesh for phase {}\n", selected_phase_); + vtkNew writer; + std::string object_mesh_filename = output_dir_ + output_file_stem_ + "_object_mesh_" + std::to_string(selected_phase_) + ".vtp"; + writer->SetFileName(object_mesh_filename.c_str()); + writer->SetInputData(object_mesh); + writer->Write(); + + fmt::print("== Writing rank mesh for phase {}\n", selected_phase_); + vtkNew writer2; + std::string rank_mesh_filneame = output_dir_ + output_file_stem_ + "_rank_mesh_" + std::to_string(selected_phase_) + ".vtp"; + writer2->SetFileName(rank_mesh_filneame.c_str()); + writer2->SetInputData(rank_mesh); + writer2->Write(); + } + + if (save_pngs_){ + fmt::print("== Rendering visualization PNG for phase {}\n", selected_phase_); + + std::pair obj_qoi_range; + try { + obj_qoi_range = std::get>(this->object_qoi_range_); + } + catch(const std::exception& e) { + std::cerr << e.what() << '\n'; + obj_qoi_range = {0, 1}; + } + + uint64_t window_size = win_size; + uint64_t edge_width = 0.03 * window_size / *std::max_element(this->grid_size_.begin(), this->grid_size_.end()); + double glyph_factor = 0.8 * this->grid_resolution_ / ( + (this->max_o_per_dim_ + 1) + * std::sqrt(object_load_max_)); + fmt::print(" Image size: {}x{}px\n", win_size, win_size); + fmt::print(" Font size: {}pt\n", font_size); + this->renderPNG( + selected_phase_, + rank_mesh, + object_mesh, + edge_width, + glyph_factor, + window_size, + font_size, + output_dir_, + output_file_stem_ + ); + } + } else { + for (PhaseType phase = 0; phase < this->n_phases_; phase++) { vtkNew object_mesh = this->createObjectMesh_(phase); vtkNew rank_mesh = this->createRankMesh_(phase); From 81cdfab9a44b1d63d2e0a035bdfcfe5ecd1ef691 Mon Sep 17 00:00:00 2001 From: Caleb Schilly Date: Wed, 19 Jun 2024 09:28:03 -0400 Subject: [PATCH 4/4] #78: reduce duplicated code --- src/vt-tv/render/render.cc | 97 ++++++++------------------------------ 1 file changed, 20 insertions(+), 77 deletions(-) diff --git a/src/vt-tv/render/render.cc b/src/vt-tv/render/render.cc index bcd62d1fc4..95c3307b0e 100644 --- a/src/vt-tv/render/render.cc +++ b/src/vt-tv/render/render.cc @@ -189,12 +189,11 @@ std::variant, std::set>> Rend double oq; std::set> oq_all; - // Iterate over all ranks - if (selected_phase_ != std::numeric_limits::max()) { - auto const& objects = this->info_.getPhaseObjects(selected_phase_); + // Update the QOI range + auto updateQoiRange = [&](auto const& objects, PhaseType phase) { for (auto const& [obj_id, obj_work] : objects) { // Update maximum object qoi - oq = info_.getObjectQoi(obj_id, selected_phase_, this->object_qoi_); + oq = info_.getObjectQoi(obj_id, phase, this->object_qoi_); if (!continuous_object_qoi_) { // Allow for integer categorical QOI (i.e. rank_id) if (oq == static_cast(oq)) { @@ -210,27 +209,16 @@ std::variant, std::set>> Rend if (oq > oq_max) oq_max = oq; if (oq < oq_min) oq_min = oq; } + }; + + // Iterate over all ranks + if (selected_phase_ != std::numeric_limits::max()) { + auto const& objects = this->info_.getPhaseObjects(selected_phase_); + updateQoiRange(objects, selected_phase_); } else { for (PhaseType phase = 0; phase < this->n_phases_; phase++) { auto const& objects = this->info_.getPhaseObjects(phase); - for (auto const& [obj_id, obj_work] : objects) { - // Update maximum object qoi - oq = info_.getObjectQoi(obj_id, phase, this->object_qoi_); - if (!continuous_object_qoi_) { - // Allow for integer categorical QOI (i.e. rank_id) - if (oq == static_cast(oq)) { - oq_all.insert(static_cast(oq)); - } else { - oq_all.insert(oq); - } - if(oq_all.size() > 20) { - oq_all.clear(); - continuous_object_qoi_ = true; - } - } - if (oq > oq_max) oq_max = oq; - if (oq < oq_min) oq_min = oq; - } + updateQoiRange(objects, phase); } } @@ -1000,63 +988,11 @@ void Render::generate(uint64_t font_size, uint64_t win_size) { fmt::print("selected phase={}\n", selected_phase_); - if (selected_phase_ != std::numeric_limits::max()) { - vtkNew object_mesh = this->createObjectMesh_(selected_phase_); - vtkNew rank_mesh = this->createRankMesh_(selected_phase_); - - if (save_meshes_){ - fmt::print("== Writing object mesh for phase {}\n", selected_phase_); - vtkNew writer; - std::string object_mesh_filename = output_dir_ + output_file_stem_ + "_object_mesh_" + std::to_string(selected_phase_) + ".vtp"; - writer->SetFileName(object_mesh_filename.c_str()); - writer->SetInputData(object_mesh); - writer->Write(); - - fmt::print("== Writing rank mesh for phase {}\n", selected_phase_); - vtkNew writer2; - std::string rank_mesh_filneame = output_dir_ + output_file_stem_ + "_rank_mesh_" + std::to_string(selected_phase_) + ".vtp"; - writer2->SetFileName(rank_mesh_filneame.c_str()); - writer2->SetInputData(rank_mesh); - writer2->Write(); - } - - if (save_pngs_){ - fmt::print("== Rendering visualization PNG for phase {}\n", selected_phase_); - - std::pair obj_qoi_range; - try { - obj_qoi_range = std::get>(this->object_qoi_range_); - } - catch(const std::exception& e) { - std::cerr << e.what() << '\n'; - obj_qoi_range = {0, 1}; - } - - uint64_t window_size = win_size; - uint64_t edge_width = 0.03 * window_size / *std::max_element(this->grid_size_.begin(), this->grid_size_.end()); - double glyph_factor = 0.8 * this->grid_resolution_ / ( - (this->max_o_per_dim_ + 1) - * std::sqrt(object_load_max_)); - fmt::print(" Image size: {}x{}px\n", win_size, win_size); - fmt::print(" Font size: {}pt\n", font_size); - this->renderPNG( - selected_phase_, - rank_mesh, - object_mesh, - edge_width, - glyph_factor, - window_size, - font_size, - output_dir_, - output_file_stem_ - ); - } - } else { - for (PhaseType phase = 0; phase < this->n_phases_; phase++) { + auto createMeshAndRender = [&](PhaseType phase) { vtkNew object_mesh = this->createObjectMesh_(phase); vtkNew rank_mesh = this->createRankMesh_(phase); - if (save_meshes_){ + if (save_meshes_) { fmt::print("== Writing object mesh for phase {}\n", phase); vtkNew writer; std::string object_mesh_filename = output_dir_ + output_file_stem_ + "_object_mesh_" + std::to_string(phase) + ".vtp"; @@ -1072,7 +1008,7 @@ void Render::generate(uint64_t font_size, uint64_t win_size) { writer2->Write(); } - if (save_pngs_){ + if (save_pngs_) { fmt::print("== Rendering visualization PNG for phase {}\n", phase); std::pair obj_qoi_range; @@ -1103,6 +1039,13 @@ void Render::generate(uint64_t font_size, uint64_t win_size) { output_file_stem_ ); } + }; + + if (selected_phase_ != std::numeric_limits::max()) { + createMeshAndRender(selected_phase_); + } else { + for (PhaseType phase = 0; phase < this->n_phases_; phase++) { + createMeshAndRender(phase); } } }