void unpackMetrics(Prof::CallPath::Profile& profile, const ParallelAnalysis::PackedMetrics& packedMetrics) { Prof::CCT::Tree& cct = *profile.cct(); // 1. unpack 'packedMetrics' into temporary derived metrics [mBegId, // mEndId) in 'profile' uint mBegId = packedMetrics.mBegId(), mEndId = packedMetrics.mEndId(); DIAG_Assert(packedMetrics.numNodes() == cct.maxDenseId() + 1, ""); DIAG_Assert(packedMetrics.numMetrics() == mEndId - mBegId, ""); for (uint nodeId = 1; nodeId < packedMetrics.numNodes(); ++nodeId) { for (uint mId1 = 0, mId2 = mBegId; mId2 < mEndId; ++mId1, ++mId2) { Prof::CCT::ANode* n = cct.findNode(nodeId); n->demandMetric(mId2) = packedMetrics.idx(nodeId, mId1); } } // 2. update derived metrics [mDrvdBeg, mDrvdEnd) based on new // values in [mBegId, mEndId) uint mDrvdBeg = packedMetrics.mDrvdBegId(); uint mDrvdEnd = packedMetrics.mDrvdEndId(); cct.root()->computeMetricsIncr(*profile.metricMgr(), mDrvdBeg, mDrvdEnd, Prof::Metric::AExprIncr::FnCombine); }
void mergeNonLocal(std::pair<Prof::CallPath::Profile*, ParallelAnalysis::PackedMetrics*> data, int rank_x, int rank_y, int myRank, MPI_Comm comm) { int tag = rank_y; // sender if (myRank == rank_x) { Prof::CallPath::Profile* profile_x = data.first; ParallelAnalysis::PackedMetrics* packedMetrics_x = data.second; // rank_x receives metric data from rank_y MPI_Status mpistat; MPI_Recv(packedMetrics_x->data(), packedMetrics_x->dataSize(), MPI_DOUBLE, rank_y, tag, comm, &mpistat); DIAG_Assert(packedMetrics_x->verify(), DIAG_UnexpectedInput); unpackMetrics(*profile_x, *packedMetrics_x); } if (myRank == rank_y) { Prof::CallPath::Profile* profile_y = data.first; ParallelAnalysis::PackedMetrics* packedMetrics_y = data.second; packMetrics(*profile_y, *packedMetrics_y); // rank_y sends metric data to rank_x MPI_Send(packedMetrics_y->data(), packedMetrics_y->dataSize(), MPI_DOUBLE, rank_x, tag, comm); } }
void broadcast(Prof::CallPath::Profile*& profile, int myRank, int maxRank, MPI_Comm comm) { if (myRank != RankTree::rootRank) { DIAG_Assert(!profile, "ParallelAnalysis::broadcast: " << DIAG_UnexpectedInput); profile = new Prof::CallPath::Profile("[ParallelAnalysis::broadcast]"); profile->isMetricMgrVirtual(true); } int max_level = RankTree::level(maxRank); for (int level = 0; level < max_level; ++level) { int i_beg = RankTree::begNode(level); int i_end = std::min(maxRank, RankTree::endNode(level)); for (int i = i_beg; i <= i_end; ++i) { // merge i into its left child (i_lchild) int i_lchild = RankTree::leftChild(i); if (i_lchild <= maxRank) { mergeNonLocal(profile, i_lchild, i, myRank); } // merge i into its right child (i_rchild) int i_rchild = RankTree::rightChild(i); if (i_rchild <= maxRank) { mergeNonLocal(profile, i_rchild, i, myRank); } } MPI_Barrier(comm); } }
LoadMap::LoadMap(uint sz) { m_lm_byId.reserve(sz); LM* nullLM = new LM(Prof::Struct::Tree::UnknownLMNm); lm_insert(nullLM); DIAG_Assert(nullLM->id() == LoadMap::LMId_NULL, "LoadMap::LoadMap"); }
// findGroup: see general comments in header. // // Currently assumes: // 1. Metric groups in both x and y appear in sorted order and without // gaps. This assumption is upheld because (a) groups are // distributed across processes in sorted order and (b) the // reduction tree always merges left before right children. // // This means we should *never* see: // x: [2.a 2.b] y: [1.a 1.b | 2.a 2.b] // x: [2.a 2.b] y: [1.a 1.b | 3.a 3.b] // // 2. All profile files in a group have the same set of metrics. // // While this simplifies things, because of groups, we still have to // merge profiles where only a subgroup of y matches a group in x. // x: [1.a 1.b] y: [1.a 1.b | 2.a 2.b] // // // *** N.B.: *** Assumptions (1) and (2) imply that either (a) y's // metrics fully match x's or (b) y's *first* metric subgroup fully // matches x's metrics. It also enables us to use a metric's unique // name for a search. // // // TODO: Eventually, we cannot assume (2). It will be possible for // a group to have different sets of metrics, which could lead to // merges like the following: // // x: [1.a 1.b] y: [1.a 1.b | 1.a 1.c] // x: [1.a 1.c] y: [1.a 1.b | 1.a 1.c] // x: [1.a 1.c] [1.d 1.e] y: [1.a 1.b | 1.a 1.c] // // This implies that *any* subgroup of y could match *any* subgroup of // x. It also implies that we cannot search by a metric's unique name // because the unique name in y may be different than the unique name // in x. // uint Mgr::findGroup(const Mgr& y) const { const Mgr* x = this; // ------------------------------------------------------- // Based on observation above, we first try to match y's first // subgroup. // ------------------------------------------------------- uint y_grp_sz = 0; // open end boundary if (y.size() > 0) { y_grp_sz = 1; // metric 0 is first entry in 'y_grp' const string& y_grp_pfx = y.metric(0)->namePfx(); for (uint y_i = 1; y_i < y.size(); ++y_i) { const string& mPfx = y.metric(y_i)->namePfx(); if (mPfx != y_grp_pfx) { break; } y_grp_sz++; } } bool found = true; // optimistic std::vector<uint> metricMap(y_grp_sz); for (uint y_i = 0; y_i < y_grp_sz; ++y_i) { const Metric::ADesc* y_m = y.metric(y_i); string mNm = y_m->name(); const Metric::ADesc* x_m = x->metric(mNm); if (!x_m || (y_i > 0 && x_m->id() != (metricMap[y_i - 1] + 1))) { found = false; break; } metricMap[y_i] = x_m->id(); } bool foundGrp = (found && !metricMap.empty()); // ------------------------------------------------------- // // ------------------------------------------------------- if (foundGrp) { // sanity check: either (x.size() == y_grp_sz) or the rest of x // matches the rest of y. for (uint x_i = metricMap[y_grp_sz - 1] + 1, y_i = y_grp_sz; x_i < x->size() && y_i < y.size(); ++x_i, ++y_i) { DIAG_Assert(x->metric(x_i)->name() == y.metric(y_i)->name(), ""); } } return (foundGrp) ? metricMap[0] : Mgr::npos; }
void LoadMap::lm_insert(LoadMap::LM* x) { m_lm_byId.push_back(x); x->id(m_lm_byId.size() - 1); // id is the last slot used std::pair<LMSet_nm::iterator, bool> ret = m_lm_byName.insert(x); DIAG_Assert(ret.second, "LoadMap::lm_insert(): conflict inserting: " << x->toString()); }
void Mgr::computePartners() { StringToADescMap metricsIncl; StringToADescMap metricsExcl; // ------------------------------------------------------- // populate maps // ------------------------------------------------------- for (uint i = 0; i < m_metrics.size(); ++i) { Metric::ADesc* m = m_metrics[i]; string nm = m->namePfxBaseSfx(); StringToADescMap* metricsMap = NULL; switch (m->type()) { case ADesc::TyIncl: metricsMap = &metricsIncl; break; case ADesc::TyExcl: metricsMap = &metricsExcl; break; default: break; } if (metricsMap) { DIAG_MsgIf(0, "Metric::Mgr::computePartners: insert: " << nm << " [" << m->name() << "]"); std::pair<StringToADescMap::iterator, bool> ret = metricsMap->insert(make_pair(nm, m)); DIAG_Assert(ret.second, "Metric::Mgr::computePartners: Found duplicate entry inserting:\n\t" << m->toString() << "\nOther entry:\n\t" << ret.first->second->toString()); } } // ------------------------------------------------------- // find partners // ------------------------------------------------------- for (uint i = 0; i < m_metrics.size(); ++i) { Metric::ADesc* m = m_metrics[i]; string nm = m->namePfxBaseSfx(); StringToADescMap* metricsMap = NULL; switch (m->type()) { case ADesc::TyIncl: metricsMap = &metricsExcl; break; case ADesc::TyExcl: metricsMap = &metricsIncl; break; default: break; } if (metricsMap) { StringToADescMap::iterator it = metricsMap->find(nm); if (it != metricsMap->end()) { Metric::ADesc* partner = it->second; m->partner(partner); DIAG_MsgIf(0, "Metric::Mgr::computePartners: found: " << m->name() << " -> " << partner->name()); } } } }
void packMetrics(const Prof::CallPath::Profile& profile, ParallelAnalysis::PackedMetrics& packedMetrics) { Prof::CCT::Tree& cct = *profile.cct(); // pack derived metrics [mDrvdBeg, mDrvdEnd) from 'profile' into // 'packedMetrics' uint mDrvdBeg = packedMetrics.mDrvdBegId(); uint mDrvdEnd = packedMetrics.mDrvdEndId(); DIAG_Assert(packedMetrics.numNodes() == cct.maxDenseId() + 1, ""); DIAG_Assert(packedMetrics.numMetrics() == mDrvdEnd - mDrvdBeg, ""); for (Prof::CCT::ANodeIterator it(cct.root()); it.Current(); ++it) { Prof::CCT::ANode* n = it.current(); for (uint mId1 = 0, mId2 = mDrvdBeg; mId2 < mDrvdEnd; ++mId1, ++mId2) { packedMetrics.idx(n->id(), mId1) = n->metric(mId2); } } }
bool Mgr::insertInMapsAndMakeUniqueName(Metric::ADesc* m) { bool isChanged = false; // 1. metric name to Metric::ADescVec table string nm = m->name(); StringToADescVecMap::iterator it = m_nuniqnmToMetricMap.find(nm); if (it != m_nuniqnmToMetricMap.end()) { Metric::ADescVec& mvec = it->second; // ensure uniqueness: qualifier is an integer >= 1 int qualifier = mvec.size(); const string& nm_sfx = m->nameSfx(); string sfx_new = nm_sfx; if (!sfx_new.empty()) { sfx_new += "."; } sfx_new += StrUtil::toStr(qualifier); m->nameSfx(sfx_new); nm = m->name(); // update 'nm' isChanged = true; mvec.push_back(m); } else { m_nuniqnmToMetricMap.insert(make_pair(nm, Metric::ADescVec(1, m))); } // 2. unique name to Metric::ADesc table std::pair<StringToADescMap::iterator, bool> ret = m_uniqnmToMetricMap.insert(make_pair(nm, m)); DIAG_Assert(ret.second, "Metric::Mgr::insertInMapsAndMakeUniqueName: Found duplicate entry inserting:\n\t" << m->toString() << "\nOther entry:\n\t" << ret.first->second->toString()); // 3. profile file name to Metric::SampledDesc table Metric::SampledDesc* mSmpl = dynamic_cast<Metric::SampledDesc*>(m); if (mSmpl) { const string& fnm = mSmpl->profileName(); StringToADescVecMap::iterator it1 = m_fnameToFMetricMap.find(fnm); if (it1 != m_fnameToFMetricMap.end()) { Metric::ADescVec& mvec = it1->second; mvec.push_back(mSmpl); } else { m_fnameToFMetricMap.insert(make_pair(fnm, Metric::ADescVec(1, mSmpl))); } } return isChanged; }
void IteratorStack::InitTraversal(TraversalOrder torder, IterStackEnumType _enumType) { clientTraversalOrder = torder; enumType = _enumType; if (enumType == ITER_STACK_ENUM_LEAVES_ONLY) traversalOrder = PostOrder; else if (torder == ReversePreOrder) traversalOrder = PreOrder; // reversed by IteratorToPushIfAny else if (torder == ReversePostOrder) traversalOrder = PostOrder; // reversed by IteratorToPushIfAny //else if (torder == ReversePreAndPostOrder) // traversalOrder = PreAndPostOrder; // reversed by IteratorToPushIfAny else { DIAG_Assert((torder == PreOrder) || (torder == PostOrder) || (torder == PreAndPostOrder), ""); traversalOrder = torder; } }
double toDbl(const char* str, unsigned* endidx) { double value = 0; DIAG_Assert((str && str[0] != '\0'), "StrUtil::toDbl: empty string!"); errno = 0; char* endptr = NULL; value = strtod(str, &endptr); if (endidx) { *endidx = (endptr - str) / sizeof(char); } if (errno || (!endidx && endptr && strlen(endptr) > 0)) { string msg = "[StrUtil::toDbl] Cannot convert `" + string(str) + "' to real (double) value."; if (errno) { // not always set msg += string(" (") + strerror(errno) + string(")"); } DIAG_Throw(msg); } return value; }
uint64_t toUInt64(const char* str, unsigned* endidx) { uint64_t value = 0; DIAG_Assert((str && str[0] != '\0'), "StrUtil::toUInt64: empty string!"); errno = 0; char* endptr = NULL; value = strtoull(str, &endptr, 0); if (endidx) { *endidx = (endptr - str) / sizeof(char); } if (errno || (!endidx && endptr && strlen(endptr) > 0)) { string msg = "[StrUtil::toUInt64] Cannot convert `" + string(str) + "' to integral (uint64_t) value"; if (errno) { // not always set msg += string(" (") + strerror(errno) + string(")"); } DIAG_Throw(msg); } return value; }
void InsertPC(VMA pc, ushort opIndex) { DIAG_Assert(pcset, ""); VMA oppc = mset->GetISA()->convertVMAToOpVMA(pc, opIndex); pcset->insert(oppc); // do not add duplicates! }