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