Kokkos Node API and Local Linear Algebra Kernels Version of the Day
DefaultSparseOps_TestSparseOps.cpp
00001 //@HEADER
00002 // ************************************************************************
00003 //
00004 //          Kokkos: Node API and Parallel Node Kernels
00005 //              Copyright (2008) Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ************************************************************************
00040 //@HEADER
00041 
00042 #include <Teuchos_UnitTestHarness.hpp>
00043 
00044 #include "Kokkos_ConfigDefs.hpp"
00045 #include "Kokkos_DefaultNode.hpp"
00046 #include "Kokkos_DefaultSparseOps.hpp"
00047 #include "Kokkos_SeqSparseOps.hpp"
00048 #include "Kokkos_Version.hpp"
00049 #include "DefaultSparseOps_TestSparseOps.hpp"
00050 
00051 
00052 namespace {
00053   using Kokkos::DefaultNode;
00054   using Teuchos::arcp;
00055   using Teuchos::ArrayRCP;
00056   using Teuchos::null;
00057   using Teuchos::ParameterList;
00058   using Teuchos::parameterList;
00059   using Teuchos::RCP;
00060   using Teuchos::rcp;
00061 
00062   //
00063   // mfh 28 Jun 2012: scalar_type, ordinal_type, and node_type are the
00064   // template parameters of interest for Kokkos local sparse kernels.
00065   // In practice, ordinal_type is usually int, and always should be a
00066   // signed integer type.  You may want to modify scalar_type if you
00067   // want to check correctness or performance of single-precision,
00068   // extended-precision, or complex arithmetic kernels.
00069   //
00070 
00071   typedef double scalar_type;
00072   typedef int ordinal_type;
00073   // mfh 28 Jun 2012: DefaultNodeType is usually TPINode, which may
00074   // start threads by default.  We use SerialNode to make absolutely
00075   // sure that this is a comparison of sequential kernels.
00076   //
00077   //typedef Kokkos::DefaultNode::DefaultNodeType node_type;
00078   typedef Kokkos::SerialNode node_type;
00079 
00080   typedef Teuchos::ScalarTraits<double> STM;
00081 
00082   //
00083   // Values of command-line arguments.
00084   //
00085   // CommandLineProcessor only accepts double for floating-point
00086   // values, and int for integer values, so we don't use scalar_type
00087   // or ordinal_type here.
00088 
00089   // If not "", then we assume this is the name of a Matrix Market -
00090   // format sparse matrix file to read.
00091   std::string matrixFilename;
00092   // The given tolerance allows some rounding error for triangular
00093   // solves, given that the test problems we generate should be well
00094   // conditioned on average.
00095   double tol = 1000 * Teuchos::ScalarTraits<double>::eps ();
00096   // Number of rows in the sparse matrices to test.
00097   int numRows = 100;
00098   // Number of columns in the sparse matrices to test.
00099   int numCols = 100;
00100   // Number of benchmark trials; timings are cumulative over all trials.
00101   int numTrials = 100;
00102   // If true, run the benchmark instead of the test.
00103   bool benchmark = false;
00104   // Number of columns in the multivectors to benchmark.
00105   // Must be at least as many as the number of rows.
00106   int numVecs = 1;
00107   // Number of threads for the Kokkos Node instance.  -1 means use the
00108   // default behavior.
00109   int numThreads = -1;
00110   // Kokkos Node instance initialization verbosity.
00111   // Only certain Node types support this option.
00112   bool verbose = false;
00113 
00114   // This will be set after reading the command-line arguments, so
00115   // that we can, for the particular Kokkos Node type, set things like
00116   // the number of threads to run.
00117   RCP<node_type> node;
00118 
00119   // Set up the extra command-line arguments.
00120   TEUCHOS_STATIC_SETUP()
00121   {
00122     Teuchos::CommandLineProcessor &clp = Teuchos::UnitTestRepository::getCLP ();
00123     clp.addOutputSetupOptions (true);
00124     clp.setOption ("matrixFilename", &matrixFilename, "If not \"\", the name "
00125                    "of a Matrix Market - format file from which to read the "
00126                    "sparse matrix A to benchmark or test.  If provided, we only"
00127                    "benchmark or test sparse mat-vec, not sparse triangular "
00128                    "solve.");
00129     clp.setOption ("numRows", &numRows, "Number of rows in the matrices to "
00130                    "test.  Ignored if a matrix file name is provided.");
00131     clp.setOption ("numCols", &numCols, "Number of columns in the matrices to "
00132                    "test.  Ignored if a matrix file name is provided.  We only "
00133                    "test sparse triangular solve if numRows == numCols.");
00134     clp.setOption ("tol", &tol, "Tolerance for relative error.");
00135     clp.setOption ("benchmark", "test", &benchmark, "Whether to run the "
00136                    "benchmark (if true) or the test (if false).");
00137     clp.setOption ("numTrials", &numTrials, "If running the benchmark: number "
00138                    "of benchmark trials.  Timings are cumulative over all "
00139                    "trials.");
00140     clp.setOption ("numVecs", &numVecs, "Number of columns in the multivectors "
00141                    "to benchmark.");
00142     clp.setOption ("numThreads", &numThreads, "Number of threads for the Kokkos "
00143                    "Node instance to use.  -1 means use the default behavior.");
00144     clp.setOption ("verbose", "quiet", &verbose, "Whether Kokkos Node "
00145                    "initialization should print verbose status output, if the "
00146                    "Node type supports this.");
00147 
00148     ParameterList nodeParams;
00149     if (numThreads != -1) {
00150       nodeParams.set ("Num Threads", numThreads);
00151     }
00152     nodeParams.set ("Verbose", verbose);
00153     node = rcp (new node_type (nodeParams));
00154   }
00155 
00156   //
00157   // UNIT TESTS
00158   //
00159 
00160   template<class SparseOpsType>
00161   class Tester {
00162   public:
00163     static void test (const std::string& sparseOpsTypeName) {
00164       TestSparseOps<SparseOpsType> tester;
00165       if (benchmark) {
00166         std::vector<std::pair<std::string, double> > results;
00167         if (matrixFilename == "") {
00168           tester.benchmarkSparseOps (results, sparseOpsTypeName, node,
00169                                      numRows, numCols, numVecs, numTrials);
00170         }
00171         else {
00172           tester.benchmarkSparseMatVecFromFile (results, matrixFilename,
00173                                                 sparseOpsTypeName, node,
00174                                                 numVecs, numTrials);
00175         }
00176       }
00177       else {
00178         tester.testSparseOps (node, numRows, numVecs, tol);
00179       }
00180     }
00181   };
00182 
00183   // Test sparse matrix-(multi)vector multiply and sparse triangular
00184   // solve, using DefaultHostSparseOps.
00185   TEUCHOS_UNIT_TEST( DefaultSparseOps, TestSparseOps )
00186   {
00187     using Kokkos::DefaultHostSparseOps;
00188     typedef DefaultHostSparseOps<scalar_type, ordinal_type, node_type> sparse_ops_type;
00189     Tester<sparse_ops_type>::test ("DefaultSparseHostOps");
00190   }
00191 
00192   // Test sparse matrix-(multi)vector multiply and sparse triangular solve.
00193   TEUCHOS_UNIT_TEST( SeqSparseOps, TestSparseOps )
00194   {
00195     using Kokkos::SeqSparseOps;
00196     typedef SeqSparseOps<scalar_type, ordinal_type, node_type> sparse_ops_type;
00197     Tester<sparse_ops_type>::test ("SeqSparseOps");
00198 
00199     if (benchmark) {
00200       // Summarize timing results.  You should only call summarize()
00201       // for all the different SparseOps types you plan to test in
00202       // this executable.
00203       //
00204       // Extra endline makes the summarize() output nicer.  In
00205       // benchmark mode, you should run with only one MPI process (if
00206       // building with MPI at all).  We don't plan to run benchmark
00207       // mode for the check-in or continuous integration tests.
00208       std::cout << "\n";
00209       Teuchos::TimeMonitor::summarize ();
00210     }
00211   }
00212 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends