Skylark (Sketching Library)  0.1
/var/lib/jenkins/jobs/Skylark/workspace/tests/unit/SparseSketchApplyCombBLASTest.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 "../../base/context.hpp"
00022 #include "../../utility/distributions.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 
00082 int test_main(int argc, char *argv[]) {
00083 
00085     //[> Parameters <]
00086 
00087     //FIXME: use random sizes?
00088     const size_t n   = 200;
00089     const size_t m   = 100;
00090     const size_t n_s = 120;
00091     const size_t m_s = 60;
00092 
00094     //[> Setup test <]
00095     namespace mpi = boost::mpi;
00096     mpi::environment env(argc, argv);
00097     mpi::communicator world;
00098     const size_t rank = world.rank();
00099 
00100     skylark::base::context_t context (0);
00101 
00102     double count = 1.0;
00103 
00104     const size_t matrix_full = n * m;
00105     mpi_vector_t colsf(matrix_full);
00106     mpi_vector_t rowsf(matrix_full);
00107     mpi_vector_t valsf(matrix_full);
00108 
00109     for(size_t i = 0; i < matrix_full; ++i) {
00110         colsf.SetElement(i, i % m);
00111         rowsf.SetElement(i, i / m);
00112         valsf.SetElement(i, count);
00113         count++;
00114     }
00115 
00116     DistMatrixType A(n, m, rowsf, colsf, valsf);
00117 
00118 
00120     //[> Column wise application DistSparseMatrix -> DistSparseMatrix <]
00121 
00122     //[> 1. Create the sketching matrix <]
00123     Dummy_t<DistMatrixType, DistMatrixType> Sparse(n, n_s, context);
00124 
00125     //[> 2. Create space for the sketched matrix <]
00126     mpi_vector_t zero;
00127     DistMatrixType sketch_A(n_s, m, zero, zero, zero);
00128 
00129     //[> 3. Apply the transform <]
00130     Sparse.apply(A, sketch_A, skylark::sketch::columnwise_tag());
00131 
00132     //[> 4. Build structure to compare <]
00133     DistMatrixType pi_sketch(n_s, n, zero, zero, zero);
00134     compute_sketch_matrix(Sparse, A, pi_sketch);
00135     DistMatrixType expected_A = Mult_AnXBn_Synch<PTDD, double, col_t>(pi_sketch, A, false, false);
00136     if (!static_cast<bool>(expected_A == sketch_A))
00137         BOOST_FAIL("Result of colwise (dist -> dist) application not as expected");
00138 
00140     //[> Column wise application DistSparseMatrix -> LocalSparseMatrix <]
00141 
00142     Dummy_t<DistMatrixType, LocalMatrixType> LocalSparse(n, n_s, context);
00143     LocalMatrixType local_sketch_A;
00144     LocalSparse.apply(A, local_sketch_A, skylark::sketch::columnwise_tag());
00145 
00146     if(rank == 0) {
00147         std::vector<size_t> row_idx = LocalSparse.getRowIdx();
00148         std::vector<double> row_val = LocalSparse.getRowValues();
00149 
00150         // PI generated by random number gen
00151         int sketch_size = row_val.size();
00152         typename LocalMatrixType::coords_t coords;
00153         for(int i = 0; i < sketch_size; ++i) {
00154             typename LocalMatrixType::coord_tuple_t new_entry(row_idx[i], i, row_val[i]);
00155             coords.push_back(new_entry);
00156         }
00157 
00158         LocalMatrixType pi_sketch_l;
00159         pi_sketch_l.set(coords);
00160 
00161         typename LocalMatrixType::coords_t coords_new;
00162         const int* indptr = pi_sketch_l.indptr();
00163         const int* indices = pi_sketch_l.indices();
00164         const double* values = pi_sketch_l.locked_values();
00165 
00166         // multiply with vector where an entry has the value:
00167         //   col_idx + row_idx * m + 1.
00168         // See creation of A.
00169         for(int col = 0; col < pi_sketch_l.width(); col++) {
00170             for(int idx = indptr[col]; idx < indptr[col + 1]; idx++) {
00171                 for(int ccol = 0; ccol < m; ++ccol) {
00172                     typename LocalMatrixType::coord_tuple_t new_entry(indices[idx],
00173                             ccol, values[idx] * (ccol + col * m + 1));
00174                     coords_new.push_back(new_entry);
00175                 }
00176             }
00177         }
00178 
00179         LocalMatrixType expected_A_l;
00180         expected_A_l.set(coords_new, n_s, m);
00181 
00182         if (!static_cast<bool>(expected_A_l == local_sketch_A))
00183             BOOST_FAIL("Result of local colwise application not as expected");
00184     }
00185 
00186 
00188     //[> Row wise application DistSparseMatrix -> DistSparseMatrix <]
00189 
00190     //[> 1. Create the sketching matrix <]
00191     Dummy_t<DistMatrixType, DistMatrixType> Sparse_r(m, m_s, context);
00192 
00193     //[> 2. Create space for the sketched matrix <]
00194     DistMatrixType sketch_A_r(n, m_s, zero, zero, zero);
00195 
00196     //[> 3. Apply the transform <]
00197     Sparse_r.apply(A, sketch_A_r, skylark::sketch::rowwise_tag());
00198 
00199     //[> 4. Build structure to compare <]
00200     DistMatrixType pi_sketch_r(m_s, m, zero, zero, zero);
00201     compute_sketch_matrix(Sparse_r, A, pi_sketch_r);
00202     pi_sketch_r.Transpose();
00203     DistMatrixType expected_AR = PSpGEMM<PTDD>(A, pi_sketch_r);
00204 
00205     if (!static_cast<bool>(expected_AR == sketch_A_r))
00206         BOOST_FAIL("Result of rowwise (dist -> dist) application not as expected");
00207 
00208     return 0;
00209 }