22 #include <Teuchos_DefaultComm.hpp>
23 #include <Teuchos_Time.hpp>
24 #include <Teuchos_StackedTimer.hpp>
33 using Teuchos::ParameterList;
38 using Teuchos::reduceAll;
39 using namespace Zoltan2_TestingFramework;
49 const std::string& problemName)
50 : stackedTimer_(stackedTimer)
51 , problemName_(problemName) {}
54 stackedTimer_->start(problemName_);
58 stackedTimer_->stop(problemName_);
62 stackedTimer_->start(timerName);
66 stackedTimer_->stop(timerName);
71 std::map<std::string, double> timings;
72 std::string prefix = stackedTimer_->name()+
"@"+problemName_+
"@";
73 for (
auto timerName : {
"adapter construction timer",
"problem construction time",
"solve time"}) {
74 auto t = stackedTimer_->findTimer(prefix+timerName);
75 timings[timerName] = t.time;
81 Teuchos::RCP<Teuchos::StackedTimer> stackedTimer_;
82 const std::string problemName_;
97 :stackedTimer_(stackedTimer) {}
103 bool Compare(
const ParameterList &pList,
const RCP<
const Comm<int> > &comm);
109 RCP<ComparisonSource> AddSource(
const string &name);
115 return this->sources.size();
119 map<const string,RCP<const ComparisonSource> > sources;
126 bool CompareSolutions(
const string &p1,
128 const RCP<
const Comm<int> > &comm);
142 const RCP<
const Comm<int> > &comm);
151 const RCP<
const Comm<int> > &comm);
160 const RCP<
const Comm<int> > &comm);
167 void loadMetricInfo(RCP<EvaluateFactory> problemFactory,
168 std::vector<MetricAnalyzerInfo> & metricInfo,
169 const ParameterList &metricsPlist);
175 bool CompareMetrics(
const ParameterList &metricsPlist,
176 const RCP<
const Comm<int> > &comm);
188 metricComparisonTest(
const RCP<
const Comm<int> > &comm,
191 const Teuchos::ParameterList & metricPlist,
192 std::ostringstream &msg);
204 timerComparisonTest(
const RCP<
const Comm<int> > &comm,
206 const double ref_time,
207 const Teuchos::ParameterList & metricPlist,
208 std::ostringstream &msg);
215 static std::map<const string, const double>
216 timerDataToMap(
const map<
const std::string, RCP<Time> > &timers);
224 static std::queue<ParameterList>
225 getMetricsToCompare(
const ParameterList & pList);
228 reduceWithMessage(
const RCP<
const Comm<int> > &comm,
229 const std::string &msg_in,
230 int &local_status, std::ostringstream &msg);
233 RCP<Teuchos::StackedTimer> stackedTimer_;
240 typedef std::pair<const string &, RCP<const ComparisonSource> > pair_t;
242 this->sources.insert(pair_t(name, source));
247 const RCP<
const Comm<int> > &comm)
249 if(pList.isParameter(
"A") && pList.isParameter(
"B")) {
251 string pA = pList.get<
string>(
"A");
252 if(this->sources.find(pA) == this->sources.end())
254 std::cout <<
"\nProblem: " + pA +
", was not saved for comparison.";
255 std::cout <<
"\nThis typically indicates that an error ";
256 std::cout <<
"occurred while running the problem.";
257 std::cout <<
"\nSolution comparison FAILED." << std::endl;
261 string pB = pList.get<
string>(
"B");
262 if(this->sources.find(pB) == this->sources.end()) {
263 std::cout <<
"\nProblem: " + pB +
", was not saved for comparison.";
264 std::cout <<
"\nThis typically indicates that an error ";
265 std::cout <<
"occurred while running the problem.";
266 std::cout <<
"\nSolution comparison FAILED." << std::endl;
270 bool bResult = this->CompareSolutions(pA, pB, comm);
273 else if (pList.isParameter(
"Problem") && pList.isParameter(
"Reference")) {
275 string prb = pList.get<
string>(
"Problem");
276 if(this->sources.find(prb) == this->sources.end()) {
277 std::cout <<
"\nProblem: " + prb +
", was not saved for comparison.";
278 std::cout <<
"\nThis typically indicates that an error ";
279 std::cout <<
"occurred while running the problem.";
280 std::cout <<
"\nMetric comparison FAILED." << std::endl;
284 string ref = pList.get<
string>(
"Reference");
285 if(this->sources.find(ref) == this->sources.end()) {
286 std::cout <<
"\nReference: " + ref +
", was not saved for comparison.";
287 std::cout <<
"\nThis typically indicates that an error ";
288 std::cout <<
"occurred while running the problem.";
289 std::cout <<
"\nMetric comparison FAILED." << std::endl;
293 bool bResult = this->CompareMetrics(pList, comm);
296 else if (pList.isParameter(
"A") || pList.isParameter(
"B"))
298 if(comm->getRank() == 0)
300 std::cout <<
"Problem A or Problem B is not specified -- check input.";
301 std::cout <<
"\nSolution comparison FAILED." << std::endl;
304 else if (pList.isParameter(
"Problem") || pList.isParameter(
"Reference")) {
305 if(comm->getRank() == 0) {
306 std::cout <<
"Problem or reference is not specified -- check input.";
307 std::cout <<
"\nMetric comparison FAILED." << std::endl;
311 if (comm->getRank() == 0) {
312 std::cout <<
"ComparisonHelper did not understand how to read the xml. ";
313 std::cout <<
"Test FAILED." << std::endl;
319 bool ComparisonHelper::CompareSolutions(
const string &p1,
321 const RCP<
const Comm<int> > &comm)
323 if(comm->getRank() == 0) printf(
"\nComparing: %s and %s\n",
324 p1.c_str(), p2.c_str());
325 auto A = this->sources[p1];
326 auto B = this->sources[p2];
327 if(A->problemFactory->getProblemName() != B->problemFactory->getProblemName()) {
328 std::cout <<
"Problem A and B are of a different kind and cannot be compared.";
329 std::cout <<
"\nSolution comparison FAILED." << std::endl;
332 if(A->problemFactory->getProblemName() ==
"partitioning") {
333 return this->ComparePartitionSolutions(A.getRawPtr(), B.getRawPtr(), comm);
335 else if(A->problemFactory->getProblemName() ==
"coloring") {
336 return this->CompareColoringSolutions(A.getRawPtr(), B.getRawPtr(), comm);
338 else if(A->problemFactory->getProblemName() ==
"ordering"){
339 return this->CompareOrderingSolutions(A.getRawPtr(), B.getRawPtr(), comm);
342 std::cout <<
"Problem kind: " << A->problemFactory->getProblemName() <<
343 " not recognized. Check spelling.";
344 std::cout <<
"\nSolution comparison FAILED." << std::endl;
350 void ComparisonHelper::reduceWithMessage(
const RCP<
const Comm<int> > &comm,
351 const std::string &msg_in,
353 std::ostringstream &msg) {
356 Teuchos::Ptr<int> global(&global_buff);
357 reduceAll<int,int>(*comm.get(), Teuchos::EReductionType::REDUCE_MAX,
358 local_status , global);
359 local_status = *global;
360 if (local_status == 1) {
365 const zpart_t * ComparisonHelper::getPartListView(
366 RCP<ProblemFactory> problemFactory)
const {
367 #define GET_PROBLEM_PARTS(adapterClass) \
368 return (rcp_dynamic_cast<PartitioningProblem<adapterClass>>( \
369 problemFactory->getProblem()))->getSolution().getPartListView();
373 bool ComparisonHelper::ComparePartitionSolutions(
const ComparisonSource * sourceA,
375 const RCP<
const Comm<int> > &comm)
377 int rank = comm->getRank();
378 std::ostringstream status;
386 ComparisonHelper::reduceWithMessage(comm,
387 "Number of parts in Solution A != Solution B. \
388 Partitioning solution comparison FAILED.",
393 i < sourceA->
adapterFactory->getMainAdapter()->getLocalNumIDs(); i++) {
397 ComparisonHelper::reduceWithMessage(comm,
398 "Solution sets A and B have different values for getPartListView(). "
399 "Solution comparison FAILED.", failed, status);
405 status <<
"Solution sets A and B are the same. ";
406 status <<
"Solution set comparison PASSED.";
410 std::cout << status.str() << std::endl;
412 return (failed == 0);
416 bool ComparisonHelper::CompareColoringSolutions(
const ComparisonSource * sourceA,
418 const RCP<
const Comm<int> > &comm)
420 int rank = comm->getRank();
421 std::ostringstream status;
463 status <<
"Solution sets A and B are the same. ";
464 status <<
"Solution set comparison PASSED.";
468 std::cout << status.str() << std::endl;
470 return (failed == 0);
473 bool ComparisonHelper::CompareOrderingSolutions(
const ComparisonSource * sourceA,
475 const RCP<
const Comm<int> > &comm)
477 int rank = comm->getRank();
478 std::ostringstream status;
484 status <<
"Solution sets A and B are the same. ";
485 status <<
"Solution set comparison PASSED.";
489 std::cout << status.str() << std::endl;
491 return (failed == 0);
495 void ComparisonHelper::loadMetricInfo(RCP<EvaluateFactory> evaluateFactory,
496 std::vector<MetricAnalyzerInfo> & metricInfo,
497 const ParameterList &metricsPlist) {
499 #define LOAD_METRIC_INFO(adapterClass, metricAnalyzerClass) \
500 RCP<EvaluateBaseClass<adapterClass>> pCast = \
501 rcp_dynamic_cast<EvaluateBaseClass<adapterClass>>(evaluateFactory->getEvaluateClass()); \
502 if(pCast == Teuchos::null) throw std::logic_error( \
503 "Bad evaluate class cast in loadMetricInfo!" ); \
504 metricAnalyzerClass analyzer(pCast); \
505 analyzer.LoadMetricInfo(metricInfo, metricsPlist.sublist("Metrics"));
507 #define LOAD_METRIC_INFO_PARTITIONING(adapterClass) \
508 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluatePartition<adapterClass>)
510 #define LOAD_METRIC_INFO_ORDERING(adapterClass) \
511 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluateOrdering<adapterClass>)
513 if(evaluateFactory->getProblemName() ==
"partitioning") {
516 else if(evaluateFactory->getProblemName() ==
"ordering") {
520 throw std::logic_error(
521 "loadMetricInfo not implemented for this problem type!" );
526 bool ComparisonHelper::CompareMetrics(
const ParameterList &metricsPlist,
const RCP<
const Comm<int> > &comm)
528 int rank = comm->getRank();
531 const string prb_name = metricsPlist.get<
string>(
"Problem");
532 const string ref_name = metricsPlist.get<
string>(
"Reference");
534 std::cout <<
"\nMetric/Timer comparison of: " << prb_name <<
" and ";
535 std::cout << ref_name <<
" (reference source)\n";
539 RCP<const ComparisonSource> sourcePrb = this->sources[prb_name];
540 RCP<const ComparisonSource> sourceRef = this->sources[ref_name];
543 const std::map< string, double>& prb_timers = sourcePrb->getTimingsMap();
544 const std::map< string, double>& ref_timers = sourceRef->getTimingsMap();
547 std::queue<ParameterList> metrics = ComparisonHelper::getMetricsToCompare(metricsPlist);
550 int all_tests_pass = 1;
553 while(!metrics.empty()) {
555 std::ostringstream msg;
556 metric_name = metrics.front().name();
558 if (metric_name ==
"Metrics") {
559 std::vector<MetricAnalyzerInfo> metricInfoSetPrb;
560 std::vector<MetricAnalyzerInfo> metricInfoSetRef;
562 loadMetricInfo(sourcePrb.get()->evaluateFactory, metricInfoSetPrb, metricsPlist);
563 loadMetricInfo(sourceRef.get()->evaluateFactory, metricInfoSetRef, metricsPlist);
568 for (
size_t n = 0; n < metricInfoSetPrb.size(); ++n) {
569 if(!ComparisonHelper::metricComparisonTest(comm, metricInfoSetPrb[n], metricInfoSetRef[n], metrics.front(), msg)) {
573 std::cout << msg.str() << std::endl;
577 else if(prb_timers.find(metric_name) != prb_timers.end() && ref_timers.find(metric_name) != ref_timers.end()) {
578 if(rank == 0) std::cout <<
"\ncomparing timer: " << metric_name << std::endl;
579 if(!ComparisonHelper::timerComparisonTest(comm,
580 prb_timers.at(metric_name),
581 ref_timers.at(metric_name),
582 metrics.front(), msg)) {
585 std::cout <<
"timer comparison test caused a FAILED event." << std::endl;
590 std::cout << msg.str() << std::endl;
598 if(all_tests_pass == 1) {
599 std::cout <<
"\nAll metric/timer comparisons PASSED." << std::endl;
602 std::cout <<
"\nMetric/timer metric comparisons FAILED." << std::endl;
606 return (all_tests_pass == 1);
609 bool ComparisonHelper::metricComparisonTest(
const RCP<
const Comm<int> > &comm,
612 const Teuchos::ParameterList & metricPlist,
613 std::ostringstream &msg)
618 string test_name = metricPlist.name() +
" test";
619 double ref_value = ref_metric.
theValue;
622 if (ref_value == 0) {
623 throw std::logic_error(
"The parameter list had a 0 value for the reference value so a percentage cannot be calculated." );
625 double percentRatio = value / ref_value;
631 if (percentRatio < min) {
632 msg << test_name <<
" FAILED: " << ref_metric.
parameterDescription <<
": " << value <<
" is " << percentRatio <<
" percent of the reference value " << ref_value <<
", which less than specified allowable minimum percent, " << min <<
".\n";
636 msg << test_name <<
" PASSED: " << ref_metric.
parameterDescription <<
": " << value <<
" is " << percentRatio <<
" percent of the reference value " << ref_value <<
", which is greater than specified allowable minimum percent, " << min <<
".\n";
642 if (percentRatio > max) {
643 msg << test_name <<
" FAILED: " << ref_metric.
parameterDescription <<
": " << value <<
" is " << percentRatio <<
" percent of the reference value " << ref_value <<
", which is greater than specified allowable maximum percent, " << max <<
".\n";
647 msg << test_name <<
" PASSED: " << ref_metric.
parameterDescription <<
": " << value <<
" is " << percentRatio <<
" percent of the reference value " << ref_value <<
", which is less than specified allowable maximum percent, " << max <<
".\n";
656 bool ComparisonHelper::timerComparisonTest(
const RCP<
const Comm<int> > &comm,
658 const double ref_time,
659 const Teuchos::ParameterList & metricPlist,
660 std::ostringstream &msg)
664 Teuchos::Ptr<double> global(&global_time);
666 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,time,global);
669 double global_ref_time;
670 Teuchos::Ptr<double> globalRef(&global_ref_time);
672 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,ref_time,globalRef);
677 string test_name = metricPlist.name() +
" test";
679 if (metricPlist.isParameter(
"lower")) {
680 double min = metricPlist.get<
double>(
"lower")*global_ref_time;
682 if (global_time < min) {
683 msg << test_name <<
" FAILED: Minimum time, "
685 "[s], less than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
689 msg << test_name <<
" PASSED: Minimum time, "
691 "[s], greater than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
695 if (metricPlist.isParameter(
"upper" ) && pass !=
false) {
696 double max = metricPlist.get<
double>(
"upper") * global_ref_time;
697 if (global_time > max) {
698 msg << test_name <<
" FAILED: Maximum time, "
700 "[s], greater than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
704 msg << test_name <<
" PASSED: Maximum time, "
706 "[s], less than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
713 std::queue<ParameterList> ComparisonHelper::getMetricsToCompare(
const ParameterList &pList)
716 std::queue<ParameterList> metrics;
717 for(
auto it = pList.begin(); it != pList.end(); ++it) {
718 if (pList.isSublist(it->first)) {
719 metrics.push(pList.sublist(it->first));
keep typedefs that commonly appear in many places localized
const zpart_t * getPartListView(RCP< ProblemFactory > problemFactory)
void startTimer(const std::string &timerName)
RCP< ComparisonSource > AddSource(const string &name)
Returns a pointer to new test classes. Is not responsible for memory management!
RCP< ProblemFactory > problemFactory
common code used by tests
#define LOAD_METRIC_INFO_ORDERING(adapterClass)
bool Compare(const ParameterList &pList, const RCP< const Comm< int > > &comm)
#define Z2_TEST_UPCAST(adptr, TEMPLATE_ACTION)
#define LOAD_METRIC_INFO_PARTITIONING(adapterClass)
size_t getNumberOfSources() const
RCP< EvaluateFactory > evaluateFactory
ComparisonHelper(Teuchos::RCP< Teuchos::StackedTimer > &stackedTimer)
A class for comparing solutions, metrics, and timing data of Zoltan2 problems.
std::map< std::string, double > getTimingsMap() const
void stopTimer(const std::string &timerName)
static const std::string pass
ComparisonSource(Teuchos::RCP< Teuchos::StackedTimer > &stackedTimer, const std::string &problemName)
A class used to save problem solutions and timers.
std::string parameterDescription
Generate Adapter for testing purposes.
RCP< AdapterFactory > adapterFactory
#define GET_PROBLEM_PARTS(adapterClass)