|
| 1 | +// *********************************************************************** |
| 2 | +// |
| 3 | +// Jet: Multilevel Graph Partitioning |
| 4 | +// |
| 5 | +// Copyright 2023 National Technology & Engineering Solutions of Sandia, LLC |
| 6 | +// (NTESS). |
| 7 | +// |
| 8 | +// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, |
| 9 | +// the U.S. Government retains certain rights in this software. |
| 10 | +// |
| 11 | +// Redistribution and use in source and binary forms, with or without |
| 12 | +// modification, are permitted provided that the following conditions are |
| 13 | +// met: |
| 14 | +// |
| 15 | +// 1. Redistributions of source code must retain the above copyright |
| 16 | +// notice, this list of conditions and the following disclaimer. |
| 17 | +// |
| 18 | +// 2. Redistributions in binary form must reproduce the above copyright |
| 19 | +// notice, this list of conditions and the following disclaimer in the |
| 20 | +// documentation and/or other materials provided with the distribution. |
| 21 | +// |
| 22 | +// 3. Neither the name of the Corporation nor the names of the |
| 23 | +// contributors may be used to endorse or promote products derived from |
| 24 | +// this software without specific prior written permission. |
| 25 | +// |
| 26 | +// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY |
| 27 | +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 28 | +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| 29 | +// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE |
| 30 | +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| 31 | +// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| 32 | +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| 33 | +// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| 34 | +// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 35 | +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 36 | +// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 37 | +// |
| 38 | +// ************************************************************************ |
| 39 | +#pragma once |
| 40 | +#include <vector> |
| 41 | +#include <stdlib.h> |
| 42 | +#include <iostream> |
| 43 | +#include <fstream> |
| 44 | +#include <string> |
| 45 | +#include <map> |
| 46 | + |
| 47 | +namespace jet_partitioner { |
| 48 | + |
| 49 | +enum class Measurement : int { |
| 50 | + Map, |
| 51 | + Build, |
| 52 | + Count, |
| 53 | + Prefix, |
| 54 | + Bucket, |
| 55 | + Dedupe, |
| 56 | + RadixSort, |
| 57 | + RadixDedupe, |
| 58 | + WriteGraph, |
| 59 | + Permute, |
| 60 | + MapConstruct, |
| 61 | + Heavy, |
| 62 | + InitTransfer, |
| 63 | + HashmapAllocate, |
| 64 | + HashmapInsert, |
| 65 | + InitPartition, |
| 66 | + Coarsen, |
| 67 | + Refine, |
| 68 | + FreeGraph, |
| 69 | + Total, |
| 70 | + END |
| 71 | +}; |
| 72 | + |
| 73 | +template <typename scalar_t> |
| 74 | +class ExperimentLoggerUtil { |
| 75 | + |
| 76 | +public: |
| 77 | + std::vector<std::string> measurementNames{ |
| 78 | + "coarsen-map", |
| 79 | + "coarsen-build", |
| 80 | + "coarsen-count", |
| 81 | + "coarsen-prefix-sum", |
| 82 | + "coarsen-bucket", |
| 83 | + "coarsen-dedupe", |
| 84 | + "coarsen-radix-sort", |
| 85 | + "coarsen-radix-dedupe", |
| 86 | + "coarsen-write-graph", |
| 87 | + "coarsen-permute", |
| 88 | + "coarsen-map-construct", |
| 89 | + "heavy", |
| 90 | + "initial-transfer-to-device", |
| 91 | + "hashmap-allocate", |
| 92 | + "hashmap-insert", |
| 93 | + "initial-partition", |
| 94 | + "coarsen", |
| 95 | + "refine", |
| 96 | + "free-graph", |
| 97 | + "total", |
| 98 | + }; |
| 99 | + std::vector<double> measurements; |
| 100 | + |
| 101 | + class CoarseLevel { |
| 102 | + public: |
| 103 | + int64_t edge_cut = 0; |
| 104 | + double imb = 0; |
| 105 | + uint64_t numEdges = 0; |
| 106 | + uint64_t numVertices = 0; |
| 107 | + double totalRefTime = 0; |
| 108 | + double iterationsTime = 0; |
| 109 | + int totalIterations = 0; |
| 110 | + int lpIterations = 0; |
| 111 | + |
| 112 | + CoarseLevel(int64_t _edge_cut, double _imb, uint64_t _numEdges, uint64_t _numVertices, double _totalRefTime, double _iterationsTime, int _totalIterations, int _lpIterations) : |
| 113 | + edge_cut(_edge_cut), |
| 114 | + imb(_imb), |
| 115 | + numEdges(_numEdges), |
| 116 | + numVertices(_numVertices), |
| 117 | + totalRefTime(_totalRefTime), |
| 118 | + iterationsTime(_iterationsTime), |
| 119 | + totalIterations(_totalIterations), |
| 120 | + lpIterations(_lpIterations) {} |
| 121 | + |
| 122 | + }; |
| 123 | + |
| 124 | +private: |
| 125 | + int numCoarseLevels = 0; |
| 126 | + std::vector<CoarseLevel> coarseLevels; |
| 127 | + double imb_ratio = 0; |
| 128 | + scalar_t fine_ec = 0; |
| 129 | + scalar_t max_part_cut = 0; |
| 130 | + scalar_t largest_part = 0; |
| 131 | + scalar_t smallest_part = 0; |
| 132 | + int64_t obj = 0; |
| 133 | + |
| 134 | +public: |
| 135 | + ExperimentLoggerUtil() : |
| 136 | + measurements(static_cast<int>(Measurement::END), 0.0) |
| 137 | + {} |
| 138 | + |
| 139 | + void addCoarseLevel(CoarseLevel cl) { |
| 140 | + coarseLevels.push_back(cl); |
| 141 | + numCoarseLevels++; |
| 142 | + } |
| 143 | + |
| 144 | + void setFinestEdgeCut(scalar_t finestEdgeCut) { |
| 145 | + this->fine_ec = finestEdgeCut; |
| 146 | + } |
| 147 | + |
| 148 | + void setMaxPartCut(scalar_t x){ |
| 149 | + this->max_part_cut = x; |
| 150 | + } |
| 151 | + |
| 152 | + void setFinestImbRatio(double _imb_ratio) { |
| 153 | + this->imb_ratio = _imb_ratio; |
| 154 | + } |
| 155 | + |
| 156 | + void setObjective(int64_t x){ |
| 157 | + this->obj = x; |
| 158 | + } |
| 159 | + |
| 160 | + void setLargestPartSize(scalar_t x){ |
| 161 | + this->largest_part = x; |
| 162 | + } |
| 163 | + |
| 164 | + void setSmallestPartSize(scalar_t x){ |
| 165 | + this->smallest_part = x; |
| 166 | + } |
| 167 | + |
| 168 | + void addMeasurement(Measurement m, double val) { |
| 169 | + measurements[static_cast<int>(m)] += val; |
| 170 | + } |
| 171 | + |
| 172 | + double getMeasurement(Measurement m) { |
| 173 | + return measurements[static_cast<int>(m)]; |
| 174 | + } |
| 175 | + |
| 176 | + void log(char* filename, bool first, bool last) { |
| 177 | + std::ofstream f; |
| 178 | + f.open(filename, std::ios::app); |
| 179 | + |
| 180 | + if (f.is_open()) { |
| 181 | + if (first) { |
| 182 | + f << "["; |
| 183 | + } |
| 184 | + f << "{"; |
| 185 | + f << "\"edge-cut\":" << std::fixed << fine_ec << ","; |
| 186 | + f << "\"max-part-cut\":" << max_part_cut << ","; |
| 187 | + f << "\"objective\":" << obj << ","; |
| 188 | + f << "\"imbalance-ratio\":" << imb_ratio << ','; |
| 189 | + for (int i = 0; i < static_cast<int>(Measurement::END); i++) { |
| 190 | + f << "\"" << measurementNames[i] << "-duration-seconds\":" << measurements[i] << ","; |
| 191 | + } |
| 192 | + f << "\"number-coarse-levels\":" << numCoarseLevels << ","; |
| 193 | + f << "\"finest-refinement-duration-seconds\":" << coarseLevels.back().totalRefTime; |
| 194 | + f << "}"; |
| 195 | + if (!last) { |
| 196 | + f << ","; |
| 197 | + } |
| 198 | + else { |
| 199 | + f << "]"; |
| 200 | + } |
| 201 | + f.close(); |
| 202 | + } |
| 203 | + else { |
| 204 | + std::cerr << "Could not open " << filename << std::endl; |
| 205 | + } |
| 206 | + } |
| 207 | + |
| 208 | + void verboseReport(){ |
| 209 | + std::cout << "Final cut: " << std::fixed << fine_ec; |
| 210 | + std::cout << "; Max part cut: " << std::fixed << max_part_cut; |
| 211 | + std::cout << "; imb: " << imb_ratio; |
| 212 | + std::cout << "; largest: " << largest_part << "; smallest: " << smallest_part << std::endl; |
| 213 | + std::cout << std::setprecision(5); |
| 214 | + std::cout << "Coarsening time: " << getMeasurement(Measurement::Coarsen) << std::endl; |
| 215 | + std::cout << " - Coarsening aggregation time: " << getMeasurement(Measurement::Map) << std::endl; |
| 216 | + std::cout << " - Coarsening contraction time: " << getMeasurement(Measurement::Build) << std::endl; |
| 217 | + std::cout << "Initial partitioning time: " << getMeasurement(Measurement::InitPartition) << std::endl; |
| 218 | + std::cout << "Uncoarsening time: " << getMeasurement(Measurement::Refine) << std::endl; |
| 219 | + std::cout << "Coarse graph free time: " << getMeasurement(Measurement::FreeGraph) << std::endl; |
| 220 | + std::cout << "Total Partitioning Time: " << getMeasurement(Measurement::Total) << std::endl; |
| 221 | + std::cout << "Comm size: " << obj << std::endl; |
| 222 | + } |
| 223 | + |
| 224 | + void refinementReport(){ |
| 225 | + std::cout << std::setprecision(6); |
| 226 | + std::cout << std::left << std::setw(6) << "Level" << std::setw(16) << "Edge Cut" << std::setw(10) << "Imbalance"; |
| 227 | + std::cout << std::setw(13) << "Vertices" << std::setw(16) << "Edges" << std::setw(22) << "Total Refinement Time"; |
| 228 | + std::cout << std::setw(17) << "Total Iterations" << std::setw(14) << "LP Iterations" << std::setw(23) << "Average Iteration Time" << std::endl; |
| 229 | + for(size_t i = 0; i < coarseLevels.size(); i++){ |
| 230 | + CoarseLevel cl = coarseLevels[i]; |
| 231 | + int level = coarseLevels.size() - 1 - i; |
| 232 | + std::cout << std::fixed << std::left << std::setw(6) << level << std::setw(16) << cl.edge_cut << std::setw(10) << cl.imb; |
| 233 | + std::cout << std::setw(13) << cl.numVertices << std::setw(16) << cl.numEdges << std::setw(22) << cl.totalRefTime; |
| 234 | + std::cout << std::setw(17) << cl.totalIterations << std::setw(14) << cl.lpIterations << std::setw(23) << (cl.iterationsTime / cl.totalIterations) << std::endl; |
| 235 | + } |
| 236 | + } |
| 237 | +}; |
| 238 | + |
| 239 | +} |
0 commit comments