58 #include <Teuchos_DefaultComm.hpp> 59 #include <Teuchos_Time.hpp> 68 using Teuchos::ParameterList;
75 using std::ostringstream;
76 using Teuchos::reduceAll;
90 timers.insert(std::pair<
const std::string &, RCP<Time> >(name,rcp(
new Time(name))));
91 timers[name]->enable();
96 for(
auto it = timers.begin(); it != timers.end(); ++it) {
97 std::cout << it->first <<
" " << it->second->totalElapsedTime()
104 std::map<const std::string, RCP<Time> >
timers;
120 bool Compare(
const ParameterList &pList,
const RCP<
const Comm<int> > &comm);
126 void AddSource(
const string &name, RCP<ComparisonSource> source);
132 return this->sources.size();
136 map<const string,RCP<const ComparisonSource> > sources;
143 bool CompareSolutions(
const string &p1,
145 const RCP<
const Comm<int> > &comm);
150 const zpart_t * getPartListView(RCP<ProblemFactory> problemFactory)
const;
159 const RCP<
const Comm<int> > &comm);
168 const RCP<
const Comm<int> > &comm);
177 const RCP<
const Comm<int> > &comm);
184 void loadMetricInfo(RCP<EvaluateFactory> problemFactory,
185 std::vector<MetricAnalyzerInfo> & metricInfo,
186 const ParameterList &metricsPlist);
192 bool CompareMetrics(
const ParameterList &metricsPlist,
193 const RCP<
const Comm<int> > &comm);
205 metricComparisonTest(
const RCP<
const Comm<int> > &comm,
208 const Teuchos::ParameterList & metricPlist,
221 timerComparisonTest(
const RCP<
const Comm<int> > &comm,
223 const double ref_time,
224 const Teuchos::ParameterList & metricPlist,
232 static std::map<const string, const double>
233 timerDataToMap(
const map<
const std::string, RCP<Time> > &timers);
241 static std::queue<ParameterList>
242 getMetricsToCompare(
const ParameterList & pList);
245 reduceWithMessage(
const RCP<
const Comm<int> > &comm,
246 const std::string &msg_in,
247 int &local_status, std::ostringstream &msg);
253 RCP<ComparisonSource> source)
255 typedef std::pair<const string &, RCP<const ComparisonSource> > pair_t;
256 this->sources.insert(pair_t(name, source));
260 const RCP<
const Comm<int> > &comm)
262 if(pList.isParameter(
"A") && pList.isParameter(
"B")) {
264 string pA = pList.get<
string>(
"A");
265 if(this->sources.find(pA) == this->sources.end())
267 cout <<
"\nProblem: " + pA +
", was not saved for comparison.";
268 cout <<
"\nThis typically indicates that an error ";
269 cout <<
"occurred while running the problem.";
270 cout <<
"\nSolution comparison FAILED." << endl;
274 string pB = pList.get<
string>(
"B");
275 if(this->sources.find(pB) == this->sources.end()) {
276 cout <<
"\nProblem: " + pB +
", was not saved for comparison.";
277 cout <<
"\nThis typically indicates that an error ";
278 cout <<
"occurred while running the problem.";
279 cout <<
"\nSolution comparison FAILED." << endl;
283 bool bResult = this->CompareSolutions(pA, pB, comm);
286 else if (pList.isParameter(
"Problem") && pList.isParameter(
"Reference")) {
288 string prb = pList.get<
string>(
"Problem");
289 if(this->sources.find(prb) == this->sources.end()) {
290 cout <<
"\nProblem: " + prb +
", was not saved for comparison.";
291 cout <<
"\nThis typically indicates that an error ";
292 cout <<
"occurred while running the problem.";
293 cout <<
"\nMetric comparison FAILED." << endl;
297 string ref = pList.get<
string>(
"Reference");
298 if(this->sources.find(ref) == this->sources.end()) {
299 cout <<
"\nReference: " + ref +
", was not saved for comparison.";
300 cout <<
"\nThis typically indicates that an error ";
301 cout <<
"occurred while running the problem.";
302 cout <<
"\nMetric comparison FAILED." << endl;
306 bool bResult = this->CompareMetrics(pList, comm);
309 else if (pList.isParameter(
"A") || pList.isParameter(
"B"))
311 if(comm->getRank() == 0)
313 cout <<
"Problem A or Problem B is not specified -- check input.";
314 cout <<
"\nSolution comparison FAILED." << endl;
317 else if (pList.isParameter(
"Problem") || pList.isParameter(
"Reference")) {
318 if(comm->getRank() == 0) {
319 cout <<
"Problem or reference is not specified -- check input.";
320 cout <<
"\nMetric comparison FAILED." << endl;
324 if (comm->getRank() == 0) {
325 cout <<
"ComparisonHelper did not understand how to read the xml. ";
326 cout <<
"Test FAILED." << endl;
332 bool ComparisonHelper::CompareSolutions(
const string &p1,
334 const RCP<
const Comm<int> > &comm)
336 if(comm->getRank() == 0) printf(
"\nComparing: %s and %s\n",
337 p1.c_str(), p2.c_str());
338 auto A = this->sources[p1];
339 auto B = this->sources[p2];
340 if(A->problemFactory->getProblemName() != B->problemFactory->getProblemName()) {
341 cout <<
"Problem A and B are of a different kind and cannot be compared.";
342 cout <<
"\nSolution comparison FAILED." << endl;
345 if(A->problemFactory->getProblemName() ==
"partitioning") {
346 return this->ComparePartitionSolutions(A.getRawPtr(), B.getRawPtr(), comm);
348 else if(A->problemFactory->getProblemName() ==
"coloring") {
349 return this->CompareColoringSolutions(A.getRawPtr(), B.getRawPtr(), comm);
351 else if(A->problemFactory->getProblemName() ==
"ordering"){
352 return this->CompareOrderingSolutions(A.getRawPtr(), B.getRawPtr(), comm);
355 cout <<
"Problem kind: " << A->problemFactory->getProblemName() <<
356 " not recognized. Check spelling.";
357 cout <<
"\nSolution comparison FAILED." << endl;
363 void ComparisonHelper::reduceWithMessage(
const RCP<
const Comm<int> > &comm,
364 const std::string &msg_in,
366 std::ostringstream &msg) {
369 Teuchos::Ptr<int> global(&global_buff);
370 reduceAll<int,int>(*comm.get(), Teuchos::EReductionType::REDUCE_MAX,
371 local_status , global);
372 local_status = *global;
373 if (local_status == 1) {
378 const zpart_t * ComparisonHelper::getPartListView(
379 RCP<ProblemFactory> problemFactory)
const {
380 #define GET_PROBLEM_PARTS(adapterClass) \ 381 return (rcp_dynamic_cast<PartitioningProblem<adapterClass>>( \ 382 problemFactory->getProblem()))->getSolution().getPartListView(); 386 bool ComparisonHelper::ComparePartitionSolutions(
const ComparisonSource * sourceA,
388 const RCP<
const Comm<int> > &comm)
390 int rank = comm->getRank();
391 ostringstream status;
399 ComparisonHelper::reduceWithMessage(comm,
400 "Number of parts in Solution A != Solution B. \ 401 Partitioning solution comparison FAILED.",
406 i < sourceA->
adapterFactory->getMainAdapter()->getLocalNumIDs(); i++) {
410 ComparisonHelper::reduceWithMessage(comm,
411 "Solution sets A and B have different values for getPartListView(). " 412 "Solution comparison FAILED.", failed, status);
418 status <<
"Solution sets A and B are the same. ";
419 status <<
"Solution set comparison PASSED.";
423 cout << status.str() << endl;
425 return (failed == 0);
429 bool ComparisonHelper::CompareColoringSolutions(
const ComparisonSource * sourceA,
431 const RCP<
const Comm<int> > &comm)
433 int rank = comm->getRank();
434 ostringstream status;
476 status <<
"Solution sets A and B are the same. ";
477 status <<
"Solution set comparison PASSED.";
481 cout << status.str() << endl;
483 return (failed == 0);
486 bool ComparisonHelper::CompareOrderingSolutions(
const ComparisonSource * sourceA,
488 const RCP<
const Comm<int> > &comm)
490 int rank = comm->getRank();
491 ostringstream status;
497 status <<
"Solution sets A and B are the same. ";
498 status <<
"Solution set comparison PASSED.";
502 cout << status.str() << endl;
504 return (failed == 0);
508 void ComparisonHelper::loadMetricInfo(RCP<EvaluateFactory> evaluateFactory,
509 std::vector<MetricAnalyzerInfo> & metricInfo,
510 const ParameterList &metricsPlist) {
512 #define LOAD_METRIC_INFO(adapterClass, metricAnalyzerClass) \ 513 RCP<EvaluateBaseClass<adapterClass>> pCast = \ 514 rcp_dynamic_cast<EvaluateBaseClass<adapterClass>>(evaluateFactory->getEvaluateClass()); \ 515 if(pCast == Teuchos::null) throw std::logic_error( \ 516 "Bad evaluate class cast in loadMetricInfo!" ); \ 517 metricAnalyzerClass analyzer(pCast); \ 518 analyzer.LoadMetricInfo(metricInfo, metricsPlist.sublist("Metrics")); 520 #define LOAD_METRIC_INFO_PARTITIONING(adapterClass) \ 521 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluatePartition<adapterClass>) 523 #define LOAD_METRIC_INFO_ORDERING(adapterClass) \ 524 LOAD_METRIC_INFO(adapterClass, MetricAnalyzerEvaluateOrdering<adapterClass>) 526 if(evaluateFactory->getProblemName() ==
"partitioning") {
529 else if(evaluateFactory->getProblemName() ==
"ordering") {
533 throw std::logic_error(
534 "loadMetricInfo not implemented for this problem type!" );
539 bool ComparisonHelper::CompareMetrics(
const ParameterList &metricsPlist,
const RCP<
const Comm<int> > &comm)
541 int rank = comm->getRank();
544 const string prb_name = metricsPlist.get<
string>(
"Problem");
545 const string ref_name = metricsPlist.get<
string>(
"Reference");
547 cout <<
"\nMetric/Timer comparison of: " << prb_name <<
" and ";
548 cout << ref_name <<
" (reference source)\n";
552 RCP<const ComparisonSource> sourcePrb = this->sources[prb_name];
553 RCP<const ComparisonSource> sourceRef = this->sources[ref_name];
556 std::map< const string, const double> prb_timers = this->timerDataToMap(sourcePrb->timers);
557 std::map< const string, const double> ref_timers = this->timerDataToMap(sourceRef->timers);
560 std::queue<ParameterList> metrics = ComparisonHelper::getMetricsToCompare(metricsPlist);
563 int all_tests_pass = 1;
566 while(!metrics.empty()) {
569 metric_name = metrics.front().name();
571 if (metric_name ==
"Metrics") {
572 std::vector<MetricAnalyzerInfo> metricInfoSetPrb;
573 std::vector<MetricAnalyzerInfo> metricInfoSetRef;
575 loadMetricInfo(sourcePrb.get()->evaluateFactory, metricInfoSetPrb, metricsPlist);
576 loadMetricInfo(sourceRef.get()->evaluateFactory, metricInfoSetRef, metricsPlist);
581 for (
size_t n = 0; n < metricInfoSetPrb.size(); ++n) {
582 if(!ComparisonHelper::metricComparisonTest(comm, metricInfoSetPrb[n], metricInfoSetRef[n], metrics.front(), msg)) {
586 cout << msg.str() << endl;
590 else if(prb_timers.find(metric_name) != prb_timers.end() && ref_timers.find(metric_name) != ref_timers.end()) {
591 if(rank == 0) cout <<
"\ncomparing timer: " << metric_name << endl;
592 if(!ComparisonHelper::timerComparisonTest(comm,
593 prb_timers.at(metric_name),
594 ref_timers.at(metric_name),
595 metrics.front(), msg)) {
598 cout <<
"timer comparison test caused a FAILED event." << endl;
603 cout << msg.str() << endl;
611 if(all_tests_pass == 1) {
612 cout <<
"\nAll metric/timer comparisons PASSED." << endl;
615 cout <<
"\nMetric/timer metric comparisons FAILED." << endl;
619 return (all_tests_pass == 1);
622 std::map<const string, const double> ComparisonHelper::timerDataToMap(
const map<
const std::string, RCP<Time> > &timers)
624 typedef std::pair<const string,const double> pair_t;
625 std::map<const string, const double> time_data;
626 for (
auto &i : timers) {
627 time_data.insert(pair_t(i.first, i.second->totalElapsedTime()));
632 bool ComparisonHelper::metricComparisonTest(
const RCP<
const Comm<int> > &comm,
635 const Teuchos::ParameterList & metricPlist,
641 string test_name = metricPlist.name() +
" test";
642 double ref_value = ref_metric.
theValue;
645 if (ref_value == 0) {
646 throw std::logic_error(
"The parameter list had a 0 value for the reference value so a percentage cannot be calculated." );
648 double percentRatio = value / ref_value;
654 if (percentRatio < min) {
655 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";
659 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";
665 if (percentRatio > max) {
666 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";
670 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";
679 bool ComparisonHelper::timerComparisonTest(
const RCP<
const Comm<int> > &comm,
681 const double ref_time,
682 const Teuchos::ParameterList & metricPlist,
687 Teuchos::Ptr<double> global(&global_time);
689 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,time,global);
692 double global_ref_time;
693 Teuchos::Ptr<double> globalRef(&global_ref_time);
695 reduceAll<int, double>(*comm.get(),Teuchos::EReductionType::REDUCE_MAX,ref_time,globalRef);
700 string test_name = metricPlist.name() +
" test";
702 if (metricPlist.isParameter(
"lower")) {
703 double min = metricPlist.get<
double>(
"lower")*global_ref_time;
705 if (global_time < min) {
706 msg << test_name <<
" FAILED: Minimum time, " 708 "[s], less than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
712 msg << test_name <<
" PASSED: Minimum time, " 714 "[s], greater than specified allowable minimum time, " << min <<
"[s]"<<
".\n";
718 if (metricPlist.isParameter(
"upper" ) && pass !=
false) {
719 double max = metricPlist.get<
double>(
"upper") * global_ref_time;
720 if (global_time > max) {
721 msg << test_name <<
" FAILED: Maximum time, " 723 "[s], greater than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
727 msg << test_name <<
" PASSED: Maximum time, " 729 "[s], less than specified allowable maximum time, " << max <<
"[s]"<<
".\n";
736 std::queue<ParameterList> ComparisonHelper::getMetricsToCompare(
const ParameterList &pList)
739 std::queue<ParameterList> metrics;
740 for(
auto it = pList.begin(); it != pList.end(); ++it) {
741 if (pList.isSublist(it->first)) {
742 metrics.push(pList.sublist(it->first));
keep typedefs that commonly appear in many places localized
Returns a pointer to new test classes. Is not responsible for memory management!
void AddSource(const string &name, RCP< ComparisonSource > source)
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)
size_t getNumberOfSources() const
#define Z2_TEST_UPCAST(adptr, TEMPLATE_ACTION)
#define LOAD_METRIC_INFO_PARTITIONING(adapterClass)
RCP< EvaluateFactory > evaluateFactory
A class for comparing solutions, metrics, and timing data of Zoltan2 problems.
std::map< const std::string, RCP< Time > > timers
static const std::string pass
A class used to save problem solutions and timers.
std::string parameterDescription
void addTimer(const std::string &name)
Generate Adapter for testing purposes.
RCP< AdapterFactory > adapterFactory
#define GET_PROBLEM_PARTS(adapterClass)