uint Mgr::makeSummaryMetricsIncr(bool needAllStats, uint srcBegId, uint srcEndId) { if (srcBegId == Mgr::npos) { srcBegId = 0; } if (srcEndId == Mgr::npos) { srcEndId = m_metrics.size(); } uint firstId = Mgr::npos; for (uint i = srcBegId; i < srcEndId; ++i) { Metric::ADesc* m = m_metrics[i]; Metric::ADesc* mNew = makeSummaryMetricIncr("Sum", m); if (needAllStats) { makeSummaryMetricIncr("Mean", m); makeSummaryMetricIncr("StdDev", m); makeSummaryMetricIncr("CfVar", m); makeSummaryMetricIncr("Min", m); makeSummaryMetricIncr("Max", m); } if (firstId == Mgr::npos) { firstId = mNew->id(); } } computePartners(); return firstId; }
// Assumes: metrics are of type Metric::SampledDesc and values are // only at leaves (CCT::Stmt) void MetricComponentsFact::make(Prof::CallPath::Profile& prof) { using namespace Prof; // ------------------------------------------------------------ // Create destination metric descriptors and mapping from source // metrics to destination metrics // ------------------------------------------------------------ std::vector<uint> metricSrcIds; std::vector<uint> metricDstIds; Metric::Mgr* metricMgr = prof.metricMgr(); uint numMetrics_orig = metricMgr->size(); for (uint mId = 0; mId < numMetrics_orig; ++mId) { Metric::ADesc* m = metricMgr->metric(mId); if (MetricComponentsFact::isTimeMetric(m)) { DIAG_Assert(typeid(*m) == typeid(Metric::SampledDesc), DIAG_UnexpectedInput << "temporary sanity check"); MetricComponentsFact::convertToWorkMetric(m); metricSrcIds.push_back(m->id()); Metric::ADesc* m_new = m->clone(); m_new->nameBase("overhead"); m_new->description("parallel overhead"); metricMgr->insert(m_new); DIAG_Assert(m_new->id() >= numMetrics_orig, "Currently, we assume new metrics are added at the end of the metric vector."); metricDstIds.push_back(m_new->id()); } } if (metricSrcIds.empty()) { return; } // ------------------------------------------------------------ // Create values for metric components // ------------------------------------------------------------ make(prof.cct()->root(), metricSrcIds, metricDstIds, false); }
std::ostream& Mgr::dump(std::ostream& os, const char* pfx) const { os << pfx << "[ metric table:" << std::endl; for (uint i = 0; i < m_metrics.size(); i++) { Metric::ADesc* m = m_metrics[i]; os << pfx << " " << m->id() << ": " << m->toString() << std::endl; } os << pfx << "]" << std::endl; os << pfx << "[ unique-name-to-metric:" << std::endl; for (StringToADescMap::const_iterator it = m_uniqnmToMetricMap.begin(); it != m_uniqnmToMetricMap.end(); ++it) { const string& nm = it->first; Metric::ADesc* m = it->second; os << pfx << " " << nm << " -> " << m->toString() << std::endl; } os << pfx << "]" << std::endl; return os; }
Metric::DerivedDesc* Mgr::makeSummaryMetric(const string mDrvdTy, const Metric::ADesc* mSrc, const Metric::ADescVec& mOpands) { Metric::AExpr** opands = new Metric::AExpr*[mOpands.size()]; for (uint i = 0; i < mOpands.size(); ++i) { Metric::ADesc* m = mOpands[i]; opands[i] = new Metric::Var(m->name(), m->id()); } bool doDispPercent = true; bool isPercent = false; bool isVisible = true; // This is a cheesy way of creating the metrics, but it is good // enough for now. Metric::AExpr* expr = NULL; if (mDrvdTy.find("Sum", 0) == 0) { expr = new Metric::Plus(opands, mOpands.size()); } else if (mDrvdTy.find("Mean", 0) == 0) { expr = new Metric::Mean(opands, mOpands.size()); doDispPercent = false; } else if (mDrvdTy.find("StdDev", 0) == 0) { expr = new Metric::StdDev(opands, mOpands.size()); doDispPercent = false; } else if (mDrvdTy.find("CfVar", 0) == 0) { expr = new Metric::CoefVar(opands, mOpands.size()); doDispPercent = false; } else if (mDrvdTy.find("%CfVar", 0) == 0) { expr = new Metric::RStdDev(opands, mOpands.size()); isPercent = true; } else if (mDrvdTy.find("Min", 0) == 0) { expr = new Metric::Min(opands, mOpands.size()); doDispPercent = false; } else if (mDrvdTy.find("Max", 0) == 0) { expr = new Metric::Max(opands, mOpands.size()); doDispPercent = false; } else { DIAG_Die(DIAG_UnexpectedInput); } string mNmFmt = mSrc->nameToFmt(); string mNmBase = mSrc->nameBase() + ":" + mDrvdTy; const string& mDesc = mSrc->description(); DerivedDesc* m = new DerivedDesc(mNmFmt, mDesc, expr, isVisible, true/*isSortKey*/, doDispPercent, isPercent); m->nameBase(mNmBase); m->nameSfx(""); // clear; cf. Prof::CallPath::Profile::RFlg_NoMetricSfx m->zeroDBInfo(); // clear insert(m); expr->accumId(m->id()); if (expr->hasAccum2()) { string m2NmBase = mNmBase + ":accum2"; DerivedDesc* m2 = new DerivedDesc(mNmFmt, mDesc, NULL/*expr*/, false/*isVisible*/, false/*isSortKey*/, false/*doDispPercent*/, false/*isPercent*/); m2->nameBase(m2NmBase); m2->nameSfx(""); // clear; cf. Prof::CallPath::Profile::RFlg_NoMetricSfx m2->zeroDBInfo(); // clear insert(m2); expr->accum2Id(m2->id()); } if (expr->hasNumSrcVar()) { string m3NmBase = mNmBase + ":num-src"; Metric::NumSource* m3Expr = new Metric::NumSource(mOpands.size()); DerivedDesc* m3 = new DerivedDesc(mNmFmt, mDesc, m3Expr, false/*isVisible*/, false/*isSortKey*/, false/*doDispPercent*/, false/*isPercent*/); m3->nameBase(m3NmBase); m3->nameSfx(""); // clear; cf. Prof::CallPath::Profile::RFlg_NoMetricSfx m3->zeroDBInfo(); // clear insert(m3); m3Expr->accumId(m3->id()); expr->numSrcVarId(m3->id()); } return m; }
uint Mgr::makeSummaryMetrics(bool needAllStats, bool needMultiOccurance, uint srcBegId, uint srcEndId) { StringToADescVecMap nmToMetricMap; std::vector<Metric::ADescVec*> metricGroups; if (srcBegId == Mgr::npos) { srcBegId = 0; } if (srcEndId == Mgr::npos) { srcEndId = m_metrics.size(); } uint threshold = (needMultiOccurance) ? 2 : 1; // ------------------------------------------------------- // collect like metrics // ------------------------------------------------------- for (uint i = srcBegId; i < srcEndId; ++i) { Metric::ADesc* m = m_metrics[i]; string nm = m->nameGeneric(); StringToADescVecMap::iterator it = nmToMetricMap.find(nm); if (it != nmToMetricMap.end()) { Metric::ADescVec& mvec = it->second; mvec.push_back(m); } else { std::pair<StringToADescVecMap::iterator, bool> ret = nmToMetricMap.insert(make_pair(nm, Metric::ADescVec(1, m))); Metric::ADescVec* grp = &(ret.first->second); metricGroups.push_back(grp); } } // ------------------------------------------------------- // create summary metrics // ------------------------------------------------------- uint firstId = Mgr::npos; for (uint i = 0; i < metricGroups.size(); ++i) { const Metric::ADescVec& mVec = *(metricGroups[i]); if (mVec.size() >= threshold) { const Metric::ADesc* m = mVec[0]; Metric::ADesc* mNew = makeSummaryMetric("Sum", m, mVec); if (needAllStats) { makeSummaryMetric("Mean", m, mVec); makeSummaryMetric("StdDev", m, mVec); makeSummaryMetric("CfVar", m, mVec); makeSummaryMetric("Min", m, mVec); makeSummaryMetric("Max", m, mVec); } if (firstId == Mgr::npos) { firstId = mNew->id(); } } } computePartners(); return firstId; }
// make: ...temporary holding pattern... void MPIBlameShiftIdlenessFact::make(Prof::CallPath::Profile& prof) { using namespace Prof; // ------------------------------------------------------------ // Create destination metric descriptors and mapping from source // metrics to destination metrics // ------------------------------------------------------------ std::vector<uint> metricSrcIds; std::vector<uint> metricBalanceIds; std::vector<uint> metricImbalInclIds, metricImbalExclIds; std::vector<uint> metricIdleInclIds; Metric::Mgr* metricMgr = prof.metricMgr(); uint numMetrics_orig = metricMgr->size(); for (uint mId = 0; mId < numMetrics_orig; ++mId) { Metric::ADesc* m = metricMgr->metric(mId); // find main source metric if (MetricComponentsFact::isTimeMetric(m) && MetricComponentsFact::isDerivedMetric(m, s_sum) && m->type() == Metric::ADesc::TyIncl && m->isVisible() /* not a temporary */) { DIAG_Assert(m->computedType() == Prof::Metric::ADesc::ComputedTy_NonFinal, DIAG_UnexpectedInput); metricSrcIds.push_back(m->id()); // FIXME: For now we use only Metric::ADesc::DerivedIncrDesc() // We should also support Metric::ADesc::DerivedDesc() DIAG_Assert(typeid(*m) == typeid(Metric::DerivedIncrDesc), DIAG_UnexpectedInput); Metric::DerivedIncrDesc* m_imbalIncl = static_cast<Metric::DerivedIncrDesc*>(m->clone()); m_imbalIncl->nameBase("imbalance" + s_sum); m_imbalIncl->description("imbalance for MPI SPMD executions"); m_imbalIncl->expr(new Metric::SumIncr(Metric::IData::npos, // FIXME:Sum Metric::IData::npos)); Metric::DerivedIncrDesc* m_imbalExcl = static_cast<Metric::DerivedIncrDesc*>(m_imbalIncl->clone()); m_imbalExcl->type(Metric::ADesc::TyExcl); m_imbalExcl->expr(new Metric::SumIncr(Metric::IData::npos, Metric::IData::npos)); m_imbalIncl->partner(m_imbalExcl); m_imbalExcl->partner(m_imbalIncl); Metric::DerivedIncrDesc* m_idleIncl = static_cast<Metric::DerivedIncrDesc*>(m->clone()); m_idleIncl->nameBase("idleness" + s_sum); m_idleIncl->description("idleness for MPI executions"); m_idleIncl->partner(NULL); m_idleIncl->expr(new Metric::SumIncr(Metric::IData::npos, // FIXME:Sum Metric::IData::npos)); metricMgr->insert(m_imbalIncl); metricMgr->insert(m_imbalExcl); metricMgr->insert(m_idleIncl); m_imbalIncl->expr()->accumId(m_imbalIncl->id()); m_imbalExcl->expr()->accumId(m_imbalExcl->id()); m_idleIncl->expr()->accumId(m_idleIncl->id()); DIAG_Assert(m_imbalIncl->id() >= numMetrics_orig && m_imbalExcl->id() >= numMetrics_orig, "Currently, we assume new metrics are added at the end of the metric vector."); metricImbalInclIds.push_back(m_imbalIncl->id()); metricImbalExclIds.push_back(m_imbalExcl->id()); metricIdleInclIds.push_back(m_idleIncl->id()); } // find secondary source metric if (MetricComponentsFact::isTimeMetric(m) && MetricComponentsFact::isDerivedMetric(m, s_cfvar) && m->type() == Metric::ADesc::TyIncl && m->isVisible() /* not a temporary */) { DIAG_Assert(m->computedType() == Prof::Metric::ADesc::ComputedTy_NonFinal, DIAG_UnexpectedInput); metricBalanceIds.push_back(m->id()); } } DIAG_Assert(metricSrcIds.size() == metricBalanceIds.size(), DIAG_UnexpectedInput); if (metricSrcIds.empty()) { return; } // ------------------------------------------------------------ // Create values for metric components // ------------------------------------------------------------ // Note that metrics are non-finalized! CCT::ANode* cctRoot = prof.cct()->root(); uint metricBalancedId = metricBalanceIds[0]; Metric::AExprIncr* metricBalancedExpr = dynamic_cast<Metric::DerivedIncrDesc*>(metricMgr->metric(metricBalancedId))->expr(); Metric::IData cctRoot_mdata(*cctRoot); metricBalancedExpr->finalize(cctRoot_mdata); double balancedThreshold = 1.2 * cctRoot_mdata.demandMetric(metricBalancedId); makeMetrics(cctRoot, metricSrcIds, metricImbalInclIds, metricImbalExclIds, metricIdleInclIds, metricBalancedId, metricBalancedExpr, balancedThreshold, NULL, NULL); VMAIntervalSet metricDstInclIdSet; for (uint i = 0; i < metricImbalInclIds.size(); ++i) { uint mId = metricImbalInclIds[i]; metricDstInclIdSet.insert(VMAInterval(mId, mId + 1)); // [ ) mId = metricIdleInclIds[i]; metricDstInclIdSet.insert(VMAInterval(mId, mId + 1)); // [ ) } cctRoot->aggregateMetricsIncl(metricDstInclIdSet); }