From c573cb822fdfefd9a163a190c7d41f8eed94068a Mon Sep 17 00:00:00 2001 From: Raphael Steiner Date: Mon, 17 Nov 2025 13:31:52 +0100 Subject: [PATCH] ridding of duplicated code --- include/osp/coarser/Sarkar/Sarkar.hpp | 330 ++++---------------------- 1 file changed, 41 insertions(+), 289 deletions(-) diff --git a/include/osp/coarser/Sarkar/Sarkar.hpp b/include/osp/coarser/Sarkar/Sarkar.hpp index 7845b049..aa0d5560 100644 --- a/include/osp/coarser/Sarkar/Sarkar.hpp +++ b/include/osp/coarser/Sarkar/Sarkar.hpp @@ -32,11 +32,9 @@ limitations under the License. #include "osp/coarser/Coarser.hpp" #include "osp/graph_algorithms/directed_graph_path_util.hpp" - namespace osp { namespace SarkarParams { - enum class Mode { LINES, FAN_IN_FULL, FAN_IN_PARTIAL, FAN_OUT_FULL, FAN_OUT_PARTIAL, LEVEL_EVEN, LEVEL_ODD, FAN_IN_BUFFER, FAN_OUT_BUFFER, HOMOGENEOUS_BUFFER }; template @@ -68,9 +66,6 @@ class Sarkar : public CoarserGenExpansionMap { vertex_idx_t levelContraction(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const; vertex_idx_t homogeneous_buffer_merge(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const; - vertex_idx_t out_buffer_merge(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const; - vertex_idx_t in_buffer_merge(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const; - std::vector homogeneousMerge(const std::size_t number, const std::size_t minSize, const std::size_t maxSize) const; std::vector computeNodeHashes(const Graph_t_in &graph, const std::vector< vertex_idx_t > &vertexPoset, const std::vector< v_workw_t > &dist) const; @@ -94,11 +89,6 @@ class Sarkar : public CoarserGenExpansionMap { std::string getCoarserName() const override { return "Sarkar"; } }; - - - - - template std::vector< vertex_idx_t > Sarkar::getBotPosetMap(const Graph_t_in &graph) const { std::vector< vertex_idx_t > botPosetMap = get_bottom_node_distance>(graph); @@ -153,7 +143,6 @@ std::vector< v_workw_t > Sarkar::getBotDist return botDist; } - template vertex_idx_t Sarkar::singleContraction(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { using VertexType = vertex_idx_t; @@ -271,7 +260,6 @@ vertex_idx_t Sarkar::singleContraction(v_wo return counter; } - template vertex_idx_t Sarkar::allChildrenContraction(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { using VertexType = vertex_idx_t; @@ -399,10 +387,6 @@ vertex_idx_t Sarkar::allChildrenContraction return counter; } - - - - template vertex_idx_t Sarkar::allParentsContraction(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { using VertexType = vertex_idx_t; @@ -546,7 +530,6 @@ std::vector>> Sarkar>> expansionMap; // std::cout << "Mode: " << static_cast(params.mode) << "\n"; - switch (params.mode) { case SarkarParams::Mode::LINES: @@ -592,17 +575,7 @@ std::vector>> Sarkar>> Sarkar std::vector>> Sarkar::generate_vertex_expansion_map(const Graph_t_in &dag_in) { vertex_idx_t dummy; return generate_vertex_expansion_map(dag_in, dummy); } - - template vertex_idx_t Sarkar::someChildrenContraction(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { using VertexType = vertex_idx_t; @@ -802,14 +770,6 @@ vertex_idx_t Sarkar::someChildrenContractio return counter; } - - - - - - - - template vertex_idx_t Sarkar::someParentsContraction(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { using VertexType = vertex_idx_t; @@ -977,17 +937,6 @@ vertex_idx_t Sarkar::someParentsContraction return counter; } - - - - - - - - - - - template vertex_idx_t Sarkar::levelContraction(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { using VertexType = vertex_idx_t; @@ -1082,10 +1031,6 @@ vertex_idx_t Sarkar::levelContraction(v_wor } } - - - - } std::vector partitionedFlag(graph.num_vertices(), false); @@ -1224,138 +1169,32 @@ vertex_idx_t Sarkar::homogeneous_buffer_mer const std::vector< v_workw_t > topDist = getTopDistance(commCost, graph); const std::vector< v_workw_t > botDist = getBotDistance(commCost, graph); - std::vector hashValues = computeNodeHashes(graph, vertexTopPoset, topDist); - std::vector hashValuesWithParents = hashValues; - for (const VertexType &par : graph.vertices()) { - for (const VertexType &chld : graph.children(par)) { - hash_combine(hashValuesWithParents[chld], hashValues[par]); - } - } - hashValues = computeNodeHashes(graph, vertexBotPoset, botDist); - std::vector hashValuesWithChildren = hashValues; - for (const VertexType &chld : graph.vertices()) { - for (const VertexType &par : graph.parents(chld)) { - hash_combine(hashValuesWithChildren[par], hashValues[chld]); - } - } - for (const VertexType &vert : graph.vertices()) { - hash_combine(hashValuesWithParents[vert], hashValuesWithChildren[vert]); - } - const std::vector &hashValuesCombined = hashValuesWithParents; - - std::unordered_map> orbits; - for (const VertexType &vert : graph.vertices()) { - if (graph.vertex_work_weight(vert) > params.smallWeightThreshold) continue; - - const std::size_t hash = hashValuesCombined[vert]; - auto found_iter = orbits.find(hash); - if (found_iter == orbits.end()) { - orbits.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(std::initializer_list< vertex_idx_t >{vert})); - } else { - found_iter->second.emplace(vert); - } - } - - vertex_idx_t counter = 0; - std::vector partitionedFlag(graph.num_vertices(), false); - - for (const VertexType &vert : graph.vertices()) { - if (graph.vertex_work_weight(vert) > params.smallWeightThreshold) continue; - if (partitionedFlag[vert]) continue; - - const std::set &orb = orbits.at(hashValuesCombined[vert]); - if (orb.size() <= 1U) continue; + std::vector hashValuesCombined(graph.num_vertices(), 1729U); - std::set parents; - for (const VertexType &par : graph.parents(vert)) { - parents.emplace(par); + if (params.mode == SarkarParams::Mode::FAN_OUT_BUFFER || params.mode == SarkarParams::Mode::HOMOGENEOUS_BUFFER) { + const std::vector hashValues = computeNodeHashes(graph, vertexTopPoset, topDist); + std::vector hashValuesWithParents = hashValues; + for (const VertexType &par : graph.vertices()) { + for (const VertexType &chld : graph.children(par)) { + hash_combine(hashValuesWithParents[chld], hashValues[par]); + } } - std::set children; - for (const VertexType &chld : graph.children(vert)) { - children.emplace(chld); + for (const VertexType &vert : graph.vertices()) { + hash_combine(hashValuesCombined[vert], hashValuesWithParents[vert]); } - - std::set secureOrb; - for (const VertexType &vertCandidate : orb) { - if (vertexTopPoset[vertCandidate] != vertexTopPoset[vert]) continue; - if (vertexBotPoset[vertCandidate] != vertexBotPoset[vert]) continue; - if (graph.vertex_work_weight(vertCandidate) != graph.vertex_work_weight(vert)) continue; - if (topDist[vertCandidate] != topDist[vert]) continue; - if (botDist[vertCandidate] != botDist[vert]) continue; - if constexpr (has_typed_vertices_v) { - if (graph.vertex_type(vertCandidate) != graph.vertex_type(vert)) continue; - } - - std::set candidateParents; - for (const VertexType &par : graph.parents(vertCandidate)) { - candidateParents.emplace(par); - } - if (candidateParents != parents) continue; - - std::set candidateChildren; - for (const VertexType &chld : graph.children(vertCandidate)) { - candidateChildren.emplace(chld); - } - if (candidateChildren != children) continue; - - secureOrb.emplace(vertCandidate); + } + if (params.mode == SarkarParams::Mode::FAN_IN_BUFFER || params.mode == SarkarParams::Mode::HOMOGENEOUS_BUFFER) { + const std::vector hashValues = computeNodeHashes(graph, vertexBotPoset, botDist); + std::vector hashValuesWithChildren = hashValues; + for (const VertexType &chld : graph.vertices()) { + for (const VertexType &par : graph.parents(chld)) { + hash_combine(hashValuesWithChildren[par], hashValues[chld]); + } } - if (secureOrb.size() <= 1U) continue; - - const v_workw_t desiredVerticesInGroup = graph.vertex_work_weight(vert) == 0 ? std::numeric_limits>::lowest() : params.smallWeightThreshold / graph.vertex_work_weight(vert); - const v_workw_t maxVerticesInGroup = graph.vertex_work_weight(vert) == 0 ? std::numeric_limits>::max() : params.maxWeight / graph.vertex_work_weight(vert); - - const std::size_t minDesiredSize = desiredVerticesInGroup < 2 ? 2U : static_cast(desiredVerticesInGroup); - const std::size_t maxDesiredSize = std::max(minDesiredSize, std::min(minDesiredSize * 2U, static_cast(maxVerticesInGroup))); - - std::vector groups = homogeneousMerge(secureOrb.size(), minDesiredSize, maxDesiredSize); - - auto secureOrbIter = secureOrb.begin(); - for (std::size_t groupSize : groups) { - std::vector cluster; - for (std::size_t i = 0; i < groupSize; ++i) { - cluster.emplace_back(*secureOrbIter); - ++secureOrbIter; - } - expansionMapOutput.emplace_back( std::move(cluster) ); - counter += static_cast(groupSize) - 1; + for (const VertexType &vert : graph.vertices()) { + hash_combine(hashValuesCombined[vert], hashValuesWithChildren[vert]); } - - for (const VertexType &touchedVertex : secureOrb) { - partitionedFlag[touchedVertex] = true; - } - } - - for (const VertexType &vert : graph.vertices()) { - if (partitionedFlag[vert]) continue; - expansionMapOutput.emplace_back(std::initializer_list{vert}); - } - - return counter; -} - - - - -template -vertex_idx_t Sarkar::out_buffer_merge(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { - using VertexType = vertex_idx_t; - assert(expansionMapOutput.size() == 0); - - const std::vector< vertex_idx_t > vertexTopPoset = get_top_node_distance>(graph); - const std::vector< vertex_idx_t > vertexBotPoset = getBotPosetMap(graph); - const std::vector< v_workw_t > topDist = getTopDistance(commCost, graph); - const std::vector< v_workw_t > botDist = getBotDistance(commCost, graph); - - std::vector hashValues = computeNodeHashes(graph, vertexTopPoset, topDist); - std::vector hashValuesWithParents = hashValues; - for (const VertexType &par : graph.vertices()) { - for (const VertexType &chld : graph.children(par)) { - hash_combine(hashValuesWithParents[chld], hashValues[par]); - } } - - const std::vector &hashValuesCombined = hashValuesWithParents; std::unordered_map> orbits; for (const VertexType &vert : graph.vertices()) { @@ -1381,113 +1220,17 @@ vertex_idx_t Sarkar::out_buffer_merge(v_wor if (orb.size() <= 1U) continue; std::set parents; - for (const VertexType &par : graph.parents(vert)) { - parents.emplace(par); - } - - std::set secureOrb; - for (const VertexType &vertCandidate : orb) { - if (vertexTopPoset[vertCandidate] != vertexTopPoset[vert]) continue; - if (vertexBotPoset[vertCandidate] != vertexBotPoset[vert]) continue; - if (graph.vertex_work_weight(vertCandidate) != graph.vertex_work_weight(vert)) continue; - if (topDist[vertCandidate] != topDist[vert]) continue; - if (botDist[vertCandidate] != botDist[vert]) continue; - if constexpr (has_typed_vertices_v) { - if (graph.vertex_type(vertCandidate) != graph.vertex_type(vert)) continue; + if (params.mode == SarkarParams::Mode::FAN_OUT_BUFFER || params.mode == SarkarParams::Mode::HOMOGENEOUS_BUFFER) { + for (const VertexType &par : graph.parents(vert)) { + parents.emplace(par); } - - std::set candidateParents; - for (const VertexType &par : graph.parents(vertCandidate)) { - candidateParents.emplace(par); - } - if (candidateParents != parents) continue; - - secureOrb.emplace(vertCandidate); } - if (secureOrb.size() <= 1U) continue; - - const v_workw_t desiredVerticesInGroup = graph.vertex_work_weight(vert) == 0 ? std::numeric_limits>::lowest() : params.smallWeightThreshold / graph.vertex_work_weight(vert); - const v_workw_t maxVerticesInGroup = graph.vertex_work_weight(vert) == 0 ? std::numeric_limits>::max() : params.maxWeight / graph.vertex_work_weight(vert); - - const std::size_t minDesiredSize = desiredVerticesInGroup < 2 ? 2U : static_cast(desiredVerticesInGroup); - const std::size_t maxDesiredSize = std::max(minDesiredSize, std::min(minDesiredSize * 2U, static_cast(maxVerticesInGroup))); - - // TODO: do this smarter depending on the connectivity of the children - std::vector groups = homogeneousMerge(secureOrb.size(), minDesiredSize, maxDesiredSize); - - auto secureOrbIter = secureOrb.begin(); - for (std::size_t groupSize : groups) { - std::vector cluster; - for (std::size_t i = 0; i < groupSize; ++i) { - cluster.emplace_back(*secureOrbIter); - ++secureOrbIter; - } - expansionMapOutput.emplace_back( std::move(cluster) ); - counter += static_cast(groupSize) - 1; - } - - for (const VertexType &touchedVertex : secureOrb) { - partitionedFlag[touchedVertex] = true; - } - } - - for (const VertexType &vert : graph.vertices()) { - if (partitionedFlag[vert]) continue; - expansionMapOutput.emplace_back(std::initializer_list{vert}); - } - - return counter; -} - - - - - -template -vertex_idx_t Sarkar::in_buffer_merge(v_workw_t commCost, const Graph_t_in &graph, std::vector>> &expansionMapOutput) const { - using VertexType = vertex_idx_t; - assert(expansionMapOutput.size() == 0); - - const std::vector< vertex_idx_t > vertexTopPoset = get_top_node_distance>(graph); - const std::vector< vertex_idx_t > vertexBotPoset = getBotPosetMap(graph); - const std::vector< v_workw_t > topDist = getTopDistance(commCost, graph); - const std::vector< v_workw_t > botDist = getBotDistance(commCost, graph); - - std::vector hashValues = computeNodeHashes(graph, vertexBotPoset, botDist); - std::vector hashValuesWithChildren = hashValues; - for (const VertexType &chld : graph.vertices()) { - for (const VertexType &par : graph.parents(chld)) { - hash_combine(hashValuesWithChildren[par], hashValues[chld]); - } - } - const std::vector &hashValuesCombined = hashValuesWithChildren; - - std::unordered_map> orbits; - for (const VertexType &vert : graph.vertices()) { - if (graph.vertex_work_weight(vert) > params.smallWeightThreshold) continue; - - const std::size_t hash = hashValuesCombined[vert]; - auto found_iter = orbits.find(hash); - if (found_iter == orbits.end()) { - orbits.emplace(std::piecewise_construct, std::forward_as_tuple(hash), std::forward_as_tuple(std::initializer_list< vertex_idx_t >{vert})); - } else { - found_iter->second.emplace(vert); - } - } - - vertex_idx_t counter = 0; - std::vector partitionedFlag(graph.num_vertices(), false); - - for (const VertexType &vert : graph.vertices()) { - if (graph.vertex_work_weight(vert) > params.smallWeightThreshold) continue; - if (partitionedFlag[vert]) continue; - - const std::set &orb = orbits.at(hashValuesCombined[vert]); - if (orb.size() <= 1U) continue; std::set children; - for (const VertexType &chld : graph.children(vert)) { - children.emplace(chld); + if (params.mode == SarkarParams::Mode::FAN_IN_BUFFER || params.mode == SarkarParams::Mode::HOMOGENEOUS_BUFFER) { + for (const VertexType &chld : graph.children(vert)) { + children.emplace(chld); + } } std::set secureOrb; @@ -1501,11 +1244,21 @@ vertex_idx_t Sarkar::in_buffer_merge(v_work if (graph.vertex_type(vertCandidate) != graph.vertex_type(vert)) continue; } - std::set candidateChildren; - for (const VertexType &chld : graph.children(vertCandidate)) { - candidateChildren.emplace(chld); + if (params.mode == SarkarParams::Mode::FAN_OUT_BUFFER || params.mode == SarkarParams::Mode::HOMOGENEOUS_BUFFER) { + std::set candidateParents; + for (const VertexType &par : graph.parents(vertCandidate)) { + candidateParents.emplace(par); + } + if (candidateParents != parents) continue; + } + + if (params.mode == SarkarParams::Mode::FAN_IN_BUFFER || params.mode == SarkarParams::Mode::HOMOGENEOUS_BUFFER) { + std::set candidateChildren; + for (const VertexType &chld : graph.children(vertCandidate)) { + candidateChildren.emplace(chld); + } + if (candidateChildren != children) continue; } - if (candidateChildren != children) continue; secureOrb.emplace(vertCandidate); } @@ -1517,7 +1270,6 @@ vertex_idx_t Sarkar::in_buffer_merge(v_work const std::size_t minDesiredSize = desiredVerticesInGroup < 2 ? 2U : static_cast(desiredVerticesInGroup); const std::size_t maxDesiredSize = std::max(minDesiredSize, std::min(minDesiredSize * 2U, static_cast(maxVerticesInGroup))); - // TODO: do this smarter depending on the connectivity of the parents std::vector groups = homogeneousMerge(secureOrb.size(), minDesiredSize, maxDesiredSize); auto secureOrbIter = secureOrb.begin();