|  | 
 | // g++ -O3 -g0 -DNDEBUG  sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.005 -DSIZE=10000 && | 
 | // ./a.out g++ -O3 -g0 -DNDEBUG  sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.05 | 
 | // -DSIZE=2000 && ./a.out | 
 | //  -DNOGMM -DNOMTL -DCSPARSE | 
 | //  -I /home/gael/Coding/LinearAlgebra/CSparse/Include/ /home/gael/Coding/LinearAlgebra/CSparse/Lib/libcsparse.a | 
 |  | 
 | #include <typeinfo> | 
 |  | 
 | #ifndef SIZE | 
 | #define SIZE 1000000 | 
 | #endif | 
 |  | 
 | #ifndef NNZPERCOL | 
 | #define NNZPERCOL 6 | 
 | #endif | 
 |  | 
 | #ifndef REPEAT | 
 | #define REPEAT 1 | 
 | #endif | 
 |  | 
 | #include <algorithm> | 
 | #include "BenchTimer.h" | 
 | #include "BenchUtil.h" | 
 | #include "BenchSparseUtil.h" | 
 |  | 
 | #ifndef NBTRIES | 
 | #define NBTRIES 1 | 
 | #endif | 
 |  | 
 | #define BENCH(X)                          \ | 
 |   timer.reset();                          \ | 
 |   for (int _j = 0; _j < NBTRIES; ++_j) {  \ | 
 |     timer.start();                        \ | 
 |     for (int _k = 0; _k < REPEAT; ++_k) { \ | 
 |       X                                   \ | 
 |     }                                     \ | 
 |     timer.stop();                         \ | 
 |   } | 
 |  | 
 | // #ifdef MKL | 
 | // | 
 | // #include "mkl_types.h" | 
 | // #include "mkl_spblas.h" | 
 | // | 
 | // template<typename Lhs,typename Rhs,typename Res> | 
 | // void mkl_multiply(const Lhs& lhs, const Rhs& rhs, Res& res) | 
 | // { | 
 | //   char n = 'N'; | 
 | //   float alpha = 1; | 
 | //   char matdescra[6]; | 
 | //   matdescra[0] = 'G'; | 
 | //   matdescra[1] = 0; | 
 | //   matdescra[2] = 0; | 
 | //   matdescra[3] = 'C'; | 
 | //   mkl_scscmm(&n, lhs.rows(), rhs.cols(), lhs.cols(), &alpha, matdescra, | 
 | //              lhs._valuePtr(), lhs._innerIndexPtr(), lhs.outerIndexPtr(), | 
 | //              pntre, b, &ldb, &beta, c, &ldc); | 
 | // //   mkl_somatcopy('C', 'T', lhs.rows(), lhs.cols(), 1, | 
 | // //                 lhs._valuePtr(), lhs.rows(), DST, dst_stride); | 
 | // } | 
 | // | 
 | // #endif | 
 |  | 
 | #ifdef CSPARSE | 
 | cs* cs_sorted_multiply(const cs* a, const cs* b) { | 
 |   //   return cs_multiply(a,b); | 
 |  | 
 |   cs* A = cs_transpose(a, 1); | 
 |   cs* B = cs_transpose(b, 1); | 
 |   cs* D = cs_multiply(B, A); /* D = B'*A' */ | 
 |   cs_spfree(A); | 
 |   cs_spfree(B); | 
 |   cs_dropzeros(D);            /* drop zeros from D */ | 
 |   cs* C = cs_transpose(D, 1); /* C = D', so that C is sorted */ | 
 |   cs_spfree(D); | 
 |   return C; | 
 |  | 
 |   //   cs* A = cs_transpose(a, 1); | 
 |   //   cs* C = cs_transpose(A, 1); | 
 |   //   return C; | 
 | } | 
 |  | 
 | cs* cs_sorted_multiply2(const cs* a, const cs* b) { | 
 |   cs* D = cs_multiply(a, b); | 
 |   cs* E = cs_transpose(D, 1); | 
 |   cs_spfree(D); | 
 |   cs* C = cs_transpose(E, 1); | 
 |   cs_spfree(E); | 
 |   return C; | 
 | } | 
 | #endif | 
 |  | 
 | void bench_sort(); | 
 |  | 
 | int main(int argc, char* argv[]) { | 
 |   //   bench_sort(); | 
 |  | 
 |   int rows = SIZE; | 
 |   int cols = SIZE; | 
 |   float density = DENSITY; | 
 |  | 
 |   EigenSparseMatrix sm1(rows, cols), sm2(rows, cols), sm3(rows, cols), sm4(rows, cols); | 
 |  | 
 |   BenchTimer timer; | 
 |   for (int nnzPerCol = NNZPERCOL; nnzPerCol > 1; nnzPerCol /= 1.1) { | 
 |     sm1.setZero(); | 
 |     sm2.setZero(); | 
 |     fillMatrix2(nnzPerCol, rows, cols, sm1); | 
 |     fillMatrix2(nnzPerCol, rows, cols, sm2); | 
 |     //     std::cerr << "filling OK\n"; | 
 |  | 
 | // dense matrices | 
 | #ifdef DENSEMATRIX | 
 |     { | 
 |       std::cout << "Eigen Dense\t" << nnzPerCol << "%\n"; | 
 |       DenseMatrix m1(rows, cols), m2(rows, cols), m3(rows, cols); | 
 |       eiToDense(sm1, m1); | 
 |       eiToDense(sm2, m2); | 
 |  | 
 |       timer.reset(); | 
 |       timer.start(); | 
 |       for (int k = 0; k < REPEAT; ++k) m3 = m1 * m2; | 
 |       timer.stop(); | 
 |       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |  | 
 |       timer.reset(); | 
 |       timer.start(); | 
 |       for (int k = 0; k < REPEAT; ++k) m3 = m1.transpose() * m2; | 
 |       timer.stop(); | 
 |       std::cout << "   a' * b:\t" << timer.value() << endl; | 
 |  | 
 |       timer.reset(); | 
 |       timer.start(); | 
 |       for (int k = 0; k < REPEAT; ++k) m3 = m1.transpose() * m2.transpose(); | 
 |       timer.stop(); | 
 |       std::cout << "   a' * b':\t" << timer.value() << endl; | 
 |  | 
 |       timer.reset(); | 
 |       timer.start(); | 
 |       for (int k = 0; k < REPEAT; ++k) m3 = m1 * m2.transpose(); | 
 |       timer.stop(); | 
 |       std::cout << "   a * b':\t" << timer.value() << endl; | 
 |     } | 
 | #endif | 
 |  | 
 |     // eigen sparse matrices | 
 |     { | 
 |       std::cout << "Eigen sparse\t" << sm1.nonZeros() / (float(sm1.rows()) * float(sm1.cols())) * 100 << "% * " | 
 |                 << sm2.nonZeros() / (float(sm2.rows()) * float(sm2.cols())) * 100 << "%\n"; | 
 |  | 
 |       BENCH(sm3 = sm1 * sm2;) | 
 |       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |  | 
 |       //       BENCH(sm3 = sm1.transpose() * sm2; ) | 
 |       //       std::cout << "   a' * b:\t" << timer.value() << endl; | 
 |       // // | 
 |       //       BENCH(sm3 = sm1.transpose() * sm2.transpose(); ) | 
 |       //       std::cout << "   a' * b':\t" << timer.value() << endl; | 
 |       // // | 
 |       //       BENCH(sm3 = sm1 * sm2.transpose(); ) | 
 |       //       std::cout << "   a * b' :\t" << timer.value() << endl; | 
 |  | 
 |       //       std::cout << "\n"; | 
 |       // | 
 |       //       BENCH( sm3._experimentalNewProduct(sm1, sm2); ) | 
 |       //       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |       // | 
 |       //       BENCH(sm3._experimentalNewProduct(sm1.transpose(),sm2); ) | 
 |       //       std::cout << "   a' * b:\t" << timer.value() << endl; | 
 |       // // | 
 |       //       BENCH(sm3._experimentalNewProduct(sm1.transpose(),sm2.transpose()); ) | 
 |       //       std::cout << "   a' * b':\t" << timer.value() << endl; | 
 |       // // | 
 |       //       BENCH(sm3._experimentalNewProduct(sm1, sm2.transpose());) | 
 |       //       std::cout << "   a * b' :\t" << timer.value() << endl; | 
 |     } | 
 |  | 
 | // eigen dyn-sparse matrices | 
 | /*{ | 
 |   DynamicSparseMatrix<Scalar> m1(sm1), m2(sm2), m3(sm3); | 
 |   std::cout << "Eigen dyn-sparse\t" << m1.nonZeros()/(float(m1.rows())*float(m1.cols()))*100 << "% * " | 
 |             << m2.nonZeros()/(float(m2.rows())*float(m2.cols()))*100 << "%\n"; | 
 |  | 
 | //       timer.reset(); | 
 | //       timer.start(); | 
 |   BENCH(for (int k=0; k<REPEAT; ++k) m3 = m1 * m2;) | 
 | //       timer.stop(); | 
 |   std::cout << "   a * b:\t" << timer.value() << endl; | 
 | //       std::cout << sm3 << "\n"; | 
 |  | 
 |   timer.reset(); | 
 |   timer.start(); | 
 | //       std::cerr << "transpose...\n"; | 
 | //       EigenSparseMatrix sm4 = sm1.transpose(); | 
 | //       std::cout << sm4.nonZeros() << " == " << sm1.nonZeros() << "\n"; | 
 | //       exit(1); | 
 | //       std::cerr << "transpose OK\n"; | 
 | //       std::cout << sm1 << "\n\n" << sm1.transpose() << "\n\n" << sm4.transpose() << "\n\n"; | 
 |   BENCH(for (int k=0; k<REPEAT; ++k) m3 = m1.transpose() * m2;) | 
 | //       timer.stop(); | 
 |   std::cout << "   a' * b:\t" << timer.value() << endl; | 
 |  | 
 | //       timer.reset(); | 
 | //       timer.start(); | 
 |   BENCH( for (int k=0; k<REPEAT; ++k) m3 = m1.transpose() * m2.transpose(); ) | 
 | //       timer.stop(); | 
 |   std::cout << "   a' * b':\t" << timer.value() << endl; | 
 |  | 
 | //       timer.reset(); | 
 | //       timer.start(); | 
 |   BENCH( for (int k=0; k<REPEAT; ++k) m3 = m1 * m2.transpose(); ) | 
 | //       timer.stop(); | 
 |   std::cout << "   a * b' :\t" << timer.value() << endl; | 
 | }*/ | 
 |  | 
 | // CSparse | 
 | #ifdef CSPARSE | 
 |     { | 
 |       std::cout << "CSparse \t" << nnzPerCol << "%\n"; | 
 |       cs *m1, *m2, *m3; | 
 |       eiToCSparse(sm1, m1); | 
 |       eiToCSparse(sm2, m2); | 
 |  | 
 |       BENCH({ | 
 |         m3 = cs_sorted_multiply(m1, m2); | 
 |         if (!m3) { | 
 |           std::cerr << "cs_multiply failed\n"; | 
 |         } | 
 |         //         cs_print(m3, 0); | 
 |         cs_spfree(m3); | 
 |       }); | 
 |       //       timer.stop(); | 
 |       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |  | 
 |       //       BENCH( { m3 = cs_sorted_multiply2(m1, m2); cs_spfree(m3); } ); | 
 |       //       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |     } | 
 | #endif | 
 |  | 
 | #ifndef NOUBLAS | 
 |     { | 
 |       std::cout << "ublas\t" << nnzPerCol << "%\n"; | 
 |       UBlasSparse m1(rows, cols), m2(rows, cols), m3(rows, cols); | 
 |       eiToUblas(sm1, m1); | 
 |       eiToUblas(sm2, m2); | 
 |  | 
 |       BENCH(boost::numeric::ublas::prod(m1, m2, m3);); | 
 |       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |     } | 
 | #endif | 
 |  | 
 | // GMM++ | 
 | #ifndef NOGMM | 
 |     { | 
 |       std::cout << "GMM++ sparse\t" << nnzPerCol << "%\n"; | 
 |       GmmDynSparse gmmT3(rows, cols); | 
 |       GmmSparse m1(rows, cols), m2(rows, cols), m3(rows, cols); | 
 |       eiToGmm(sm1, m1); | 
 |       eiToGmm(sm2, m2); | 
 |  | 
 |       BENCH(gmm::mult(m1, m2, gmmT3);); | 
 |       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |  | 
 |       //       BENCH(gmm::mult(gmm::transposed(m1), m2, gmmT3);); | 
 |       //       std::cout << "   a' * b:\t" << timer.value() << endl; | 
 |       // | 
 |       //       if (rows<500) | 
 |       //       { | 
 |       //         BENCH(gmm::mult(gmm::transposed(m1), gmm::transposed(m2), gmmT3);); | 
 |       //         std::cout << "   a' * b':\t" << timer.value() << endl; | 
 |       // | 
 |       //         BENCH(gmm::mult(m1, gmm::transposed(m2), gmmT3);); | 
 |       //         std::cout << "   a * b':\t" << timer.value() << endl; | 
 |       //       } | 
 |       //       else | 
 |       //       { | 
 |       //         std::cout << "   a' * b':\t" << "forever" << endl; | 
 |       //         std::cout << "   a * b':\t" << "forever" << endl; | 
 |       //       } | 
 |     } | 
 | #endif | 
 |  | 
 | // MTL4 | 
 | #ifndef NOMTL | 
 |     { | 
 |       std::cout << "MTL4\t" << nnzPerCol << "%\n"; | 
 |       MtlSparse m1(rows, cols), m2(rows, cols), m3(rows, cols); | 
 |       eiToMtl(sm1, m1); | 
 |       eiToMtl(sm2, m2); | 
 |  | 
 |       BENCH(m3 = m1 * m2;); | 
 |       std::cout << "   a * b:\t" << timer.value() << endl; | 
 |  | 
 |       //       BENCH(m3 = trans(m1) * m2;); | 
 |       //       std::cout << "   a' * b:\t" << timer.value() << endl; | 
 |       // | 
 |       //       BENCH(m3 = trans(m1) * trans(m2);); | 
 |       //       std::cout << "  a' * b':\t" << timer.value() << endl; | 
 |       // | 
 |       //       BENCH(m3 = m1 * trans(m2);); | 
 |       //       std::cout << "   a * b' :\t" << timer.value() << endl; | 
 |     } | 
 | #endif | 
 |  | 
 |     std::cout << "\n\n"; | 
 |   } | 
 |  | 
 |   return 0; | 
 | } |