Teuchos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Time/TimeMonitor_UnitTests.cpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 //
00005 //                    Teuchos: Common Tools Package
00006 //                 Copyright (2004) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 // @HEADER
00042 */
00043 
00044 #include "Teuchos_TimeMonitor.hpp"
00045 #include "Teuchos_DefaultComm.hpp"
00046 #include "Teuchos_UnitTestHarness.hpp"
00047 
00048 namespace {
00049 
00050   void func_time_monitor1()
00051   {
00052     TEUCHOS_FUNC_TIME_MONITOR("FUNC_TIME_MONITOR1");
00053   }
00054 
00055 
00056   void func_time_monitor2()
00057   {
00058     TEUCHOS_FUNC_TIME_MONITOR("FUNC_TIME_MONITOR2");
00059     {
00060       TEUCHOS_FUNC_TIME_MONITOR_DIFF("FUNC_TIME_MONITOR2_inner", inner);
00061     }
00062   }
00063 
00064   // Slowly compute the n-th Fibonacci number.  This gives timers
00065   // something to time.  Be careful not to make n too large, or you'll
00066   // run out of stack space.
00067   int
00068   fib (const int n)
00069   {
00070     if (n <= 0) {
00071       return 0;
00072     } else if (n == 1) {
00073       return 1;
00074     }
00075     else {
00076       // You should never compute the n-th Fibonacci number like this.
00077       // This is exponentially slow in n.  The point of using a slow
00078       // algorithm like this is to exercise timers.
00079       return fib (n-1) + fib (n-2);
00080     }
00081   }
00082 
00083   // Do a number of arithmetic operations proportional to n^3, in
00084   // order to have something to time.  Unlike fib() above, this
00085   // function shouldn't take up a lot of stack space.
00086   double
00087   slowLoop (const size_t n)
00088   {
00089     const double inc = 1 / static_cast<double> (n);
00090     double x = 1.0;
00091 
00092     for (size_t i = 0; i < n; ++i) {
00093       for (size_t j = 0; j < n; ++j) {
00094         for (size_t k = 0; k < n; ++k) {
00095           x = x + inc;
00096         }
00097       }
00098     }
00099     return x;
00100   }
00101 
00102 } // namespace (anonymous)
00103 
00104 
00105 namespace Teuchos {
00106   //
00107   // Basic TimeMonitor test: create and exercise a timer on all (MPI)
00108   // processes, and make sure that TimeMonitor::summarize() reports it.
00109   //
00110   TEUCHOS_UNIT_TEST( TimeMonitor, FUNC_TIME_MONITOR  )
00111   {
00112     using Teuchos::ParameterList;
00113     using Teuchos::parameterList;
00114     using Teuchos::RCP;
00115 
00116     func_time_monitor1 (); // Function to time.
00117 
00118     { // Repeat test for default output format.
00119       std::ostringstream oss;
00120       TimeMonitor::summarize (oss);
00121 
00122       // Echo summarize() output to the FancyOStream out (which is a
00123       // standard unit test argument).  Output should only appear in
00124       // show-all-test-details mode.
00125       out << oss.str () << std::endl;
00126 
00127       // Make sure that the timer's name shows up in the output.
00128       const size_t substr_i = oss.str ().find ("FUNC_TIME_MONITOR1");
00129       TEST_INEQUALITY(substr_i, std::string::npos);
00130     }
00131 
00132     { // Repeat test for YAML output, compact style.
00133       std::ostringstream oss;
00134       RCP<ParameterList> reportParams =
00135         parameterList (* (TimeMonitor::getValidReportParameters ()));
00136       reportParams->set ("Report format", "YAML");
00137       reportParams->set ("YAML style", "compact");
00138       TimeMonitor::report (oss, reportParams);
00139 
00140       // Echo output to the FancyOStream out (which is a standard unit
00141       // test argument).  Output should only appear in "show all test
00142       // details" mode.
00143       out << oss.str () << std::endl;
00144 
00145       // Make sure that the timer's name shows up in the output.
00146       const size_t substr_i = oss.str ().find ("FUNC_TIME_MONITOR1");
00147       TEST_INEQUALITY(substr_i, std::string::npos);
00148     }
00149 
00150     { // Repeat test for YAML output, spacious style.
00151       std::ostringstream oss;
00152       RCP<ParameterList> reportParams =
00153         parameterList (* (TimeMonitor::getValidReportParameters ()));
00154       reportParams->set ("Report format", "YAML");
00155       reportParams->set ("YAML style", "spacious");
00156       TimeMonitor::report (oss, reportParams);
00157 
00158       // Echo output to the FancyOStream out (which is a standard unit
00159       // test argument).  Output should only appear in "show all test
00160       // details" mode.
00161       out << oss.str () << std::endl;
00162 
00163       // Make sure that the timer's name shows up in the output.
00164       const size_t substr_i = oss.str ().find ("FUNC_TIME_MONITOR1");
00165       TEST_INEQUALITY(substr_i, std::string::npos);
00166     }
00167 
00168     // This sets up for the next unit test.
00169     TimeMonitor::clearCounters ();
00170   }
00171 
00172   //
00173   // Test correct quoting of labels for TimeMonitor's YAML output.
00174   //
00175   TEUCHOS_UNIT_TEST( TimeMonitor, YamlLabelQuoting )
00176   {
00177     using Teuchos::Array;
00178     using Teuchos::ParameterList;
00179     using Teuchos::parameterList;
00180     using Teuchos::RCP;
00181     using Teuchos::Time;
00182     typedef Array<std::string>::size_type size_type;
00183 
00184     Array<std::string> inputLabels, outputLabels;
00185 
00186     // Make sure to exercise things that don't need quoting, like
00187     // spaces and certain punctuation, as well as things that do need
00188     // quoting, like colons, inner double quotes, and backslashes.
00189     inputLabels.push_back ("NoQuotingNeeded");
00190     inputLabels.push_back ("No quoting needed");
00191     inputLabels.push_back ("\"AlreadyQuotedNoQuotingNeeded\"");
00192     inputLabels.push_back ("\"Already quoted, no quoting needed\"");
00193     inputLabels.push_back ("\"Already quoted: quoting needed\"");
00194     inputLabels.push_back ("NotQuoted:QuotingNeeded");
00195     inputLabels.push_back ("Not quoted: quoting needed");
00196     // Test both individual double quotes, and pairs of double quotes.
00197     inputLabels.push_back ("Not quoted \" quoting needed");
00198     inputLabels.push_back ("Not quoted \" \" quoting needed");
00199     inputLabels.push_back ("\"Already quoted \" quoting needed\"");
00200     inputLabels.push_back ("\"Already quoted \" \" quoting needed\"");
00201     // Remember that in C strings, a double backslash turns into a
00202     // single backslash.  Our YAML output routine should turn each
00203     // single backslash back into a double backslash.
00204     inputLabels.push_back ("Not quoted \\ quoting needed");
00205     inputLabels.push_back ("Not quoted \\\\ quoting needed");
00206     inputLabels.push_back ("Not quoted \\ \\ quoting needed");
00207     inputLabels.push_back ("\"Already quoted \\ quoting needed\"");
00208     inputLabels.push_back ("\"Already quoted \\\\ quoting needed\"");
00209     inputLabels.push_back ("\"Already quoted \\ \\ quoting needed\"");
00210 
00211     outputLabels.push_back ("NoQuotingNeeded");
00212     outputLabels.push_back ("No quoting needed");
00213     outputLabels.push_back ("\"AlreadyQuotedNoQuotingNeeded\"");
00214     outputLabels.push_back ("\"Already quoted, no quoting needed\"");
00215     outputLabels.push_back ("\"Already quoted: quoting needed\"");
00216     outputLabels.push_back ("\"NotQuoted:QuotingNeeded\"");
00217     outputLabels.push_back ("\"Not quoted: quoting needed\"");
00218     outputLabels.push_back ("\"Not quoted \\\" quoting needed\"");
00219     outputLabels.push_back ("\"Not quoted \\\" \\\" quoting needed\"");
00220     outputLabels.push_back ("\"Already quoted \\\" quoting needed\"");
00221     outputLabels.push_back ("\"Already quoted \\\" \\\" quoting needed\"");
00222     outputLabels.push_back ("\"Not quoted \\\\ quoting needed\"");
00223     outputLabels.push_back ("\"Not quoted \\\\\\\\ quoting needed\"");
00224     outputLabels.push_back ("\"Not quoted \\\\ \\\\ quoting needed\"");
00225     outputLabels.push_back ("\"Already quoted \\\\ quoting needed\"");
00226     outputLabels.push_back ("\"Already quoted \\\\\\\\ quoting needed\"");
00227     outputLabels.push_back ("\"Already quoted \\\\ \\\\ quoting needed\"");
00228 
00229     // Sanity check.
00230     TEUCHOS_TEST_FOR_EXCEPTION(
00231       inputLabels.size () != outputLabels.size (),
00232       std::logic_error,
00233       "The number of input labels is different than the number of output labels."
00234       "  Please ask a Teuchos developer to make sure that every test input "
00235       "label has a corresponding output label.");
00236 
00237     Array<RCP<Time> > timers;
00238     for (size_type i = 0; i < inputLabels.size (); ++i) {
00239       timers.push_back (TimeMonitor::getNewCounter (inputLabels[i]));
00240     }
00241 
00242     // The actual number of operations in the loop is proportional to
00243     // the cube of the loop length.  Adjust the quantities below as
00244     // necessary to ensure the timer reports a nonzero elapsed time
00245     // for each of the invocations.
00246     const size_t loopLength = 25;
00247     for (int k = 0; k < 3; ++k) {
00248       for (size_type i = 0; i < timers.size (); ++i) {
00249         TimeMonitor timeMon (* timers[i]);
00250         slowLoop (loopLength);
00251       }
00252     }
00253 
00254     { // YAML output, compact style.
00255       std::ostringstream oss;
00256       RCP<ParameterList> reportParams =
00257         parameterList (* (TimeMonitor::getValidReportParameters ()));
00258       reportParams->set ("Report format", "YAML");
00259       reportParams->set ("YAML style", "compact");
00260       TimeMonitor::report (oss, reportParams);
00261 
00262       // Echo output to the FancyOStream out (which is a standard unit
00263       // test argument).  Output should only appear in "show all test
00264       // details" mode.
00265       out << oss.str () << std::endl;
00266 
00267       // Make sure that all timer labels appear correctly in the output.
00268       for (size_type i = 0; i < inputLabels.size(); ++i) {
00269         const size_t pos = oss.str ().find (outputLabels[i]);
00270         TEST_INEQUALITY(pos, std::string::npos);
00271       }
00272     }
00273 
00274     { // YAML output, spacious style.
00275       std::ostringstream oss;
00276       RCP<ParameterList> reportParams =
00277         parameterList (* (TimeMonitor::getValidReportParameters ()));
00278       reportParams->set ("Report format", "YAML");
00279       reportParams->set ("YAML style", "spacious");
00280       TimeMonitor::report (oss, reportParams);
00281 
00282       // Echo output to the FancyOStream out (which is a standard unit
00283       // test argument).  Output should only appear in "show all test
00284       // details" mode.
00285       out << oss.str () << std::endl;
00286 
00287       // Make sure that all timer labels appear correctly in the output.
00288       for (size_type i = 0; i < inputLabels.size(); ++i) {
00289         const size_t pos = oss.str ().find (outputLabels[i]);
00290         TEST_INEQUALITY(pos, std::string::npos);
00291       }
00292     }
00293 
00294     // This sets up for the next unit test.
00295     TimeMonitor::clearCounters ();
00296   }
00297 
00298 
00299   //
00300   // Test filtering of timer labels.
00301   //
00302   TEUCHOS_UNIT_TEST( TimeMonitor, TimerLabelFiltering )
00303   {
00304     using Teuchos::Array;
00305     using Teuchos::ParameterList;
00306     using Teuchos::parameterList;
00307     using Teuchos::RCP;
00308     using Teuchos::Time;
00309     typedef Array<std::string>::size_type size_type;
00310 
00311     // Filters to use in the test.
00312     Array<std::string> filters;
00313     filters.push_back ("Foo:");
00314     filters.push_back ("Bar:");
00315     filters.push_back ("Baz:");
00316 
00317     // All the timer labels.
00318     Array<std::string> labels;
00319     labels.push_back ("Foo: timer 1");
00320     labels.push_back ("Foo: timer 2");
00321     labels.push_back ("Foo: timer 3");
00322     labels.push_back ("Bar: timer 1");
00323     labels.push_back ("Bar: timer 2");
00324     labels.push_back ("Baz: timer 1");
00325     labels.push_back ("Xyzzy");
00326     labels.push_back ("This is not a pipe");
00327     labels.push_back ("You should not see this");
00328 
00329     Array<Array<std::string> > outLabels (3);
00330     // Label(s) that should be printed for filters[0]
00331     outLabels[0].push_back ("Foo: timer 1");
00332     outLabels[0].push_back ("Foo: timer 2");
00333     outLabels[0].push_back ("Foo: timer 3");
00334     // Label(s) that should be printed for filters[1]
00335     outLabels[1].push_back ("Bar: timer 1");
00336     outLabels[1].push_back ("Bar: timer 2");
00337     // Label(s) that should be printed for filters[2]
00338     outLabels[2].push_back ("Baz: timer 1");
00339 
00340     // Labels that should not be printed for any of the filters below.
00341     Array<std::string> otherLabels;
00342     otherLabels.push_back ("Xyzzy");
00343     otherLabels.push_back ("This is not a pipe");
00344     otherLabels.push_back ("You should not see this");
00345 
00346     Array<RCP<Time> > timers;
00347     for (size_type i = 0; i < labels.size (); ++i) {
00348       timers.push_back (TimeMonitor::getNewCounter (labels[i]));
00349     }
00350 
00351     // The actual number of operations in the loop is proportional to
00352     // the cube of the loop length.  Adjust the quantities below as
00353     // necessary to ensure the timer reports a nonzero elapsed time
00354     // for each of the invocations.
00355     const size_t loopLength = 25;
00356     for (int k = 0; k < 3; ++k) {
00357       for (size_type i = 0; i < timers.size (); ++i) {
00358         TimeMonitor timeMon (* timers[i]);
00359         slowLoop (loopLength);
00360       }
00361     }
00362 
00363     try {
00364       // FIXME (mfh 21 Aug 2012) We don't yet have a test ensuring that
00365       // the filter only selects at the beginning of the timer label.
00366 
00367       // Test for each filter.
00368       for (size_type i = 0; i < filters.size (); ++i) {
00369         { // Default (tabular) output format.
00370           std::ostringstream oss;
00371           RCP<ParameterList> reportParams =
00372             parameterList (* (TimeMonitor::getValidReportParameters ()));
00373           TimeMonitor::report (oss, filters[i], reportParams);
00374 
00375           // Echo output to the FancyOStream out (which is a standard unit
00376           // test argument).  Output should only appear in "show all test
00377           // details" mode.
00378           out << oss.str () << std::endl;
00379 
00380           // Check whether the labels that were supposed to be printed
00381           // were actually printed.
00382           for (size_type j = 0; j < outLabels[i].size(); ++j) {
00383             const size_t pos = oss.str ().find (outLabels[i][j]);
00384             TEST_INEQUALITY(pos, std::string::npos);
00385           }
00386 
00387           // Check whether the labels that were _not_ supposed to be
00388           // printed were actually printed.
00389           //
00390           // First, check the labels that should only be printed with
00391           // the other filters.
00392           for (size_type ii = 0; ii < outLabels.size(); ++ii) {
00393             if (ii != i) {
00394               for (size_type j = 0; j < outLabels[ii].size(); ++j) {
00395                 const size_t pos = oss.str ().find (outLabels[ii][j]);
00396                 TEST_EQUALITY(pos, std::string::npos);
00397               }
00398             }
00399           }
00400           // Next, check the labels that should not be printed for any
00401           // filters.
00402           for (size_type j = 0; j < otherLabels.size(); ++j) {
00403             const size_t pos = oss.str ().find (otherLabels[j]);
00404             TEST_EQUALITY(pos, std::string::npos);
00405           }
00406         }
00407 
00408         { // YAML output, compact style.
00409           std::ostringstream oss;
00410           RCP<ParameterList> reportParams =
00411             parameterList (* (TimeMonitor::getValidReportParameters ()));
00412           reportParams->set ("Report format", "YAML");
00413           reportParams->set ("YAML style", "compact");
00414           TimeMonitor::report (oss, filters[i], reportParams);
00415 
00416           // Echo output to the FancyOStream out (which is a standard unit
00417           // test argument).  Output should only appear in "show all test
00418           // details" mode.
00419           out << oss.str () << std::endl;
00420 
00421           // Check whether the labels that were supposed to be printed
00422           // were actually printed.
00423           for (size_type j = 0; j < outLabels[i].size(); ++j) {
00424             const size_t pos = oss.str ().find (outLabels[i][j]);
00425             TEST_INEQUALITY(pos, std::string::npos);
00426           }
00427 
00428           // Check whether the labels that were _not_ supposed to be
00429           // printed were actually printed.
00430           //
00431           // First, check the labels that should only be printed with
00432           // the other filters.
00433           for (size_type ii = 0; ii < outLabels.size(); ++ii) {
00434             if (ii != i) {
00435               for (size_type j = 0; j < outLabels[ii].size(); ++j) {
00436                 const size_t pos = oss.str ().find (outLabels[ii][j]);
00437                 TEST_EQUALITY(pos, std::string::npos);
00438               }
00439             }
00440           }
00441           // Next, check the labels that should not be printed for any
00442           // filters.
00443           for (size_type j = 0; j < otherLabels.size(); ++j) {
00444             const size_t pos = oss.str ().find (otherLabels[j]);
00445             TEST_EQUALITY(pos, std::string::npos);
00446           }
00447         }
00448 
00449         { // YAML output, spacious style.
00450           std::ostringstream oss;
00451           RCP<ParameterList> reportParams =
00452             parameterList (* (TimeMonitor::getValidReportParameters ()));
00453           reportParams->set ("Report format", "YAML");
00454           reportParams->set ("YAML style", "spacious");
00455           TimeMonitor::report (oss, filters[i], reportParams);
00456 
00457           // Echo output to the FancyOStream out (which is a standard unit
00458           // test argument).  Output should only appear in "show all test
00459           // details" mode.
00460           out << oss.str () << std::endl;
00461 
00462           // Check whether the labels that were supposed to be printed
00463           // were actually printed.
00464           for (size_type j = 0; j < outLabels[i].size(); ++j) {
00465             const size_t pos = oss.str ().find (outLabels[i][j]);
00466             TEST_INEQUALITY(pos, std::string::npos);
00467           }
00468 
00469           // Check whether the labels that were _not_ supposed to be
00470           // printed were actually printed.
00471           //
00472           // First, check the labels that should only be printed with
00473           // the other filters.
00474           for (size_type ii = 0; ii < outLabels.size(); ++ii) {
00475             if (ii != i) {
00476               for (size_type j = 0; j < outLabels[ii].size(); ++j) {
00477                 const size_t pos = oss.str ().find (outLabels[ii][j]);
00478                 TEST_EQUALITY(pos, std::string::npos);
00479               }
00480             }
00481           }
00482           // Next, check the labels that should not be printed for any
00483           // filters.
00484           for (size_type j = 0; j < otherLabels.size(); ++j) {
00485             const size_t pos = oss.str ().find (otherLabels[j]);
00486             TEST_EQUALITY(pos, std::string::npos);
00487           }
00488         }
00489       }
00490     }
00491     catch (...) {
00492       // Make sure to clear the counters, so that they don't pollute
00493       // the remaining tests.  (The Teuchos unit test framework may
00494       // catch any exceptions that the above code throws, but allow
00495       // the remaining tests to continue.)
00496       TimeMonitor::clearCounters ();
00497       throw;
00498     }
00499 
00500     // This sets up for the next unit test.
00501     TimeMonitor::clearCounters ();
00502   }
00503 
00504 
00505 
00506   //
00507   // TimeMonitor nested timers test: create two timers on all (MPI)
00508   // processes, use the second inside the scope of the first, and make
00509   // sure that TimeMonitor::summarize() reports both timers.
00510   //
00511   TEUCHOS_UNIT_TEST( TimeMonitor, FUNC_TIME_MONITOR_tested  )
00512   {
00513     using Teuchos::ParameterList;
00514     using Teuchos::parameterList;
00515     using Teuchos::RCP;
00516 
00517     func_time_monitor2 ();
00518 
00519     {
00520       std::ostringstream oss;
00521       TimeMonitor::summarize (oss);
00522 
00523       // Echo summarize() output to the FancyOStream out (which is a
00524       // standard unit test argument).  Output should only appear in
00525       // show-all-test-details mode.
00526       out << oss.str() << std::endl;
00527 
00528       const size_t substr_i = oss.str().find ("FUNC_TIME_MONITOR2");
00529       TEST_INEQUALITY(substr_i, std::string::npos);
00530       const size_t substr_inner_i = oss.str().find ("FUNC_TIME_MONITOR2_inner");
00531       TEST_INEQUALITY(substr_inner_i, std::string::npos);
00532     }
00533 
00534     { // Repeat test for YAML output, compact style.
00535       std::ostringstream oss;
00536       RCP<ParameterList> reportParams =
00537         parameterList (* (TimeMonitor::getValidReportParameters ()));
00538       reportParams->set ("Report format", "YAML");
00539       reportParams->set ("YAML style", "compact");
00540       TimeMonitor::report (oss, reportParams);
00541 
00542       // Echo output to the FancyOStream out (which is a standard unit
00543       // test argument).  Output should only appear in "show all test
00544       // details" mode.
00545       out << oss.str () << std::endl;
00546 
00547       const size_t substr_i = oss.str().find ("FUNC_TIME_MONITOR2");
00548       TEST_INEQUALITY(substr_i, std::string::npos);
00549       const size_t substr_inner_i = oss.str().find ("FUNC_TIME_MONITOR2_inner");
00550       TEST_INEQUALITY(substr_inner_i, std::string::npos);
00551     }
00552 
00553     { // Repeat test for YAML output, spacious style.
00554       std::ostringstream oss;
00555       RCP<ParameterList> reportParams =
00556         parameterList (* (TimeMonitor::getValidReportParameters ()));
00557       reportParams->set ("Report format", "YAML");
00558       reportParams->set ("YAML style", "spacious");
00559       TimeMonitor::report (oss, reportParams);
00560 
00561       // Echo output to the FancyOStream out (which is a standard unit
00562       // test argument).  Output should only appear in "show all test
00563       // details" mode.
00564       out << oss.str () << std::endl;
00565 
00566       const size_t substr_i = oss.str().find ("FUNC_TIME_MONITOR2");
00567       TEST_INEQUALITY(substr_i, std::string::npos);
00568       const size_t substr_inner_i = oss.str().find ("FUNC_TIME_MONITOR2_inner");
00569       TEST_INEQUALITY(substr_inner_i, std::string::npos);
00570     }
00571 
00572     // This sets up for the next unit test.
00573     TimeMonitor::clearCounters ();
00574   }
00575 
00576   //
00577   // Test whether TimeMonitor::summarize() does the right thing when
00578   // different MPI processes create different sets of timers.  This
00579   // test is only meaningful if running with more than one MPI
00580   // process, but it should also pass if running in a non-MPI build or
00581   // with only one MPI process.
00582   //
00583   TEUCHOS_UNIT_TEST( TimeMonitor, SUMMARIZE_diffTimerSets )
00584   {
00585     RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
00586     const int numProcs = comm->getSize ();
00587     const int myRank = comm->getRank ();
00588 
00589     // If MPI has not been initialized, turn the MPI communicator into
00590     // a "serial" communicator.  This may not be necessary when using
00591     // the Teuchos Unit Test Framework.
00592 #ifdef HAVE_MPI
00593     {
00594       int mpiHasBeenInitialized = 0;
00595       MPI_Initialized (&mpiHasBeenInitialized);
00596       if (! mpiHasBeenInitialized) {
00597         comm = Teuchos::DefaultComm<int>::getDefaultSerialComm (null);
00598       }
00599     }
00600 #endif // HAVE_MPI
00601 
00602     // Store the output of TimeMonitor::summarize() here.
00603     std::ostringstream oss;
00604 
00605     // Timer A gets created on all MPI processes.
00606     // Timer B only gets created on Proc 0.
00607     RCP<Time> timerA = TimeMonitor::getNewCounter ("Timer A");
00608     RCP<Time> timerB;
00609     if (myRank == 0) {
00610       timerB = TimeMonitor::getNewCounter ("Timer B");
00611     }
00612     else {
00613       timerB = null; // True anyway, but I want to make this explicit.
00614     }
00615 
00616     // The actual number of operations in the loop is proportional to
00617     // the cube of the loop length.  Adjust the quantities below as
00618     // necessary to ensure the timer reports a nonzero elapsed time
00619     // for each of the invocations.
00620     const size_t timerA_loopLength = 150;
00621     const size_t timerB_loopLength = 200;
00622 
00623     // Timer A gets a call count of 3.
00624     for (size_t k = 0; k < 3; ++k) {
00625       TimeMonitor monitorA (*timerA);
00626       slowLoop (timerA_loopLength);
00627     }
00628     if (myRank == 0) { // Timer B gets a call count of 1 on Proc 0.
00629       TimeMonitor monitorB (*timerB);
00630       slowLoop (timerB_loopLength);
00631     }
00632 
00633     const bool alwaysWriteLocal = false; // the default
00634     const bool writeGlobalStats = true;  // the default
00635     const bool writeZeroTimers = true;  // the default
00636     TimeMonitor::summarize (oss, alwaysWriteLocal, writeGlobalStats,
00637                             writeZeroTimers, Intersection);
00638 
00639     // Echo summarize() output to the FancyOStream out (which is a
00640     // standard unit test argument).  Output should only appear in
00641     // show-all-test-details mode.
00642     out << std::endl << "Testing intersection of timers:" << std::endl
00643         << oss.str() << std::endl;
00644 
00645     // Since setOp == Intersection, only Timer A should be reported,
00646     // unless there is only one (MPI) process.
00647     size_t substr_i = oss.str().find ("Timer A");
00648     TEST_INEQUALITY(substr_i, std::string::npos);
00649     if (numProcs > 1) {
00650       substr_i = oss.str().find ("Timer B");
00651       TEST_EQUALITY(substr_i, std::string::npos);
00652     }
00653 
00654     // Now call summarize(), but ask for a union of timers.
00655     std::ostringstream ossUnion;
00656     TimeMonitor::summarize (ossUnion, alwaysWriteLocal, writeGlobalStats,
00657                             writeZeroTimers, Union);
00658 
00659     // Echo summarize() output to the FancyOStream out (which is a
00660     // standard unit test argument).  Output should only appear in
00661     // show-all-test-details mode.
00662     out << std::endl << "Testing union of timers:" << std::endl
00663         << ossUnion.str() << std::endl;
00664 
00665     // Since setOp == Union, both Timer A and Timer B should be
00666     // reported.
00667     substr_i = ossUnion.str().find ("Timer A");
00668     TEST_INEQUALITY(substr_i, std::string::npos);
00669     substr_i = ossUnion.str().find ("Timer B");
00670     TEST_INEQUALITY(substr_i, std::string::npos);
00671 
00672     // This sets up for the next unit test.
00673     TimeMonitor::clearCounters ();
00674   }
00675 
00676   //
00677   // Test whether the option to filter out zero timers works, for the
00678   // case that all (MPI) processes have the same call counts.
00679   //
00680   TEUCHOS_UNIT_TEST( TimeMonitor, FILTER_ZERO_TIMERS_sameParallelCallCounts )
00681   {
00682     // Store the output of TimeMonitor::summarize() here.
00683     std::ostringstream oss;
00684 
00685     RCP<Time> timerA = TimeMonitor::getNewCounter ("Timer A");
00686     RCP<Time> timerB = TimeMonitor::getNewCounter ("Timer B");
00687     RCP<Time> timerC = TimeMonitor::getNewCounter ("Timer C");
00688 
00689     // Timers A and B get nonzero elapsed times and call counts on all
00690     // (MPI) processes.  Timer C never gets started, so it should have
00691     // a zero elapsed time and zero call count on all processes.
00692 
00693     // The actual number of operations in the loop is proportional to
00694     // the cube of the loop length.  Adjust the quantities below as
00695     // necessary to ensure the timer reports a nonzero elapsed time
00696     // for each of the invocations.
00697     const size_t timerA_loopLength = 200;
00698     const size_t timerB_loopLength = 250;
00699 
00700     // Timer A gets a call count of 3.
00701     for (size_t k = 0; k < 3; ++k) {
00702       TimeMonitor monitorA (*timerA);
00703       slowLoop (size_t (timerA_loopLength));
00704     }
00705     // Timer B gets a call count of 1.
00706     {
00707       TimeMonitor monitorB (*timerB);
00708       slowLoop (size_t (timerB_loopLength));
00709     }
00710 
00711     const bool alwaysWriteLocal = false; // the default
00712     const bool writeGlobalStats = true;  // the default
00713     const bool writeZeroTimers = false;  // NOT the default
00714     TimeMonitor::summarize (oss, alwaysWriteLocal, writeGlobalStats,
00715                             writeZeroTimers);
00716 
00717     // Echo summarize() output to the FancyOStream out (which is a
00718     // standard unit test argument).  Output should only appear in
00719     // show-all-test-details mode.
00720     out << oss.str() << std::endl;
00721 
00722     // Timers A and B should be reported.
00723     size_t substr_i = oss.str().find ("Timer A");
00724     TEST_INEQUALITY(substr_i, std::string::npos);
00725     substr_i = oss.str().find ("Timer B");
00726     TEST_INEQUALITY(substr_i, std::string::npos);
00727 
00728     // Timer C should NOT be reported.
00729     substr_i = oss.str().find ("Timer C");
00730     TEST_EQUALITY(substr_i, std::string::npos);
00731 
00732     // This sets up for the next unit test.
00733     TimeMonitor::clearCounters ();
00734   }
00735 
00736 
00737   //
00738   // Test whether the option to filter out zero timers works, for the
00739   // case that different (MPI) processes have different call counts.
00740   //
00741   TEUCHOS_UNIT_TEST( TimeMonitor, FILTER_ZERO_TIMERS_differentParallelCallCounts )
00742   {
00743     RCP<const Comm<int> > comm = Teuchos::DefaultComm<int>::getComm ();
00744     const int myRank = comm->getRank ();
00745 
00746     // If MPI has not been initialized, turn the MPI communicator into
00747     // a "serial" communicator.  This may not be necessary when using
00748     // the Teuchos Unit Test Framework.
00749 #ifdef HAVE_MPI
00750     {
00751       int mpiHasBeenInitialized = 0;
00752       MPI_Initialized (&mpiHasBeenInitialized);
00753       if (! mpiHasBeenInitialized) {
00754         comm = Teuchos::DefaultComm<int>::getDefaultSerialComm (null);
00755       }
00756     }
00757 #endif // HAVE_MPI
00758 
00759     // Store the output of TimeMonitor::summarize() here.
00760     std::ostringstream oss;
00761 
00762     RCP<Time> timerA = TimeMonitor::getNewCounter ("Timer A");
00763     RCP<Time> timerB = TimeMonitor::getNewCounter ("Timer B");
00764     RCP<Time> timerC = TimeMonitor::getNewCounter ("Timer C");
00765 
00766     // Timer A gets a nonzero elapsed time and call count on Proc 0,
00767     // but a zero elapsed time and call count elsewhere.
00768     //
00769     // Timer B gets the same nonzero elapsed time and call count on
00770     // all MPI procs.
00771     //
00772     // Timer C gets a zero elapsed time and call count on all procs.
00773     //
00774     // The actual number of operations in the loop is proportional to
00775     // the cube of the loop length.  Adjust the quantities below as
00776     // necessary to ensure the timer reports a nonzero elapsed time
00777     // for each of the invocations.
00778     const size_t timerA_loopLength = 200;
00779     const size_t timerB_loopLength = 500;
00780 
00781     if (myRank == 0) {
00782       // Timer A gets a call count of 3 on Proc 0.
00783       for (int k = 0; k < 3; ++k) {
00784         TimeMonitor monitorA (*timerA);
00785         slowLoop (size_t (timerA_loopLength));
00786       }
00787     }
00788 
00789     // Timer B gets a call count of 1 on all procs.
00790     {
00791       TimeMonitor monitorB (*timerB);
00792       slowLoop (size_t (timerB_loopLength));
00793     }
00794 
00795     const bool alwaysWriteLocal = false; // the default
00796     const bool writeGlobalStats = true;  // the default
00797     const bool writeZeroTimers = false;  // NOT the default
00798     TimeMonitor::summarize (oss, alwaysWriteLocal, writeGlobalStats,
00799                             writeZeroTimers, Union);
00800 
00801     // Echo summarize() output to the FancyOStream out (which is a
00802     // standard unit test argument).  Output should only appear in
00803     // show-all-test-details mode.
00804     out << oss.str() << std::endl;
00805 
00806     // Timers A and B should both be reported.
00807     size_t substr_i = oss.str().find ("Timer A");
00808     TEST_INEQUALITY(substr_i, std::string::npos);
00809     substr_i = oss.str().find ("Timer B");
00810     TEST_INEQUALITY(substr_i, std::string::npos);
00811 
00812     // Timer C should NOT be reported.
00813     substr_i = oss.str().find ("Timer C");
00814     TEST_EQUALITY(substr_i, std::string::npos);
00815 
00816     // This sets up for the next unit test (if there is one).
00817     TimeMonitor::clearCounters ();
00818   }
00819 
00820 
00821 } // namespace Teuchos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines