00001
00002
00003
00004 #define SCALAR double
00005
00006 #include <iostream>
00007 #include <algorithm>
00008 #include "BenchTimer.h"
00009 #include "BenchSparseUtil.h"
00010
00011 #define SPMV_BENCH(CODE) BENCH(t,tries,repeats,CODE);
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 int main(int argc, char *argv[])
00038 {
00039 int size = 10000;
00040 int rows = size;
00041 int cols = size;
00042 int nnzPerCol = 40;
00043 int tries = 2;
00044 int repeats = 2;
00045
00046 bool need_help = false;
00047 for(int i = 1; i < argc; i++)
00048 {
00049 if(argv[i][0] == 'r')
00050 {
00051 rows = atoi(argv[i]+1);
00052 }
00053 else if(argv[i][0] == 'c')
00054 {
00055 cols = atoi(argv[i]+1);
00056 }
00057 else if(argv[i][0] == 'n')
00058 {
00059 nnzPerCol = atoi(argv[i]+1);
00060 }
00061 else if(argv[i][0] == 't')
00062 {
00063 tries = atoi(argv[i]+1);
00064 }
00065 else if(argv[i][0] == 'p')
00066 {
00067 repeats = atoi(argv[i]+1);
00068 }
00069 else
00070 {
00071 need_help = true;
00072 }
00073 }
00074 if(need_help)
00075 {
00076 std::cout << argv[0] << " r<nb rows> c<nb columns> n<non zeros per column> t<nb tries> p<nb repeats>\n";
00077 return 1;
00078 }
00079
00080 std::cout << "SpMV " << rows << " x " << cols << " with " << nnzPerCol << " non zeros per column. (" << repeats << " repeats, and " << tries << " tries)\n\n";
00081
00082 EigenSparseMatrix sm(rows,cols);
00083 DenseVector dv(cols), res(rows);
00084 dv.setRandom();
00085
00086 BenchTimer t;
00087 while (nnzPerCol>=4)
00088 {
00089 std::cout << "nnz: " << nnzPerCol << "\n";
00090 sm.setZero();
00091 fillMatrix2(nnzPerCol, rows, cols, sm);
00092
00093
00094 #ifdef DENSEMATRIX
00095 {
00096 DenseMatrix dm(rows,cols), (rows,cols);
00097 eiToDense(sm, dm);
00098
00099 SPMV_BENCH(res = dm * sm);
00100 std::cout << "Dense " << t.value()/repeats << "\t";
00101
00102 SPMV_BENCHres = dm.transpose() * sm);
00103 std::cout << t.value()/repeats << endl;
00104 }
00105 #endif
00106
00107
00108 {
00109 SPMV_BENCH(res.noalias() += sm * dv; )
00110 std::cout << "Eigen " << t.value()/repeats << "\t";
00111
00112 SPMV_BENCH(res.noalias() += sm.transpose() * dv; )
00113 std::cout << t.value()/repeats << endl;
00114 }
00115
00116
00117 #ifdef CSPARSE
00118 {
00119 std::cout << "CSparse \n";
00120 cs *csm;
00121 eiToCSparse(sm, csm);
00122
00123
00124
00125
00126
00127
00128
00129 }
00130 #endif
00131
00132 #ifdef OSKI
00133 {
00134 oski_matrix_t om;
00135 oski_vecview_t ov, ores;
00136 oski_Init();
00137 om = oski_CreateMatCSC(sm._outerIndexPtr(), sm._innerIndexPtr(), sm._valuePtr(), rows, cols,
00138 SHARE_INPUTMAT, 1, INDEX_ZERO_BASED);
00139 ov = oski_CreateVecView(dv.data(), cols, STRIDE_UNIT);
00140 ores = oski_CreateVecView(res.data(), rows, STRIDE_UNIT);
00141
00142 SPMV_BENCH( oski_MatMult(om, OP_NORMAL, 1, ov, 0, ores) );
00143 std::cout << "OSKI " << t.value()/repeats << "\t";
00144
00145 SPMV_BENCH( oski_MatMult(om, OP_TRANS, 1, ov, 0, ores) );
00146 std::cout << t.value()/repeats << "\n";
00147
00148
00149 t.reset();
00150 t.start();
00151 oski_SetHintMatMult(om, OP_NORMAL, 1.0, SYMBOLIC_VEC, 0.0, SYMBOLIC_VEC, ALWAYS_TUNE_AGGRESSIVELY);
00152 oski_TuneMat(om);
00153 t.stop();
00154 double tuning = t.value();
00155
00156 SPMV_BENCH( oski_MatMult(om, OP_NORMAL, 1, ov, 0, ores) );
00157 std::cout << "OSKI tuned " << t.value()/repeats << "\t";
00158
00159 SPMV_BENCH( oski_MatMult(om, OP_TRANS, 1, ov, 0, ores) );
00160 std::cout << t.value()/repeats << "\t(" << tuning << ")\n";
00161
00162
00163 oski_DestroyMat(om);
00164 oski_DestroyVecView(ov);
00165 oski_DestroyVecView(ores);
00166 oski_Close();
00167 }
00168 #endif
00169
00170 #ifndef NOUBLAS
00171 {
00172 using namespace boost::numeric;
00173 UblasMatrix um(rows,cols);
00174 eiToUblas(sm, um);
00175
00176 boost::numeric::ublas::vector<Scalar> uv(cols), ures(rows);
00177 Map<Matrix<Scalar,Dynamic,1> >(&uv[0], cols) = dv;
00178 Map<Matrix<Scalar,Dynamic,1> >(&ures[0], rows) = res;
00179
00180 SPMV_BENCH(ublas::axpy_prod(um, uv, ures, true));
00181 std::cout << "ublas " << t.value()/repeats << "\t";
00182
00183 SPMV_BENCH(ublas::axpy_prod(boost::numeric::ublas::trans(um), uv, ures, true));
00184 std::cout << t.value()/repeats << endl;
00185 }
00186 #endif
00187
00188
00189 #ifndef NOGMM
00190 {
00191 GmmSparse gm(rows,cols);
00192 eiToGmm(sm, gm);
00193
00194 std::vector<Scalar> gv(cols), gres(rows);
00195 Map<Matrix<Scalar,Dynamic,1> >(&gv[0], cols) = dv;
00196 Map<Matrix<Scalar,Dynamic,1> >(&gres[0], rows) = res;
00197
00198 SPMV_BENCH(gmm::mult(gm, gv, gres));
00199 std::cout << "GMM++ " << t.value()/repeats << "\t";
00200
00201 SPMV_BENCH(gmm::mult(gmm::transposed(gm), gv, gres));
00202 std::cout << t.value()/repeats << endl;
00203 }
00204 #endif
00205
00206
00207 #ifndef NOMTL
00208 {
00209 MtlSparse mm(rows,cols);
00210 eiToMtl(sm, mm);
00211 mtl::dense_vector<Scalar> mv(cols, 1.0);
00212 mtl::dense_vector<Scalar> mres(rows, 1.0);
00213
00214 SPMV_BENCH(mres = mm * mv);
00215 std::cout << "MTL4 " << t.value()/repeats << "\t";
00216
00217 SPMV_BENCH(mres = trans(mm) * mv);
00218 std::cout << t.value()/repeats << endl;
00219 }
00220 #endif
00221
00222 std::cout << "\n";
00223
00224 if(nnzPerCol==1)
00225 break;
00226 nnzPerCol -= nnzPerCol/2;
00227 }
00228
00229 return 0;
00230 }
00231
00232
00233