Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/tests/unit/SparseSketchApplyMixedTest.cpp
Go to the documentation of this file.
00001 
00013 #include <vector>
00014 
00015 #include <boost/mpi.hpp>
00016 #include <boost/test/minimal.hpp>
00017 
00018 //FIXME: ugly
00019 #define SKYLARK_SKETCH_HPP 1
00020 
00021 #include "../../utility/distributions.hpp"
00022 #include "../../base/context.hpp"
00023 #include "../../sketch/hash_transform.hpp"
00024 
00025 #include "../../base/sparse_matrix.hpp"
00026 
00027 typedef FullyDistVec<size_t, double> mpi_vector_t;
00028 typedef SpDCCols<size_t, double> col_t;
00029 typedef SpParMat<size_t, double, col_t> DistMatrixType;
00030 typedef PlusTimesSRing<double, double> PTDD;
00031 typedef skylark::base::sparse_matrix_t<double> LocalMatrixType;
00032 
00033 
00034 template < typename InputMatrixType,
00035            typename OutputMatrixType = InputMatrixType >
00036 struct Dummy_t : public skylark::sketch::hash_transform_t<
00037     InputMatrixType, OutputMatrixType,
00038     boost::random::uniform_int_distribution,
00039     skylark::utility::rademacher_distribution_t > {
00040 
00041     typedef skylark::sketch::hash_transform_t<
00042         InputMatrixType, OutputMatrixType,
00043         boost::random::uniform_int_distribution,
00044         skylark::utility::rademacher_distribution_t >
00045             hash_t;
00046 
00047     Dummy_t(int N, int S, skylark::base::context_t& context)
00048         : skylark::sketch::hash_transform_t<InputMatrixType, OutputMatrixType,
00049           boost::random::uniform_int_distribution,
00050           skylark::utility::rademacher_distribution_t>(N, S, context)
00051     {}
00052 
00053     std::vector<size_t> getRowIdx() { return hash_t::row_idx; }
00054     std::vector<double> getRowValues() { return hash_t::row_value; }
00055 };
00056 
00057 
00058 template<typename sketch_t>
00059 void compute_sketch_matrix(sketch_t sketch, const DistMatrixType &A,
00060                            DistMatrixType &result) {
00061 
00062     std::vector<size_t> row_idx = sketch.getRowIdx();
00063     std::vector<double> row_val = sketch.getRowValues();
00064 
00065     // PI generated by random number gen
00066     size_t sketch_size = row_val.size();
00067     mpi_vector_t cols(sketch_size);
00068     mpi_vector_t rows(sketch_size);
00069     mpi_vector_t vals(sketch_size);
00070 
00071     for(size_t i = 0; i < sketch_size; ++i) {
00072         cols.SetElement(i, i);
00073         rows.SetElement(i, row_idx[i]);
00074         vals.SetElement(i, row_val[i]);
00075     }
00076 
00077     result = DistMatrixType(result.getnrow(), result.getncol(),
00078                             rows, cols, vals);
00079 }
00080 
00081 void compare_result(size_t rank, DistMatrixType &expected_A,
00082                     elem::DistMatrix<double, elem::STAR, elem::STAR> &result) {
00083 
00084     col_t &data = expected_A.seq();
00085     //FIXME: use comm_grid
00086     const size_t my_row_offset =
00087         static_cast<int>((static_cast<double>(expected_A.getnrow()) /
00088                 expected_A.getcommgrid()->GetGridRows())) *
00089                 expected_A.getcommgrid()->GetRankInProcCol(rank);
00090 
00091     const size_t my_col_offset =
00092         static_cast<int>((static_cast<double>(expected_A.getncol()) /
00093                 expected_A.getcommgrid()->GetGridCols())) *
00094                 expected_A.getcommgrid()->GetRankInProcRow(rank);
00095 
00096     for(typename col_t::SpColIter col = data.begcol();
00097         col != data.endcol(); col++) {
00098         for(typename col_t::SpColIter::NzIter nz = data.begnz(col);
00099             nz != data.endnz(col); nz++) {
00100 
00101             const size_t rowid = nz.rowid()  + my_row_offset;
00102             const size_t colid = col.colid() + my_col_offset;
00103             const double value = nz.value();
00104 
00105             if(value != result.GetLocal(rowid, colid))
00106                 BOOST_FAIL("Result of colwise (dist -> dist) application not as expected");
00107         }
00108     }
00109 
00110 }
00111 
00112 int test_main(int argc, char *argv[]) {
00113 
00115     //[> Parameters <]
00116 
00117     //FIXME: use random sizes?
00118     const size_t n   = 100;
00119     const size_t m   = 50;
00120     const size_t n_s = 60;
00121     const size_t m_s = 30;
00122 
00124     //[> Setup test <]
00125     namespace mpi = boost::mpi;
00126 
00127 #ifdef SKYLARK_HAVE_OPENMP
00128     int provided;
00129     MPI_Init_thread(&argc, &argv, MPI_THREAD_MULTIPLE, &provided);
00130 #endif
00131 
00132     mpi::environment env(argc, argv);
00133     mpi::communicator world;
00134     const size_t rank = world.rank();
00135 
00136     elem::Initialize(argc, argv);
00137     MPI_Comm mpi_world(world);
00138     elem::Grid grid(mpi_world);
00139 
00140     skylark::base::context_t context (0);
00141 
00142     double count = 1.0;
00143 
00144     const size_t matrix_full = n * m;
00145     mpi_vector_t colsf(matrix_full);
00146     mpi_vector_t rowsf(matrix_full);
00147     mpi_vector_t valsf(matrix_full);
00148 
00149     for(size_t i = 0; i < matrix_full; ++i) {
00150         colsf.SetElement(i, i % m);
00151         rowsf.SetElement(i, i / m);
00152         valsf.SetElement(i, count);
00153         count++;
00154     }
00155 
00156     DistMatrixType A(n, m, rowsf, colsf, valsf);
00157     mpi_vector_t zero;
00158 
00159     count = 1.0;
00160     elem::Matrix<double> local_A(n, m);
00161     for( size_t j = 0; j < local_A.Height(); j++ )
00162         for( size_t i = 0; i < local_A.Width(); i++ )
00163             local_A.Set(j, i, count++);
00164 
00165 
00167     //[> Column wise application DistSparseMatrix -> DistMatrix[MC/MR] <]
00168 
00169     typedef elem::DistMatrix<double> mcmr_target_t;
00170 
00171     //[> 1. Create the sketching matrix <]
00172     Dummy_t<DistMatrixType, mcmr_target_t> Sparse(n, n_s, context);
00173 
00174     //[> 2. Create space for the sketched matrix <]
00175     mcmr_target_t sketch_A(n_s, m, grid);
00176     elem::Zero(sketch_A);
00177 
00178     //[> 3. Apply the transform <]
00179     Sparse.apply(A, sketch_A, skylark::sketch::columnwise_tag());
00180 
00181     //[> 4. Build structure to compare <]
00182     // easier to check if all processors own result
00183     elem::DistMatrix<double, elem::STAR, elem::STAR> result = sketch_A;
00184 
00185     DistMatrixType pi_sketch(n_s, n, zero, zero, zero);
00186     compute_sketch_matrix(Sparse, A, pi_sketch);
00187     DistMatrixType expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(
00188             pi_sketch, A, false, false);
00189 
00190     compare_result(rank, expected_A, result);
00191 
00193     //[> Column wise application DistSparseMatrix -> DistMatrix[VC/*] <]
00194 
00195     typedef elem::DistMatrix<double, elem::VC, elem::STAR> vcs_target_t;
00196 
00197     //[> 1. Create the sketching matrix <]
00198     Dummy_t<DistMatrixType, vcs_target_t> SparseVC(n, n_s, context);
00199 
00200     //[> 2. Create space for the sketched matrix <]
00201     vcs_target_t sketch_A_vcs(n, n_s, grid);
00202     elem::Zero(sketch_A_vcs);
00203 
00204     //[> 3. Apply the transform <]
00205     SparseVC.apply(A, sketch_A_vcs, skylark::sketch::columnwise_tag());
00206 
00207     //[> 4. Build structure to compare <]
00208     // easier to check if all processors own result
00209     result = sketch_A_vcs;
00210 
00211     compute_sketch_matrix(SparseVC, A, pi_sketch);
00212     expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(
00213             pi_sketch, A, false, false);
00214 
00215     compare_result(rank, expected_A, result);
00216 
00217 #if 0
00218 
00219     //[> Column wise application DistSparseMatrix -> DistMatrix[*/*] <]
00220 
00221     typedef elem::DistMatrix<double, elem::STAR, elem::STAR> st_target_t;
00222 
00223     //[> 1. Create the sketching matrix <]
00224     Dummy_t<DistMatrixType, st_target_t> SparseST(n, n_s, context);
00225 
00226     //[> 2. Create space for the sketched matrix <]
00227     st_target_t sketch_A_st(n, n_s, grid);
00228     elem::Zero(sketch_A_st);
00229 
00230     //[> 3. Apply the transform <]
00231     SparseST.apply(A, sketch_A_st, skylark::sketch::columnwise_tag());
00232 
00233     //[> 4. Build structure to compare <]
00234     // easier to check if all processors own result
00235     result = sketch_A_st;
00236 
00237     compute_sketch_matrix(SparseVC, A, pi_sketch);
00238     expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(
00239             pi_sketch, A, false, false);
00240 
00241     compare_result(rank, expected_A, result);
00242 #endif
00243 
00245     //[> Column wise application DistSparseMatrix -> LocalDenseMatrix <]
00246 
00247     Dummy_t<DistMatrixType, elem::Matrix<double>> LocalSparse(n, n_s, context);
00248     elem::Matrix<double> local_sketch_A(n, n_s);
00249     elem::Zero(local_sketch_A);
00250     LocalSparse.apply(A, local_sketch_A, skylark::sketch::columnwise_tag());
00251 
00252     elem::Matrix<double> pi_sketch_l(n_s, n);
00253     elem::Zero(pi_sketch_l);
00254     elem::Matrix<double> expected_A_l(n_s, m);
00255     elem::Zero(expected_A_l);
00256 
00257     if(rank == 0) {
00258         // PI generated by random number gen
00259         std::vector<size_t> row_idx = LocalSparse.getRowIdx();
00260         std::vector<double> row_val = LocalSparse.getRowValues();
00261 
00262         int sketch_size = row_val.size();
00263         typename LocalMatrixType::coords_t coords;
00264 
00265         for(int i = 0; i < sketch_size; ++i)
00266             pi_sketch_l.Set(row_idx[i], i, row_val[i]);
00267 
00268         elem::Gemm(elem::NORMAL, elem::NORMAL, 1.0, pi_sketch_l, local_A,
00269                    0.0, expected_A_l);
00270 
00271         for(int col = 0; col < expected_A_l.Width(); col++) {
00272             for(int row = 0; row < expected_A_l.Height(); row++) {
00273                 if(local_sketch_A.Get(row, col) !=
00274                         expected_A_l.Get(row, col))
00275                     BOOST_FAIL("Result of local colwise application not as expected");
00276             }
00277         }
00278     }
00279 
00280 
00282     //[> Row wise application DistSparseMatrix -> DistMatrix[MC/MR] <]
00283 
00284     //[> 1. Create the sketching matrix <]
00285     Dummy_t<DistMatrixType, mcmr_target_t> Sparse_r(m, m_s, context);
00286 
00287     //[> 2. Create space for the sketched matrix <]
00288     mcmr_target_t sketch_A_r(n, m_s, grid);
00289     elem::Zero(sketch_A_r);
00290 
00291     //[> 3. Apply the transform <]
00292     Sparse_r.apply(A, sketch_A_r, skylark::sketch::rowwise_tag());
00293 
00294     //[> 4. Build structure to compare <]
00295     // easier to check if all processors own result
00296     result = sketch_A_r;
00297 
00298     DistMatrixType pi_sketch_r(m_s, m, zero, zero, zero);
00299     compute_sketch_matrix(Sparse_r, A, pi_sketch_r);
00300     pi_sketch_r.Transpose();
00301     DistMatrixType expected_AR = Mult_AnXBn_Synch<PTDD, double, col_t>(
00302             A, pi_sketch_r, false, false);
00303 
00304     compare_result(rank, expected_AR, result);
00305 
00307     //[> Row wise application DistSparseMatrix -> DistMatrix[VC/*] <]
00308 
00309     //[> 1. Create the sketching matrix <]
00310     Dummy_t<DistMatrixType, vcs_target_t> Sparse_r_vcs(m, m_s, context);
00311 
00312     //[> 2. Create space for the sketched matrix <]
00313     vcs_target_t sketch_A_r_vcs(n, m_s, grid);
00314     elem::Zero(sketch_A_r_vcs);
00315 
00316     //[> 3. Apply the transform <]
00317     Sparse_r_vcs.apply(A, sketch_A_r_vcs, skylark::sketch::rowwise_tag());
00318 
00319     //[> 4. Build structure to compare <]
00320     // easier to check if all processors own result
00321     result = sketch_A_r_vcs;
00322 
00323     pi_sketch_r.Transpose();
00324     compute_sketch_matrix(Sparse_r_vcs, A, pi_sketch_r);
00325     pi_sketch_r.Transpose();
00326     expected_AR = Mult_AnXBn_Synch<PTDD, double, col_t>(
00327             A, pi_sketch_r, false, false);
00328 
00329     compare_result(rank, expected_AR, result);
00330 
00332     //[> Row wise application DistSparseMatrix -> LocalDenseMatrix <]
00333 
00334     Dummy_t<DistMatrixType, elem::Matrix<double>> LocalSparse_r(m, m_s, context);
00335     elem::Matrix<double> local_sketch_A_r(n, m_s);
00336     elem::Zero(local_sketch_A_r);
00337     LocalSparse_r.apply(A, local_sketch_A_r, skylark::sketch::rowwise_tag());
00338 
00339     elem::Matrix<double> local_pi_sketch_r(m_s, m);
00340     elem::Zero(local_pi_sketch_r);
00341     elem::Matrix<double> expected_A_r(n, m_s);
00342     elem::Zero(expected_A_r);
00343 
00344     if(rank == 0) {
00345         // PI generated by random number gen
00346         std::vector<size_t> row_idx = LocalSparse_r.getRowIdx();
00347         std::vector<double> row_val = LocalSparse_r.getRowValues();
00348 
00349         int sketch_size = row_val.size();
00350         typename LocalMatrixType::coords_t coords;
00351 
00352         for(int i = 0; i < sketch_size; ++i)
00353             local_pi_sketch_r.Set(row_idx[i], i, row_val[i]);
00354 
00355         elem::Gemm(elem::NORMAL, elem::TRANSPOSE, 1.0, local_A, local_pi_sketch_r,
00356                    0.0, expected_A_r);
00357 
00358         for(int col = 0; col < expected_A_r.Width(); col++) {
00359             for(int row = 0; row < expected_A_r.Height(); row++) {
00360                 if(local_sketch_A_r.Get(row, col) !=
00361                         expected_A_r.Get(row, col))
00362                     BOOST_FAIL("Result of local rowwise application not as expected");
00363             }
00364         }
00365     }
00366 
00367     return 0;
00368 }