#include "leak_detector.h" #include #include #include #include #include #include #include #include #include #include #include #if _WIN32 && NDEBUG && __BOOST #include #endif extern int passDone; using std::pair; using std::set; using std::make_pair; using std::string; using std::wstring; using std::tuple; using std::vector; using namespace std::chrono; #include "GraphCSR.h" #include "Arrays.h" #include "Array.h" #include "Distribution.h" #include "utils.h" #include "errors.h" #include "types.h" #include "../Distribution/Cycle.h" #include "../VisualizerCalls/get_information.h" #include "../VisualizerCalls/SendMessage.h" extern int keepFiles; #define ERROR_CHECK(err) do { if (err != 0) return err; } while(0) #define FIRST(x) get<0>(x) #define SECOND(x) get<1>(x) #define THIRD(x) get<2>(x) namespace Distribution { //fix attributes: pair< pair, pair > template attrType shiftByDiffInArc(const attrType& arcAttr) { pair left = arcAttr.first; pair right = arcAttr.second; if (left.first == right.first) { if (left.second == right.second) left.second = right.second = 0; else if (left.second != 0 && right.second != 0) { const int diffZeroL = abs(left.second - 0); const int diffZeroR = abs(right.second - 0); if (diffZeroL < diffZeroR) { if (left.second > 0) { left.second -= diffZeroL; right.second -= diffZeroL; } else { left.second += diffZeroL; right.second += diffZeroL; } } else { if (right.second > 0) { left.second -= diffZeroR; right.second -= diffZeroR; } else { left.second += diffZeroR; right.second += diffZeroR; } } } } return make_pair(left, right); } template attrType inverseArcByShifts(const attrType& arcAttr) { pair left = arcAttr.first; pair right = arcAttr.second; if (left.first == right.first) { if (left.second < 0 && right.second < 0) ; else if (left.second < 0) { std::swap(left.second, right.second); right.second = -right.second; } else if (right.second < 0) { std::swap(left.second, right.second); left.second = -left.second; } } return make_pair(left, right); } template int AddArrayAccess(GraphCSR &G, Arrays &allArrays, Array *arr1, Array *arr2, pair arc, wType arcWeight, const attrType &arcAttr, const uint8_t linkType) { int err = 0; allArrays.AddArrayToGraph(arr1); allArrays.AddArrayToGraph(arr2); vType V1, V2; ERROR_CHECK(allArrays.GetVertNumber(arr1, arc.first, V1)); ERROR_CHECK(allArrays.GetVertNumber(arr2, arc.second, V2)); G.AddToGraph(V1, V2, arcWeight, shiftByDiffInArc(arcAttr), linkType); return err; } template static int GetIdxOfNextCycle(const vector> &localDelArcs, const vector> &cycles, const vector> &indexOfConflict, const int idxStart = 0) { int idx = -1; for (int i = idxStart; i < (int)indexOfConflict.size(); ++i) { const Cycle &currCycle = cycles[indexOfConflict[i].first]; if (localDelArcs.size() == 0) { idx = i; break; } else { const vector> &arcs = currCycle.GetArcs(); const vector &attributes = currCycle.GetAttributesArcs(); bool same = false; for (int k = 0; k < (int)arcs.size(); ++k) { const tuple toCheck = make_tuple(arcs[k].first, arcs[k].second, attributes[k]); const tuple toCheckRev = make_tuple(arcs[k].second, arcs[k].first, make_pair(attributes[k].second, attributes[k].first)); same = false; for (int m = 0; m < (int)localDelArcs.size(); ++m) { if (toCheck == localDelArcs[m] || toCheckRev == localDelArcs[m]) { same = true; break; } } if (same) break; } if (same) continue; else { idx = i; break; } } } return idx; } template static int GetIdxOfNextCycle(const unsigned *fastCache, const vector &localDelArcsShort, const vector> &cycles, const vector> &indexOfConflict, const int idxStart = 0) { int idx = -1; const pair *data = indexOfConflict.data(); for (int i = idxStart; i < (int)indexOfConflict.size(); ++i) { const Cycle &currCycle = cycles[data[i].first]; if (localDelArcsShort.size() == 0) { idx = i; break; } else { const vector &shortInfo = currCycle.GetShortInfo(); bool same = false; for (int k = 0; k < (int)shortInfo.size(); ++k) { if (fastCache[shortInfo[k]] == 1) { same = true; break; } } if (same) continue; else { idx = i; break; } } } return idx; } static inline bool checkGraphTrue(const int startV, const int realV, const GraphCSR &G) { return true; } static inline bool checkGraph(const int startV, const int realV, const GraphCSR &G) { return realV == G.CountOfConnected(startV); } template &G)> static void FindBestSequenceForDelArcs(double &globalSum, vector> &globalDelArcs, const double localSum, vector> &localDelArcs, vector &localDelArcsShort, unsigned *fastCache, const vector> &cycles, const vector> &indexOfConflict, const int lastIndexOfConflict, const int countInTree, const GraphCSR &graph) { int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1); if (nextConflict == -1) { globalSum = localSum; globalDelArcs = localDelArcs; //char buf[256]; //sprintf(buf, " global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict); printf("SAPFOR: global sum = %f, last idx of conflict %d\n", globalSum, lastIndexOfConflict); //addToGlobalBufferAndPrint(buf); createNeededException(); } else { const Cycle &conflicCycle = cycles[indexOfConflict[nextConflict].first]; const vector> &arcs = conflicCycle.GetArcs(); const vector &shortInfo = conflicCycle.GetShortInfo(); const vector &weights = conflicCycle.GetWeigthsArcs(); const vector &attributes = conflicCycle.GetAttributesArcs(); for (int i = 0; i < (int)arcs.size(); ++i) { const pair &currArc = arcs[i]; const wType currW = weights[i]; const attrType &currAttr = attributes[i]; if (!check(currArc.first, countInTree, graph)) continue; else { if (localSum + currW < globalSum) { localDelArcs.push_back(make_tuple(currArc.first, currArc.second, currAttr)); localDelArcsShort.push_back(shortInfo[i]); fastCache[shortInfo[i]] = 1; FindBestSequenceForDelArcs (globalSum, globalDelArcs, localSum + currW, localDelArcs, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict, countInTree, graph); fastCache[shortInfo[i]] = 0; localDelArcs.pop_back(); localDelArcsShort.pop_back(); } else { createNeededException(); break; } } } } } template static void CountConflictVarints(int64_t &countVars, vector &localDelArcsShort, unsigned *fastCache, const vector> &cycles, const vector> &indexOfConflict, const int lastIndexOfConflict) { int nextConflict = GetIdxOfNextCycle(fastCache, localDelArcsShort, cycles, indexOfConflict, lastIndexOfConflict + 1); if (nextConflict == -1) { countVars++; return; } else { const Cycle &conflicCycle = cycles[indexOfConflict[nextConflict].first]; const vector &shortInfo = conflicCycle.GetShortInfo(); for (int i = 0; i < (int)shortInfo.size(); ++i) { localDelArcsShort.push_back(shortInfo[i]); fastCache[shortInfo[i]] = 1; CountConflictVarints(countVars, localDelArcsShort, fastCache, cycles, indexOfConflict, nextConflict); fastCache[shortInfo[i]] = 0; localDelArcsShort.pop_back(); } } } #define DEGUB_DEL_ALL_CYCLES 0 template static void FindNonConflictDelArcs(vector> &delArcs, const vector> &cycles) { vector> idxOfLoops(cycles.size()); // fill indexs for all lopps for using 'GetIdxOfNextCycle' procedure for (int i = 0; i < (int)cycles.size(); ++i) #if !DEGUB_DEL_ALL_CYCLES idxOfLoops[i] = std::make_pair(i, 0); #else { const std::vector> &arcs = cycles[i].GetArcs(); const std::vector &attrs = cycles[i].GetAttributesArcs(); for (int i = 0; i < arcs.size(); ++i) delArcs.push_back(std::make_tuple(arcs[i].first, arcs[i].second, attrs[i])); } #endif #if !DEGUB_DEL_ALL_CYCLES int idxNext = -1; do { idxNext = GetIdxOfNextCycle(delArcs, cycles, idxOfLoops, idxNext + 1); if (idxNext != -1) { std::pair arc = cycles[idxNext].GetArcs()[0]; attrType attr = cycles[idxNext].GetAttributesArcs()[0]; delArcs.push_back(std::make_tuple(arc.first, arc.second, attr)); } } while (idxNext != -1); #endif } #undef DEGUB_DEL_ALL_CYCLES template static pair CreateOptimalAlignementTree(GraphCSR &G, const Arrays &allArrays, vector> &toDelArcs, bool needPrint = true, bool useSavedQ = false) { double globalSum = 0; bool allOnlySecondType = true; vector trees; vector> vertByTrees; set unqieTrees = G.FindTrees(trees, vertByTrees); __spf_print(needPrint, " GRAPH size: |V| = %d, |E| = %d\n", G.GetNumberOfV(), G.GetNumberOfE() / 2); __spf_print(needPrint, " TREES count %d\n", (int)unqieTrees.size()); vector tmp; for (int z = 0; z < vertByTrees.size(); ++z) if (vertByTrees[z].size()) __spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, (int)vertByTrees[z].size(), G.MakeConnected(vertByTrees[z][0], tmp).second); else __spf_print(needPrint, " TREES %d: V = %d, E = %d\n", z, 0, 0); toDelArcs = G.CreateMaximumSpanningTree(); return make_pair(allOnlySecondType, globalSum); // OLD ALGORITHM, THIS IS unreachable code !! vector>> AllCycles; G.GetAllSimpleLoops(AllCycles, needPrint, useSavedQ); toDelArcs.clear(); for (int k = 0; k < AllCycles.size(); ++k) { unsigned maxElem = 0; bool onlySecondConflictType = true; for (auto &elem : AllCycles[k]) for (auto &cycleShortInfo : elem.GetShortInfo()) maxElem = std::max(maxElem, cycleShortInfo); if (maxElem != 0 && needPrint) printf(" SAPFOR: max elem for cache %lld, in MB: %f\n", maxElem, maxElem / 1024. / 1024. * sizeof(unsigned)); unsigned *fastCache = new unsigned[maxElem]; memset(fastCache, 0, sizeof(unsigned) * maxElem); char buf[256]; if (needPrint) { sprintf(buf, " PROF: [%d TREE]:\n", k); addToGlobalBufferAndPrint(buf); } double globalSumLocal = (double)INT32_MAX; vector> indexOfConflict; vector> &cycles = AllCycles[k]; vector> localDelArcs; vector localDelArcShort; G.SortLoopsBySize(cycles, needPrint); G.SortLoopsByWeight(cycles, needPrint); for (int i = 0; i < (int)cycles.size(); ++i) cycles[i].SortArcs(); int countConflicts = G.GetConflictCycles(cycles, allArrays, indexOfConflict, needPrint); if (needPrint) { sprintf(buf, " num of conflict cycles %d\n", countConflicts); printf("SAPFOR: num of conflict cycles %d\n", countConflicts); addToGlobalBufferAndPrint(buf); } if (countConflicts != 0) { int typeConflict[2] = { 0, 0 }; for (int i = 0; i < indexOfConflict.size(); ++i) typeConflict[indexOfConflict[i].second]++; if (needPrint) { sprintf(buf, " num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]); printf("SAPFOR: num of type1 = %d, type2 = %d\n", typeConflict[0], typeConflict[1]); addToGlobalBufferAndPrint(buf); } if (typeConflict[0]) { onlySecondConflictType = false; allOnlySecondType = false; } } if (needPrint) sendMessage_2lvl(4, k, (int)AllCycles.size()); auto timeR = steady_clock::now(); if (countConflicts != 0) { const int countInTree = G.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first); const int lastIndexOfConflict = -1; if (needPrint) printf("SAPFOR: before del %d\n", countInTree); /*int64_t countVars = 0; CountConflictVarints(countVars, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict); printf("SAPFOR: count of vars %lld\n", countVars);*/ if (onlySecondConflictType) FindBestSequenceForDelArcs (globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G); else FindBestSequenceForDelArcs (globalSumLocal, toDelArcs, 0, localDelArcs, localDelArcShort, fastCache, cycles, indexOfConflict, lastIndexOfConflict, countInTree, G); if (needPrint) { auto tmpReducedG = G; tmpReducedG.RemovedEdges(toDelArcs, allArrays); if (needPrint) printf("SAPFOR: after del %d\n", tmpReducedG.CountOfConnected(cycles[indexOfConflict[0].first].GetArcs()[0].first)); } globalSum += globalSumLocal; } if (needPrint) { sprintf(buf, "PROF: FindBestSequenceForDelArcs: %f sec\n", (duration_cast>(steady_clock::now() - timeR)).count()); printf("SAPFOR: time of FindBestSequenceForDelArcs %f sec\n", (duration_cast>(steady_clock::now() - timeR)).count()); addToGlobalBufferAndPrint(buf); } timeR = steady_clock::now(); FindNonConflictDelArcs(toDelArcs, cycles); if (needPrint) { sprintf(buf, "PROF: FindNonConflictDelArcs %f\n", (duration_cast>(steady_clock::now() - timeR)).count()); addToGlobalBufferAndPrint(buf); } delete []fastCache; } if (needPrint) sendMessage_2lvl(2); return make_pair(allOnlySecondType, globalSum); } template void createOptimalDistribution(GraphCSR &G, GraphCSR &reducedG, const Arrays &allArrays, const uint64_t regionNum, bool onlyGraph) { vector> toDelArcs; if (G.GetNumberOfE() == 0) return; double globalSum = 0; string FullName = "_graph_full_reg" + std::to_string(regionNum) + ".txt"; string ReducedName = "_graph_reduced_reg" + std::to_string(regionNum) + ".txt"; //__spf_print(1, "flag keepFiles %d, flag onlyGraph %d\n", keepFiles, onlyGraph); if (keepFiles) { if (!onlyGraph) G.CreateGraphWiz(FullName.c_str(), toDelArcs, allArrays, false); else G.CreateGraphWiz(FullName.c_str(), vector>(), allArrays, true); } if (!onlyGraph) { G.HighlightLinks(); //old simple algorithm //G.RemoveMultipleArcsByWeights(); //new algorithm with optimal strategy G.RemoveMultipleArcsOptimal(); pair retVal = CreateOptimalAlignementTree(G, allArrays, toDelArcs); globalSum = retVal.second; bool onlySecondType = retVal.first; reducedG = G; reducedG.RemovedEdges(toDelArcs, allArrays); double maxWeight = reducedG.CalculateSumOfWeights() + 1; //try to resolve conflicts of 1 type const set &arrays = allArrays.GetArrays(); vector arraysV; arraysV.assign(arrays.begin(), arrays.end()); for (int z = 0; z < arraysV.size(); ++z) { const DIST::Array *array = arraysV[z]; sendMessage_2lvl(5, z, (int)arrays.size()); vector verts; if (array->GetDimSize() == 1) continue; int err = allArrays.GetAllVertNumber(array, verts); if (err != 0) printInternalError(convertFileName(__FILE__).c_str(), __LINE__); attrType tmpPair = make_pair(make_pair(1, 0), make_pair(1, 0)); for (int i = 0; i < verts.size(); ++i) { for (int j = i + 1; j < verts.size(); ++j) { GraphCSR findConflict(reducedG); findConflict.AddToGraph(verts[i], verts[j], maxWeight, tmpPair, WW_link); vector> toDelArcsLocal; globalSum = CreateOptimalAlignementTree(findConflict, allArrays, toDelArcsLocal, false, true).second; if (toDelArcsLocal.size() != 0) reducedG.RemovedEdges(toDelArcsLocal, allArrays); } } } sendMessage_2lvl(2); } else { reducedG = G; reducedG.RemoveMultipleArcsByWeights(); } if (keepFiles) reducedG.CreateGraphWiz(ReducedName.c_str(), vector>(), allArrays, true); } template void createOptimalDistribution(GraphCSR &G, GraphCSR &reducedG, const Arrays &allArrays, const uint64_t regionNum, bool onlyGraph); template int AddArrayAccess(GraphCSR &G, Arrays &allArrays, Array *arr1, Array *arr2, pair arc, double arcWeight, const attrType &arcAttr, const uint8_t linkType); template attrType shiftByDiffInArc(const attrType& arcAttr); template attrType inverseArcByShifts(const attrType& arcAttr); } #undef ERROR_CHECK #undef FIRST #undef SECOND #undef THIRD