Stxxl  1.4.0
containers/test_matrix.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines