mdds/misc/matrix_perf.cpp

512 lines
15 KiB
C++

#include <cstdlib>
#include <iostream>
#include <sys/time.h>
#include <mdds/mixed_type_matrix.hpp>
#include <mdds/multi_type_matrix.hpp>
double get_current_time()
{
#ifdef _WIN32
FILETIME ft;
__int64 *time64 = reinterpret_cast<__int64 *>(&ft);
GetSystemTimeAsFileTime(&ft);
return *time64 / 10000000.0;
#else
timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_sec + tv.tv_usec / 1000000.0;
#endif
}
class stack_watch
{
public:
explicit stack_watch() : m_start_time(get_current_time()) {}
void reset() { m_start_time = get_current_time(); }
double get_duration() const { return get_current_time() - m_start_time; }
private:
double m_start_time;
};
using namespace std;
typedef mdds::mixed_type_matrix<std::string, bool> mixed_mx_type;
typedef mdds::multi_type_matrix<mdds::mtm::std_string_trait> multi_mx_type;
namespace {
class sum_all_values
{
double m_sum;
public:
sum_all_values() : m_sum(0.0) {}
void operator() (const multi_mx_type::element_block_node_type& blk)
{
if (!blk.data)
return;
if (mdds::mtv::get_block_type(*blk.data) != mdds::mtv::element_type_double)
return;
using mdds::mtv::double_element_block;
numeric_element_block::const_iterator it = numeric_element_block::begin(*blk.data);
numeric_element_block::const_iterator it_end = numeric_element_block::end(*blk.data);
for (; it != it_end; ++it)
m_sum += *it;
}
double get() const { return m_sum; }
};
class count_all_values
{
long m_count;
public:
count_all_values() : m_count(0) {}
void operator() (const multi_mx_type::element_block_node_type& blk)
{
if (!blk.data)
return;
if (mdds::mtv::get_block_type(*blk.data) != mdds::mtv::element_type_double)
return;
m_count += blk.size;
}
long get() const { return m_count; }
};
template<typename _Mx>
void init_manual_loop(_Mx& mx, size_t row_size, size_t col_size)
{
double val = 0.0;
for (size_t row = 0; row < row_size; ++row)
{
for (size_t col = 0; col < col_size; ++col)
{
mx.set(row, col, val);
val += 0.00001;
}
}
}
void init_value_vector(vector<double>& vals, size_t row_size, size_t col_size)
{
vals.reserve(row_size*col_size);
double val = 0.0;
for (size_t row = 0; row < row_size; ++row)
{
for (size_t col = 0; col < col_size; ++col)
{
vals.push_back(val);
val += 0.00001;
}
}
}
template<typename _Mx>
double sum_manual_loop(const _Mx& mx, size_t row_size, size_t col_size)
{
double sum = 0.0;
for (size_t row = 0; row < row_size; ++row)
for (size_t col = 0; col < col_size; ++col)
sum += mx.get_numeric(row, col);
return sum;
}
double sum_iterator(const mixed_mx_type& mx)
{
double sum = 0.0;
mixed_mx_type::const_iterator it = mx.begin(), it_end = mx.end();
for (; it != it_end; ++it)
{
if (it->m_type == mdds::element_numeric)
sum += it->m_numeric;
}
return sum;
}
}
void perf_construction()
{
cout << "---" << endl;
size_t row_size = 20000, col_size = 8000;
{
stack_watch sw;
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_zero);
cout << "construction filled zero: " << sw.get_duration() << " sec (mixed_type_matrix, filled)" << endl;
}
{
stack_watch sw;
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_sparse_zero);
cout << "construction filled zero: " << sw.get_duration() << " sec (mixed_type_matrix, sparse)" << endl;
}
{
stack_watch sw;
multi_mx_type mx(row_size, col_size, 0.0);
cout << "construction filled zero: " << sw.get_duration() << " sec (multi_type_matrix)" << endl;
}
{
stack_watch sw;
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_empty);
cout << "construction filled empty: " << sw.get_duration() << " sec (mixed_type_matrix, filled)" << endl;
}
{
stack_watch sw;
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_sparse_empty);
cout << "construction filled empty: " << sw.get_duration() << " sec (mixed_type_matrix, sparse)" << endl;
}
{
stack_watch sw;
multi_mx_type mx(row_size, col_size);
cout << "construction filled empty: " << sw.get_duration() << " sec (multi_type_matrix)" << endl;
}
}
void perf_insertion()
{
cout << "---" << endl;
size_t row_size = 10000;
size_t col_size = 1000;
{
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_zero);
stack_watch sw;
init_manual_loop(mx, row_size, col_size);
cout << "insertion via loop: " << sw.get_duration() << " sec (mixed_type_matrix, filled zero)" << endl;
}
{
multi_mx_type mx(row_size, col_size);
stack_watch sw;
init_manual_loop(mx, row_size, col_size);
cout << "insertion via loop: " << sw.get_duration() << " sec (multi_type_matrix, init empty)" << endl;
}
{
multi_mx_type mx(row_size, col_size, 0.0);
stack_watch sw;
init_manual_loop(mx, row_size, col_size);
cout << "insertion via loop: " << sw.get_duration() << " sec (multi_type_matrix, init zero)" << endl;
}
{
multi_mx_type mx(row_size, col_size);
std::vector<double> vals;
stack_watch sw;
init_value_vector(vals, row_size, col_size);
mx.set(0, 0, vals.begin(), vals.end());
cout << "insertion via single set call: " << sw.get_duration() << " sec (multi_type_matrix, init empty, value initialization included)" << endl;
}
{
multi_mx_type mx(row_size, col_size);
std::vector<double> vals;
init_value_vector(vals, row_size, col_size);
stack_watch sw;
mx.set(0, 0, vals.begin(), vals.end());
cout << "insertion via single set call: " << sw.get_duration() << " sec (multi_type_matrix, init empty, value initialization excluded)" << endl;
}
{
multi_mx_type mx(row_size, col_size, 0.0);
std::vector<double> vals;
vals.reserve(row_size*col_size);
stack_watch sw;
init_value_vector(vals, row_size, col_size);
mx.set(0, 0, vals.begin(), vals.end());
cout << "insertion via single set call: " << sw.get_duration() << " sec (multi_type_matrix, init zero, value initialization included)" << endl;
}
{
multi_mx_type mx(row_size, col_size, 0.0);
std::vector<double> vals;
init_value_vector(vals, row_size, col_size);
stack_watch sw;
mx.set(0, 0, vals.begin(), vals.end());
cout << "insertion via single set call: " << sw.get_duration() << " sec (multi_type_matrix, init zero, value initialization excluded)" << endl;
}
}
void perf_sum_all_values()
{
cout << "---" << endl;
size_t row_size = 10000;
size_t col_size = 1000;
{
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_zero);
init_manual_loop(mx, row_size, col_size);
{
stack_watch sw;
double sum = sum_manual_loop(mx, row_size, col_size);
cout << "sum all values (" << sum << ") : " << sw.get_duration() << " sec (mixed_type_matrix, manual loop)" << endl;
}
{
stack_watch sw;
double sum = sum_iterator(mx);
cout << "sum all values (" << sum << ") : " << sw.get_duration() << " sec (mixed_type_matrix, iterator)" << endl;
}
{
stack_watch sw;
long count = 0;
for (size_t row = 0; row < row_size; ++row)
for (size_t col = 0; col < col_size; ++col)
{
if (mx.get_type(row, col) == mdds::element_numeric)
++count;
}
cout << "count all values (" << count << ") : " << sw.get_duration() << " sec (mixed_type_matrix, manual loop)" << endl;
}
{
stack_watch sw;
long count = 0;
mixed_mx_type::const_iterator it = mx.begin(), it_end = mx.end();
for (; it != it_end; ++it)
{
if (it->m_type == mdds::element_numeric)
++count;
}
cout << "count all values (" << count << ") : " << sw.get_duration() << " sec (mixed_type_matrix, iterator)" << endl;
}
}
{
multi_mx_type mx(row_size, col_size, 0.0);
init_manual_loop(mx, row_size, col_size);
{
stack_watch sw;
double sum = sum_manual_loop(mx, row_size, col_size);
cout << "sum all values (" << sum << ") : " << sw.get_duration() << " sec (multi_type_matrix, manual loop)" << endl;
}
{
stack_watch sw;
sum_all_values func;
mx.walk(func);
cout << "sum all values (" << func.get() << ") : " << sw.get_duration() << " sec (multi_type_matrix, walk)" << endl;
}
{
stack_watch sw;
count_all_values func;
mx.walk(func);
cout << "count all values (" << func.get() << ") : " << sw.get_duration() << " sec (multi_type_matrix, walk)" << endl;
}
}
}
void perf_sum_all_values_multi_block()
{
cout << "---" << endl;
size_t row_size = 10000;
size_t col_size = 1000;
double step = 0.00001;
{
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_zero);
double val = 0.0;
for (size_t row = 0; row < row_size; ++row)
{
for (size_t col = 0; col < col_size; ++col)
{
if ((col % 3) == 0)
{
mx.set_empty(row, col);
}
else
{
mx.set(row, col, val);
val += step;
}
}
}
{
stack_watch sw;
double sum = sum_manual_loop(mx, row_size, col_size);
cout << "sum all values multi-block (" << sum << ") : " << sw.get_duration() << " sec (mixed_type_matrix, manual loop)" << endl;
}
{
stack_watch sw;
double sum = sum_iterator(mx);
cout << "sum all values multi-block (" << sum << ") : " << sw.get_duration() << " sec (mixed_type_matrix, iterator)" << endl;
}
{
stack_watch sw;
long count = 0;
for (size_t row = 0; row < row_size; ++row)
for (size_t col = 0; col < col_size; ++col)
{
if (mx.get_type(row, col) == mdds::element_numeric)
++count;
}
cout << "count all values multi-block (" << count << ") : " << sw.get_duration() << " sec (mixed_type_matrix, manual loop)" << endl;
}
{
stack_watch sw;
long count = 0;
mixed_mx_type::const_iterator it = mx.begin(), it_end = mx.end();
for (; it != it_end; ++it)
{
if (it->m_type == mdds::element_numeric)
++count;
}
cout << "count all values multi-block (" << count << ") : " << sw.get_duration() << " sec (mixed_type_matrix, iterator)" << endl;
}
}
{
multi_mx_type mx(row_size, col_size);
double val = 0.0;
vector<double> vals;
vals.reserve(row_size);
for (size_t col = 0; col < col_size; ++col)
{
if ((col % 3) == 0)
continue;
vals.clear();
for (size_t row = 0; row < row_size; ++row)
{
vals.push_back(val);
val += step;
}
mx.set(0, col, vals.begin(), vals.end());
}
{
stack_watch sw;
double sum = sum_manual_loop(mx, row_size, col_size);
cout << "sum all values multi-block (" << sum << ") : " << sw.get_duration() << " sec (multi_type_matrix, manual loop)" << endl;
}
{
stack_watch sw;
sum_all_values func;
mx.walk(func);
cout << "sum all values multi-block (" << func.get() << ") : " << sw.get_duration() << " sec (multi_type_matrix, walk)" << endl;
}
{
stack_watch sw;
count_all_values func;
mx.walk(func);
cout << "count all values multi-block (" << func.get() << ") : " << sw.get_duration() << " sec (multi_type_matrix, walk)" << endl;
}
}
}
void perf_init_with_value()
{
cout << "---" << endl;
size_t row_size = 10000;
size_t col_size = 2000;
double val = 12.3;
{
stack_watch sw;
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_zero);
for (size_t row = 0; row < row_size; ++row)
for (size_t col = 0; col < col_size; ++col)
mx.set(row, col, val);
cout << "init with value: " << sw.get_duration() << " sec (mixed_type_matrix, filled zero, manual loop)" << endl;
}
{
stack_watch sw;
multi_mx_type mx(row_size, col_size, 0.0);
for (size_t row = 0; row < row_size; ++row)
for (size_t col = 0; col < col_size; ++col)
mx.set(row, col, val);
cout << "init with value: " << sw.get_duration() << " sec (multi_type_matrix, manual loop)" << endl;
}
{
stack_watch sw;
multi_mx_type(row_size, col_size, val);
cout << "init with value: " << sw.get_duration() << " sec (multi_type_matrix, constructor)" << endl;
}
{
stack_watch sw;
multi_mx_type mx(row_size, col_size);
vector<double> vals(row_size*col_size, val);
mx.set(0, 0, vals.begin(), vals.end());
cout << "init with value: " << sw.get_duration() << " sec (multi_type_matrix, vector + set)" << endl;
}
}
void perf_heap_vs_array()
{
cout << "---" << endl;
size_t row_size = 20000, col_size = 3000;
{
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_empty);
init_manual_loop(mx, row_size, col_size);
stack_watch sw;
double sum = 0.0;
for (size_t row = 0; row < row_size; ++row)
for (size_t col = 0; col < col_size; ++col)
sum += mx.get_numeric(row, col);
cout << "sum with values on the heap (mixed_type_matrix): " << sw.get_duration() << " sec (" << sum << ")" << endl;
}
{
mixed_mx_type mx(row_size, col_size, mdds::matrix_density_filled_zero);
init_manual_loop(mx, row_size, col_size);
stack_watch sw;
double sum = 0.0;
for (size_t row = 0; row < row_size; ++row)
for (size_t col = 0; col < col_size; ++col)
sum += mx.get_numeric(row, col);
cout << "sum with array values (mixed_type_matrix): " << sw.get_duration() << " sec (" << sum << ")" << endl;
}
{
multi_mx_type mx(row_size, col_size, 0.0);
init_manual_loop(mx, row_size, col_size);
sum_all_values func;
stack_watch sw;
mx.walk(func);
double sum = func.get();
cout << "sum with array values (multi_type_matrix): " << sw.get_duration() << " sec (" << sum << ")" << endl;
}
}
int main()
{
perf_construction();
perf_insertion();
perf_sum_all_values();
perf_sum_all_values_multi_block();
perf_init_with_value();
perf_heap_vs_array();
return EXIT_SUCCESS;
}