Stxxl
1.4.0
|
00001 /*************************************************************************** 00002 * containers/test_matrix.cpp 00003 * 00004 * Part of the STXXL. See http://stxxl.sourceforge.net 00005 * 00006 * Copyright (C) 2010-2011 Raoul Steffen <R-Steffen@gmx.de> 00007 * 00008 * Distributed under the Boost Software License, Version 1.0. 00009 * (See accompanying file LICENSE_1_0.txt or copy at 00010 * http://www.boost.org/LICENSE_1_0.txt) 00011 **************************************************************************/ 00012 00013 #include <iostream> 00014 #include <limits> 00015 00016 // Thanks Daniel Russel, Stanford University 00017 #include <Argument_helper.h> 00018 00019 #include <stxxl/vector> 00020 #include <stxxl/stream> 00021 #include <stxxl/bits/containers/matrix.h> 00022 00023 using namespace stxxl; 00024 00025 struct constant_one 00026 { 00027 const constant_one & operator ++ () const { return *this; } 00028 bool empty() const { return false; } 00029 int operator * () const { return 1; } 00030 }; 00031 00032 struct modulus_integers 00033 { 00034 private: 00035 unsigned_type step, counter, modulus; 00036 00037 public: 00038 modulus_integers(unsigned_type start = 1, unsigned_type step = 1, unsigned_type modulus = 0) 00039 : step(step), 00040 counter(start), 00041 modulus(modulus) 00042 { } 00043 00044 modulus_integers & operator ++ () 00045 { 00046 counter += step; 00047 if (modulus != 0 && counter >= modulus) 00048 counter %= modulus; 00049 return *this; 00050 } 00051 00052 bool empty() const { return false; } 00053 00054 unsigned_type operator * () const { return counter; } 00055 }; 00056 00057 struct diagonal_matrix 00058 { 00059 private: 00060 unsigned_type order, counter, value; 00061 00062 public: 00063 diagonal_matrix(unsigned_type order, unsigned_type value = 1) 00064 : order(order), counter(0), value(value) { } 00065 00066 diagonal_matrix & operator ++ () 00067 { 00068 ++counter; 00069 return *this; 00070 } 00071 00072 bool empty() const { return false; } 00073 00074 unsigned_type operator * () const 00075 { return (counter % (order + 1) == 0) * value; } 00076 }; 00077 00078 struct inverse_diagonal_matrix 00079 { 00080 private: 00081 unsigned_type order, counter, value; 00082 00083 public: 00084 inverse_diagonal_matrix(unsigned_type order, unsigned_type value = 1) 00085 : order(order), counter(0), value(value) { } 00086 00087 inverse_diagonal_matrix & operator ++ () 00088 { 00089 ++counter; 00090 return *this; 00091 } 00092 00093 bool empty() const { return false; } 00094 00095 unsigned_type operator * () const 00096 { return (counter % order == order - 1 - counter / order) * value; } 00097 }; 00098 00099 template <class CompareIterator, typename ValueType> 00100 class iterator_compare 00101 { 00102 typedef std::pair<ValueType, ValueType> error_type; 00103 00104 CompareIterator & compiter; 00105 ValueType current_value; 00106 vector<error_type> errors; 00107 00108 public: 00109 iterator_compare(CompareIterator & co) 00110 : compiter(co), 00111 current_value(), 00112 errors() 00113 { } 00114 00115 iterator_compare & operator ++ () 00116 { 00117 if (current_value != *compiter) 00118 errors.push_back(error_type(current_value, *compiter)); 00119 ++compiter; 00120 return *this; 00121 } 00122 00123 bool empty() const { return compiter.empty(); } 00124 ValueType & operator * () { return current_value; } 00125 00126 unsigned_type get_num_errors() { return errors.size(); } 00127 vector<error_type> & get_errors() { return errors; } 00128 }; 00129 00130 int main(int argc, char **argv) 00131 { 00132 const int small_block_order = 32; // must be a multiple of 32, assuming at least 4 bytes element size 00133 const int block_order = 32; // must be a multiple of 32, assuming at least 4 bytes element size 00134 00135 int test_case = -1; 00136 int rank = 10000; 00137 int internal_memory_megabyte = 256; 00138 int mult_algo_num = 2; 00139 int sched_algo_num = 1; 00140 int internal_memory_byte = 0; 00141 00142 dsr::Argument_helper ah; 00143 ah.new_int("K", "number of the test case to run", test_case); 00144 ah.new_named_int('r', "rank", "N","rank of the matrices default", rank); 00145 ah.new_named_int('m', "memory", "L", "internal memory to use (in megabytes) default", internal_memory_megabyte); 00146 ah.new_named_int('a', "mult-algo", "N", "use multiplication-algorithm number N\n available are:\n 0: naive_multiply_and_add\n 1: recursive_multiply_and_add\n 2: strassen_winograd_multiply_and_add\n 3: multi_level_strassen_winograd_multiply_and_add\n 4: strassen_winograd_multiply (block-interleaved pre- and postadditions)\n 5: strassen_winograd_multiply_and_add_interleaved (block-interleaved preadditions)\n 6: multi_level_strassen_winograd_multiply_and_add_block_grained\n default", mult_algo_num); 00147 ah.new_named_int('s', "scheduling-algo", "N", "use scheduling-algorithm number N\n available are:\n 0: online LRU\n 1: offline LFD\n 2: offline LRU prefetching\n default", sched_algo_num); 00148 ah.new_named_int('c', "memory-byte", "L", "internal memory to use (in bytes) no default", internal_memory_byte); 00149 00150 ah.set_description("stxxl matrix test"); 00151 ah.set_author("Raoul Steffen, R-Steffen@gmx.de"); 00152 ah.process(argc, argv); 00153 00154 int_type internal_memory; 00155 if (internal_memory_byte) 00156 internal_memory = internal_memory_byte; 00157 else 00158 internal_memory = int_type(internal_memory_megabyte) * 1048576; 00159 00160 switch (test_case) 00161 { 00162 default: 00163 STXXL_ERRMSG("unknown testcase"); 00164 case 4: 00165 { 00166 STXXL_MSG("multiplying two int_type matrices of rank " << rank << " block order " << small_block_order); 00167 typedef int_type value_type; 00168 00169 typedef block_scheduler< matrix_swappable_block<value_type, small_block_order> > bst; 00170 typedef matrix<value_type, small_block_order> mt; 00171 typedef mt::row_vector_type rvt; 00172 typedef mt::column_vector_type cvt; 00173 typedef mt::row_major_iterator mitt; 00174 typedef mt::const_row_major_iterator cmitt; 00175 00176 bst * b_s = new bst(internal_memory); // the block_scheduler may use internal_memory byte for caching 00177 //bst * b_s = new bst(16*sizeof(value_type)*small_block_order*small_block_order); // the block_scheduler may use 16 blocks for caching 00178 bst & bs = *b_s; 00179 mt * a = new mt(bs, rank, rank), 00180 * b = new mt(bs, rank, rank), 00181 * c = new mt(bs, rank, rank); 00182 stats_data stats_before, stats_after; 00183 matrix_operation_statistic_data matrix_stats_before, matrix_stats_after; 00184 00185 // ------ first run 00186 for (mitt mit = a->begin(); mit != a->end(); ++mit) 00187 *mit = 1; 00188 for (mitt mit = b->begin(); mit != b->end(); ++mit) 00189 *mit = 1; 00190 00191 bs.flush(); 00192 STXXL_MSG("start mult"); 00193 matrix_stats_before.set(); 00194 stats_before = *stats::get_instance(); 00195 *c = *a * *b; 00196 bs.flush(); 00197 stats_after = *stats::get_instance(); 00198 matrix_stats_after.set(); 00199 STXXL_MSG("end mult"); 00200 00201 STXXL_MSG(matrix_stats_after - matrix_stats_before); 00202 STXXL_MSG(stats_after - stats_before); 00203 { 00204 int_type num_err = 0; 00205 for (cmitt mit = c->cbegin(); mit != c->cend(); ++mit) 00206 num_err += (*mit != rank); 00207 if (num_err) 00208 STXXL_ERRMSG("c had " << num_err << " errors"); 00209 } 00210 00211 // ------ second run 00212 { 00213 int_type i = 1; 00214 for (mitt mit = a->begin(); mit != a->end(); ++mit, ++i) 00215 *mit = i; 00216 } 00217 { 00218 b->set_zero(); 00219 mt::iterator mit = b->begin(); 00220 for (int_type i = 0; i < b->get_height(); ++i) 00221 { 00222 mit.set_pos(i,i); 00223 *mit = 1; 00224 } 00225 } 00226 00227 bs.flush(); 00228 STXXL_MSG("start mult"); 00229 matrix_stats_before.set(); 00230 stats_before = *stats::get_instance(); 00231 *c = *a * *b; 00232 bs.flush(); 00233 stats_after = *stats::get_instance(); 00234 matrix_stats_after.set(); 00235 STXXL_MSG("end mult"); 00236 00237 *c *= 3; 00238 *c += *a; 00239 STXXL_MSG(matrix_stats_after - matrix_stats_before); 00240 STXXL_MSG(stats_after - stats_before); 00241 { 00242 int_type num_err = 0; 00243 int_type i = 1; 00244 for (cmitt mit = c->cbegin(); mit != c->cend(); ++mit, ++i) 00245 num_err += (*mit != (i * 4)); 00246 if (num_err) 00247 STXXL_ERRMSG("c had " << num_err << " errors"); 00248 } 00249 00250 { 00251 cvt x(rank), 00252 y; 00253 int_type i = 0; 00254 for (cvt::iterator it = x.begin(); it != x.end(); ++it) 00255 *it = ++i; 00256 y = *b * x; 00257 y = y + x; 00258 y += x; 00259 y = y - x; 00260 y -= x; 00261 y = x * 5; 00262 y *= 5; 00263 00264 rvt w(rank), 00265 z; 00266 i = 0; 00267 for (rvt::iterator it = w.begin(); it != w.end(); ++it) 00268 *it = ++i; 00269 z = w * *b; 00270 z = z + w; 00271 z += w; 00272 z = z - w; 00273 z -= w; 00274 z = w * 5; 00275 z *= 5; 00276 00277 *a = mt(bs, x, w); 00278 00279 value_type v; 00280 v = w * x; 00281 STXXL_UNUSED(v); 00282 } 00283 00284 delete a; 00285 delete b; 00286 delete c; 00287 delete b_s; 00288 break; 00289 } 00290 case 5: 00291 { 00292 STXXL_MSG("multiplying two full double matrices of rank " << rank << ", block order " << block_order 00293 << " using " << internal_memory_megabyte << "MiB internal memory, multiplication-algo " 00294 << mult_algo_num << ", scheduling-algo " << sched_algo_num); 00295 00296 typedef double value_type; 00297 00298 typedef block_scheduler< matrix_swappable_block<value_type, block_order> > bst; 00299 typedef matrix<value_type, block_order> mt; 00300 typedef mt::row_major_iterator mitt; 00301 typedef mt::const_row_major_iterator cmitt; 00302 00303 bst * b_s = new bst(internal_memory); // the block_scheduler may use internal_memory byte for caching 00304 bst & bs = *b_s; 00305 mt * a = new mt(bs, rank, rank), 00306 * b = new mt(bs, rank, rank), 00307 * c = new mt(bs, rank, rank); 00308 stats_data stats_before, stats_after; 00309 matrix_operation_statistic_data matrix_stats_before, matrix_stats_after; 00310 00311 STXXL_MSG("writing input matrices"); 00312 for (mitt mit = a->begin(); mit != a->end(); ++mit) 00313 *mit = 1; 00314 for (mitt mit = b->begin(); mit != b->end(); ++mit) 00315 *mit = 1; 00316 00317 bs.flush(); 00318 STXXL_MSG("start of multiplication"); 00319 matrix_stats_before.set(); 00320 stats_before = *stats::get_instance(); 00321 if (mult_algo_num >= 0) 00322 *c = a->multiply(*b, mult_algo_num, sched_algo_num); 00323 else 00324 *c = a->multiply_internal(*b, sched_algo_num); 00325 bs.flush(); 00326 stats_after = *stats::get_instance(); 00327 matrix_stats_after.set(); 00328 STXXL_MSG("end of multiplication"); 00329 00330 STXXL_MSG(matrix_stats_after - matrix_stats_before); 00331 STXXL_MSG(stats_after - stats_before); 00332 { 00333 int_type num_err = 0; 00334 for (cmitt mit = c->cbegin(); mit != c->cend(); ++mit) 00335 num_err += (*mit != rank); 00336 if (num_err) 00337 STXXL_ERRMSG("c had " << num_err << " errors"); 00338 } 00339 00340 delete a; 00341 delete b; 00342 delete c; 00343 delete b_s; 00344 break; 00345 } 00346 } 00347 STXXL_MSG("end of test"); 00348 return 0; 00349 }