http://stxxl.sourceforge.net
<R-Steffen@gmx.de>
<tb@panthema.net>
http://www.boost.org/LICENSE_1_0.txt
#include <iostream>
#include <limits>
#include <stxxl/vector>
#include <stxxl/stream>
#include <stxxl/bits/containers/matrix.h>
#include <stxxl/bits/common/cmdline.h>
using stxxl::int_type;
using stxxl::unsigned_type;
template class stxxl::matrix<int_type, 32>;
template class stxxl::matrix_iterator<int_type, 32>;
template class stxxl::const_matrix_iterator<int_type, 32>;
template class stxxl::matrix_row_major_iterator<int_type, 32>;
template class stxxl::matrix_col_major_iterator<int_type, 32>;
template class stxxl::const_matrix_row_major_iterator<int_type, 32>;
template class stxxl::const_matrix_col_major_iterator<int_type, 32>;
template class stxxl::column_vector<int_type>;
template class stxxl::row_vector<int_type>;
template struct stxxl::matrix_local::matrix_operations<int_type, 32>;
struct constant_one
{
const constant_one& operator ++ () const { return *this; }
bool empty() const { return false; }
int operator * () const { return 1; }
};
struct modulus_integers
{
private:
unsigned_type step, counter, modulus;
public:
modulus_integers(unsigned_type start = 1, unsigned_type step = 1, unsigned_type modulus = 0)
: step(step),
counter(start),
modulus(modulus)
{ }
modulus_integers& operator ++ ()
{
counter += step;
if (modulus != 0 && counter >= modulus)
counter %= modulus;
return *this;
}
bool empty() const { return false; }
unsigned_type operator * () const { return counter; }
};
struct diagonal_matrix
{
private:
unsigned_type order, counter, value;
public:
diagonal_matrix(unsigned_type order, unsigned_type value = 1)
: order(order), counter(0), value(value) { }
diagonal_matrix& operator ++ ()
{
++counter;
return *this;
}
bool empty() const { return false; }
unsigned_type operator * () const
{ return (counter % (order + 1) == 0) * value; }
};
struct inverse_diagonal_matrix
{
private:
unsigned_type order, counter, value;
public:
inverse_diagonal_matrix(unsigned_type order, unsigned_type value = 1)
: order(order), counter(0), value(value) { }
inverse_diagonal_matrix& operator ++ ()
{
++counter;
return *this;
}
bool empty() const { return false; }
unsigned_type operator * () const
{ return (counter % order == order - 1 - counter / order) * value; }
};
template <class CompareIterator, typename ValueType>
class iterator_compare
{
typedef std::pair<ValueType, ValueType> error_type;
CompareIterator& compiter;
ValueType current_value;
stxxl::vector<error_type> errors;
public:
iterator_compare(CompareIterator& co)
: compiter(co),
current_value(),
errors()
{ }
iterator_compare& operator ++ ()
{
if (current_value != *compiter)
errors.push_back(error_type(current_value, *compiter));
++compiter;
return *this;
}
bool empty() const { return compiter.empty(); }
ValueType& operator * () { return current_value; }
unsigned_type get_num_errors() { return errors.size(); }
stxxl::vector<error_type> & get_errors() { return errors; }
};
const int small_block_order = 32;
const int block_order = 32;
unsigned_type internal_memory = 256 * 1024 * 1024;
void test1(int rank)
{
STXXL_MSG("multiplying two int_type matrices of rank " << rank << " block order " << small_block_order);
typedef int_type value_type;
typedef stxxl::block_scheduler<stxxl::matrix_swappable_block<value_type, small_block_order> > block_scheduler_type;
typedef stxxl::matrix<value_type, small_block_order> matrix_type;
typedef matrix_type::row_vector_type row_vector_type;
typedef matrix_type::column_vector_type column_vector_type;
typedef matrix_type::row_major_iterator row_major_iterator;
typedef matrix_type::const_row_major_iterator const_row_major_iterator;
block_scheduler_type* bs_ptr = new block_scheduler_type(internal_memory);
block_scheduler_type& bs = *bs_ptr;
matrix_type
* a = new matrix_type(bs, rank, rank),
* b = new matrix_type(bs, rank, rank),
* c = new matrix_type(bs, rank, rank);
stxxl::stats_data stats_before, stats_after;
stxxl::matrix_operation_statistic_data matrix_stats_before, matrix_stats_after;
for (row_major_iterator mit = a->begin(); mit != a->end(); ++mit)
*mit = 1;
for (row_major_iterator mit = b->begin(); mit != b->end(); ++mit)
*mit = 1;
bs.flush();
STXXL_MSG("start mult");
matrix_stats_before.set();
stats_before = *stxxl::stats::get_instance();
*c = *a * *b;
bs.flush();
stats_after = *stxxl::stats::get_instance();
matrix_stats_after.set();
STXXL_MSG("end mult");
STXXL_MSG(matrix_stats_after - matrix_stats_before);
STXXL_MSG(stats_after - stats_before);
{
int_type num_err = 0;
for (const_row_major_iterator mit = c->cbegin(); mit != c->cend(); ++mit)
num_err += (*mit != rank);
STXXL_CHECK2(num_err == 0,
"c had " << num_err << " errors");
}
{
int_type i = 1;
for (row_major_iterator mit = a->begin(); mit != a->end(); ++mit, ++i)
*mit = i;
}
{
b->set_zero();
matrix_type::iterator mit = b->begin();
for (int_type i = 0; i < b->get_height(); ++i)
{
mit.set_pos(i, i);
*mit = 1;
}
}
bs.flush();
STXXL_MSG("start mult");
matrix_stats_before.set();
stats_before = *stxxl::stats::get_instance();
*c = *a * *b;
bs.flush();
stats_after = *stxxl::stats::get_instance();
matrix_stats_after.set();
STXXL_MSG("end mult");
*c *= 3;
*c += *a;
STXXL_MSG(matrix_stats_after - matrix_stats_before);
STXXL_MSG(stats_after - stats_before);
{
int_type num_err = 0;
int_type i = 1;
for (const_row_major_iterator mit = c->cbegin(); mit != c->cend(); ++mit, ++i)
num_err += (*mit != (i * 4));
STXXL_CHECK2(num_err == 0,
"c had " << num_err << " errors");
}
{
column_vector_type x(rank), y;
int_type i = 0;
for (column_vector_type::iterator it = x.begin(); it != x.end(); ++it)
*it = ++i;
y = *b * x;
y = y + x;
y += x;
y = y - x;
y -= x;
y = x * 5;
y *= 5;
row_vector_type w(rank), z;
i = 0;
for (row_vector_type::iterator it = w.begin(); it != w.end(); ++it)
*it = ++i;
z = w * *b;
z = z + w;
z += w;
z = z - w;
z -= w;
z = w * 5;
z *= 5;
*a = matrix_type(bs, x, w);
value_type v;
v = w * x;
stxxl::STXXL_UNUSED(v);
}
delete a;
delete b;
delete c;
delete bs_ptr;
}
void test2(int rank, int mult_algo_num, int sched_algo_num)
{
STXXL_MSG("multiplying two full double matrices of rank " << rank << ", block order " << block_order
<< " using " << internal_memory << " bytes internal memory, multiplication-algo "
<< mult_algo_num << ", scheduling-algo " << sched_algo_num);
typedef double value_type;
typedef stxxl::block_scheduler<stxxl::matrix_swappable_block<value_type, block_order> > block_scheduler_type;
typedef stxxl::matrix<value_type, block_order> matrix_type;
typedef matrix_type::row_major_iterator row_major_iterator;
typedef matrix_type::const_row_major_iterator const_row_major_iterator;
block_scheduler_type* bs_ptr = new block_scheduler_type(internal_memory);
block_scheduler_type& bs = *bs_ptr;
matrix_type
* a = new matrix_type(bs, rank, rank),
* b = new matrix_type(bs, rank, rank),
* c = new matrix_type(bs, rank, rank);
stxxl::stats_data stats_before, stats_after;
stxxl::matrix_operation_statistic_data matrix_stats_before, matrix_stats_after;
STXXL_MSG("writing input matrices");
for (row_major_iterator mit = a->begin(); mit != a->end(); ++mit)
*mit = 1;
for (row_major_iterator mit = b->begin(); mit != b->end(); ++mit)
*mit = 1;
bs.flush();
STXXL_MSG("start of multiplication");
matrix_stats_before.set();
stats_before = *stxxl::stats::get_instance();
if (mult_algo_num >= 0)
*c = a->multiply(*b, mult_algo_num, sched_algo_num);
else
*c = a->multiply_internal(*b, sched_algo_num);
bs.flush();
stats_after = *stxxl::stats::get_instance();
matrix_stats_after.set();
STXXL_MSG("end of multiplication");
STXXL_MSG(matrix_stats_after - matrix_stats_before);
STXXL_MSG(stats_after - stats_before);
{
int_type num_err = 0;
for (const_row_major_iterator mit = c->cbegin(); mit != c->cend(); ++mit)
num_err += (*mit != rank);
STXXL_CHECK2(num_err == 0, "c had " << num_err << " errors");
}
delete a;
delete b;
delete c;
delete bs_ptr;
}
int main(int argc, char** argv)
{
int test_case = -1;
int rank = 500;
int mult_algo_num = 2;
int sched_algo_num = 1;
stxxl::cmdline_parser cp;
cp.set_description("stxxl matrix test");
cp.set_author("Raoul Steffen <R-Steffen@gmx.de>");
cp.add_opt_param_int("K", "number of the test case to run: 1 or 2, or by default: all", test_case);
cp.add_int('r', "rank", "<N>", "rank of the matrices, default: 500", rank);
cp.add_bytes('m', "memory", "<L>", "internal memory to, default: 256 MiB", internal_memory);
cp.add_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: 2", mult_algo_num);
cp.add_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: 1", sched_algo_num);
if (!cp.process(argc, argv))
return 0;
switch (test_case)
{
default:
test1(rank);
for (int mult_algo = 0; mult_algo <= 6; ++mult_algo)
{
for (int sched_algo = 0; sched_algo <= 2; ++sched_algo)
{
test2(rank, mult_algo, sched_algo);
}
}
break;
case 1:
test1(rank);
break;
case 2:
test2(rank, mult_algo_num, sched_algo_num);
break;
}
STXXL_MSG("end of test");
return 0;
}