|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
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
1.7.6.1