sparse_product.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. //g++ -O3 -g0 -DNDEBUG sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.005 -DSIZE=10000 && ./a.out
  2. //g++ -O3 -g0 -DNDEBUG sparse_product.cpp -I.. -I/home/gael/Coding/LinearAlgebra/mtl4/ -DDENSITY=0.05 -DSIZE=2000 && ./a.out
  3. // -DNOGMM -DNOMTL -DCSPARSE
  4. // -I /home/gael/Coding/LinearAlgebra/CSparse/Include/ /home/gael/Coding/LinearAlgebra/CSparse/Lib/libcsparse.a
  5. #include <typeinfo>
  6. #ifndef SIZE
  7. #define SIZE 1000000
  8. #endif
  9. #ifndef NNZPERCOL
  10. #define NNZPERCOL 6
  11. #endif
  12. #ifndef REPEAT
  13. #define REPEAT 1
  14. #endif
  15. #include <algorithm>
  16. #include "BenchTimer.h"
  17. #include "BenchUtil.h"
  18. #include "BenchSparseUtil.h"
  19. #ifndef NBTRIES
  20. #define NBTRIES 1
  21. #endif
  22. #define BENCH(X) \
  23. timer.reset(); \
  24. for (int _j=0; _j<NBTRIES; ++_j) { \
  25. timer.start(); \
  26. for (int _k=0; _k<REPEAT; ++_k) { \
  27. X \
  28. } timer.stop(); }
  29. // #ifdef MKL
  30. //
  31. // #include "mkl_types.h"
  32. // #include "mkl_spblas.h"
  33. //
  34. // template<typename Lhs,typename Rhs,typename Res>
  35. // void mkl_multiply(const Lhs& lhs, const Rhs& rhs, Res& res)
  36. // {
  37. // char n = 'N';
  38. // float alpha = 1;
  39. // char matdescra[6];
  40. // matdescra[0] = 'G';
  41. // matdescra[1] = 0;
  42. // matdescra[2] = 0;
  43. // matdescra[3] = 'C';
  44. // mkl_scscmm(&n, lhs.rows(), rhs.cols(), lhs.cols(), &alpha, matdescra,
  45. // lhs._valuePtr(), lhs._innerIndexPtr(), lhs.outerIndexPtr(),
  46. // pntre, b, &ldb, &beta, c, &ldc);
  47. // // mkl_somatcopy('C', 'T', lhs.rows(), lhs.cols(), 1,
  48. // // lhs._valuePtr(), lhs.rows(), DST, dst_stride);
  49. // }
  50. //
  51. // #endif
  52. #ifdef CSPARSE
  53. cs* cs_sorted_multiply(const cs* a, const cs* b)
  54. {
  55. // return cs_multiply(a,b);
  56. cs* A = cs_transpose(a, 1);
  57. cs* B = cs_transpose(b, 1);
  58. cs* D = cs_multiply(B,A); /* D = B'*A' */
  59. cs_spfree (A) ;
  60. cs_spfree (B) ;
  61. cs_dropzeros (D) ; /* drop zeros from D */
  62. cs* C = cs_transpose (D, 1) ; /* C = D', so that C is sorted */
  63. cs_spfree (D) ;
  64. return C;
  65. // cs* A = cs_transpose(a, 1);
  66. // cs* C = cs_transpose(A, 1);
  67. // return C;
  68. }
  69. cs* cs_sorted_multiply2(const cs* a, const cs* b)
  70. {
  71. cs* D = cs_multiply(a,b);
  72. cs* E = cs_transpose(D,1);
  73. cs_spfree(D);
  74. cs* C = cs_transpose(E,1);
  75. cs_spfree(E);
  76. return C;
  77. }
  78. #endif
  79. void bench_sort();
  80. int main(int argc, char *argv[])
  81. {
  82. // bench_sort();
  83. int rows = SIZE;
  84. int cols = SIZE;
  85. float density = DENSITY;
  86. EigenSparseMatrix sm1(rows,cols), sm2(rows,cols), sm3(rows,cols), sm4(rows,cols);
  87. BenchTimer timer;
  88. for (int nnzPerCol = NNZPERCOL; nnzPerCol>1; nnzPerCol/=1.1)
  89. {
  90. sm1.setZero();
  91. sm2.setZero();
  92. fillMatrix2(nnzPerCol, rows, cols, sm1);
  93. fillMatrix2(nnzPerCol, rows, cols, sm2);
  94. // std::cerr << "filling OK\n";
  95. // dense matrices
  96. #ifdef DENSEMATRIX
  97. {
  98. std::cout << "Eigen Dense\t" << nnzPerCol << "%\n";
  99. DenseMatrix m1(rows,cols), m2(rows,cols), m3(rows,cols);
  100. eiToDense(sm1, m1);
  101. eiToDense(sm2, m2);
  102. timer.reset();
  103. timer.start();
  104. for (int k=0; k<REPEAT; ++k)
  105. m3 = m1 * m2;
  106. timer.stop();
  107. std::cout << " a * b:\t" << timer.value() << endl;
  108. timer.reset();
  109. timer.start();
  110. for (int k=0; k<REPEAT; ++k)
  111. m3 = m1.transpose() * m2;
  112. timer.stop();
  113. std::cout << " a' * b:\t" << timer.value() << endl;
  114. timer.reset();
  115. timer.start();
  116. for (int k=0; k<REPEAT; ++k)
  117. m3 = m1.transpose() * m2.transpose();
  118. timer.stop();
  119. std::cout << " a' * b':\t" << timer.value() << endl;
  120. timer.reset();
  121. timer.start();
  122. for (int k=0; k<REPEAT; ++k)
  123. m3 = m1 * m2.transpose();
  124. timer.stop();
  125. std::cout << " a * b':\t" << timer.value() << endl;
  126. }
  127. #endif
  128. // eigen sparse matrices
  129. {
  130. std::cout << "Eigen sparse\t" << sm1.nonZeros()/(float(sm1.rows())*float(sm1.cols()))*100 << "% * "
  131. << sm2.nonZeros()/(float(sm2.rows())*float(sm2.cols()))*100 << "%\n";
  132. BENCH(sm3 = sm1 * sm2; )
  133. std::cout << " a * b:\t" << timer.value() << endl;
  134. // BENCH(sm3 = sm1.transpose() * sm2; )
  135. // std::cout << " a' * b:\t" << timer.value() << endl;
  136. // //
  137. // BENCH(sm3 = sm1.transpose() * sm2.transpose(); )
  138. // std::cout << " a' * b':\t" << timer.value() << endl;
  139. // //
  140. // BENCH(sm3 = sm1 * sm2.transpose(); )
  141. // std::cout << " a * b' :\t" << timer.value() << endl;
  142. // std::cout << "\n";
  143. //
  144. // BENCH( sm3._experimentalNewProduct(sm1, sm2); )
  145. // std::cout << " a * b:\t" << timer.value() << endl;
  146. //
  147. // BENCH(sm3._experimentalNewProduct(sm1.transpose(),sm2); )
  148. // std::cout << " a' * b:\t" << timer.value() << endl;
  149. // //
  150. // BENCH(sm3._experimentalNewProduct(sm1.transpose(),sm2.transpose()); )
  151. // std::cout << " a' * b':\t" << timer.value() << endl;
  152. // //
  153. // BENCH(sm3._experimentalNewProduct(sm1, sm2.transpose());)
  154. // std::cout << " a * b' :\t" << timer.value() << endl;
  155. }
  156. // eigen dyn-sparse matrices
  157. /*{
  158. DynamicSparseMatrix<Scalar> m1(sm1), m2(sm2), m3(sm3);
  159. std::cout << "Eigen dyn-sparse\t" << m1.nonZeros()/(float(m1.rows())*float(m1.cols()))*100 << "% * "
  160. << m2.nonZeros()/(float(m2.rows())*float(m2.cols()))*100 << "%\n";
  161. // timer.reset();
  162. // timer.start();
  163. BENCH(for (int k=0; k<REPEAT; ++k) m3 = m1 * m2;)
  164. // timer.stop();
  165. std::cout << " a * b:\t" << timer.value() << endl;
  166. // std::cout << sm3 << "\n";
  167. timer.reset();
  168. timer.start();
  169. // std::cerr << "transpose...\n";
  170. // EigenSparseMatrix sm4 = sm1.transpose();
  171. // std::cout << sm4.nonZeros() << " == " << sm1.nonZeros() << "\n";
  172. // exit(1);
  173. // std::cerr << "transpose OK\n";
  174. // std::cout << sm1 << "\n\n" << sm1.transpose() << "\n\n" << sm4.transpose() << "\n\n";
  175. BENCH(for (int k=0; k<REPEAT; ++k) m3 = m1.transpose() * m2;)
  176. // timer.stop();
  177. std::cout << " a' * b:\t" << timer.value() << endl;
  178. // timer.reset();
  179. // timer.start();
  180. BENCH( for (int k=0; k<REPEAT; ++k) m3 = m1.transpose() * m2.transpose(); )
  181. // timer.stop();
  182. std::cout << " a' * b':\t" << timer.value() << endl;
  183. // timer.reset();
  184. // timer.start();
  185. BENCH( for (int k=0; k<REPEAT; ++k) m3 = m1 * m2.transpose(); )
  186. // timer.stop();
  187. std::cout << " a * b' :\t" << timer.value() << endl;
  188. }*/
  189. // CSparse
  190. #ifdef CSPARSE
  191. {
  192. std::cout << "CSparse \t" << nnzPerCol << "%\n";
  193. cs *m1, *m2, *m3;
  194. eiToCSparse(sm1, m1);
  195. eiToCSparse(sm2, m2);
  196. BENCH(
  197. {
  198. m3 = cs_sorted_multiply(m1, m2);
  199. if (!m3)
  200. {
  201. std::cerr << "cs_multiply failed\n";
  202. }
  203. // cs_print(m3, 0);
  204. cs_spfree(m3);
  205. }
  206. );
  207. // timer.stop();
  208. std::cout << " a * b:\t" << timer.value() << endl;
  209. // BENCH( { m3 = cs_sorted_multiply2(m1, m2); cs_spfree(m3); } );
  210. // std::cout << " a * b:\t" << timer.value() << endl;
  211. }
  212. #endif
  213. #ifndef NOUBLAS
  214. {
  215. std::cout << "ublas\t" << nnzPerCol << "%\n";
  216. UBlasSparse m1(rows,cols), m2(rows,cols), m3(rows,cols);
  217. eiToUblas(sm1, m1);
  218. eiToUblas(sm2, m2);
  219. BENCH(boost::numeric::ublas::prod(m1, m2, m3););
  220. std::cout << " a * b:\t" << timer.value() << endl;
  221. }
  222. #endif
  223. // GMM++
  224. #ifndef NOGMM
  225. {
  226. std::cout << "GMM++ sparse\t" << nnzPerCol << "%\n";
  227. GmmDynSparse gmmT3(rows,cols);
  228. GmmSparse m1(rows,cols), m2(rows,cols), m3(rows,cols);
  229. eiToGmm(sm1, m1);
  230. eiToGmm(sm2, m2);
  231. BENCH(gmm::mult(m1, m2, gmmT3););
  232. std::cout << " a * b:\t" << timer.value() << endl;
  233. // BENCH(gmm::mult(gmm::transposed(m1), m2, gmmT3););
  234. // std::cout << " a' * b:\t" << timer.value() << endl;
  235. //
  236. // if (rows<500)
  237. // {
  238. // BENCH(gmm::mult(gmm::transposed(m1), gmm::transposed(m2), gmmT3););
  239. // std::cout << " a' * b':\t" << timer.value() << endl;
  240. //
  241. // BENCH(gmm::mult(m1, gmm::transposed(m2), gmmT3););
  242. // std::cout << " a * b':\t" << timer.value() << endl;
  243. // }
  244. // else
  245. // {
  246. // std::cout << " a' * b':\t" << "forever" << endl;
  247. // std::cout << " a * b':\t" << "forever" << endl;
  248. // }
  249. }
  250. #endif
  251. // MTL4
  252. #ifndef NOMTL
  253. {
  254. std::cout << "MTL4\t" << nnzPerCol << "%\n";
  255. MtlSparse m1(rows,cols), m2(rows,cols), m3(rows,cols);
  256. eiToMtl(sm1, m1);
  257. eiToMtl(sm2, m2);
  258. BENCH(m3 = m1 * m2;);
  259. std::cout << " a * b:\t" << timer.value() << endl;
  260. // BENCH(m3 = trans(m1) * m2;);
  261. // std::cout << " a' * b:\t" << timer.value() << endl;
  262. //
  263. // BENCH(m3 = trans(m1) * trans(m2););
  264. // std::cout << " a' * b':\t" << timer.value() << endl;
  265. //
  266. // BENCH(m3 = m1 * trans(m2););
  267. // std::cout << " a * b' :\t" << timer.value() << endl;
  268. }
  269. #endif
  270. std::cout << "\n\n";
  271. }
  272. return 0;
  273. }