Commit 15048e73 authored by Bednárek David RNDr. Ph.D.'s avatar Bednárek David RNDr. Ph.D.
Browse files

Merge branch 'build_test' into 'master'

Matrix assignment; corrected fmwkng

See merge request teaching/nprg054/asgn!12
parents 06a8e47a 72704541
......@@ -11,6 +11,7 @@ include("CMakeConf.cmake")
MAKE_TARGET("MACRO" "macro")
MAKE_TARGET("LEVEN" "leven")
MAKE_TARGET("BSEARCH" "bsearch")
MAKE_TARGET("MATRIX" "matrix")
add_subdirectory ("asgn")
add_subdirectory ("sol")
......@@ -2,6 +2,7 @@
target_include_directories(${TARGET_MACRO} PUBLIC ".")
target_include_directories(${TARGET_LEVEN} PUBLIC ".")
target_include_directories(${TARGET_BSEARCH} PUBLIC ".")
target_include_directories(${TARGET_MATRIX} PUBLIC ".")
target_sources(${TARGET_MACRO} PUBLIC "fmwkng.hpp" "macroasgn.hpp" "macroasgn.cpp" "macromain.cpp")
TARGET_GOLD_SOURCES(${TARGET_MACRO} "macrogold")
......@@ -11,3 +12,6 @@ TARGET_GOLD_SOURCES(${TARGET_LEVEN} "levengold")
target_sources(${TARGET_BSEARCH} PUBLIC "fmwkng.hpp" "bsearchasgn.hpp" "bsearchmain.cpp")
TARGET_GOLD_SOURCES(${TARGET_BSEARCH} "bsearchgold")
target_sources(${TARGET_MATRIX} PUBLIC "fmwkng.hpp" "matrixasgn.hpp" "matrixmain.cpp")
TARGET_GOLD_SOURCES(${TARGET_MATRIX} "matrixgold")
......@@ -162,7 +162,6 @@ namespace fmwkng {
}
void metadata_text(std::ostream& os) const
{
std::size_t s = 0;
for (auto&& a : *this)
{
a->metadata_marker(os);
......@@ -831,7 +830,7 @@ namespace fmwkng {
{
openers.push_back(&*a);
}
for (auto d = depth; d > 0;)
for (auto d = depth; d > 1;) // avoid aggregated version_tag
{
--d;
for (auto&& a : root)
......@@ -878,7 +877,7 @@ namespace fmwkng {
}
virtual std::size_t data_size() const override
{
return 1;
return my_traits::has_data(d_) ? 1 : 0;
}
virtual void data_text(std::ostream& os, std::size_t i) const override
{
......@@ -1911,6 +1910,7 @@ namespace fmwkng {
{
}
using data_type = std::string;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type&d)
{
os << d;
......@@ -1975,6 +1975,11 @@ namespace fmwkng {
{
}
using data_type = std::tuple< std::string, std::string, std::string>;
static bool has_data(const data_type&d)
{
using std::get;
return !get<0>(d).empty() || !get<1>(d).empty() || !get<2>(d).empty();
}
static void data_text(std::ostream& os, const data_type& d)
{
using std::get;
......@@ -1997,14 +2002,13 @@ namespace fmwkng {
return false;
}
template< element_sense sense>
using aggregator = element_t< version_tag, sense>;
static data_type aggregator_data(const data_type& v)
using aggregator = config_element< version_tag, sense>;
static std::monostate aggregator_data(const data_type&)
{
return v;
return {};
}
static void aggregate(data_type&, const data_type&)
static void aggregate(std::monostate&, const data_type&)
{
// the first wins
}
};
......@@ -2034,7 +2038,7 @@ namespace fmwkng {
template< typename platform_tag>
bool check_platform() const
{
static constexpr auto index = config_t::platforms::template index_v<platform_tag>;
static constexpr std::size_t index = config_t::platforms::template index_v<platform_tag>;
return platform_enablers_[index];
}
template< typename F>
......@@ -2042,7 +2046,7 @@ namespace fmwkng {
{
config_t::platforms::for_each([this, &f](auto ps) {
using platform_tag = pass_t<decltype(ps)>;
static constexpr auto index = config_t::platforms::template index_v<platform_tag>;
static constexpr std::size_t index = config_t::platforms::template index_v<platform_tag>;
if (platform_enablers_[index])
{
f(ps);
......@@ -2052,7 +2056,7 @@ namespace fmwkng {
template< typename range_tag>
auto& get_range_config() const
{
static constexpr auto index = config_t::ranges::template index_v<range_tag>;
static constexpr std::size_t index = config_t::ranges::template index_v<range_tag>;
return std::get<index>(range_configs_);
}
template< typename dt_t>
......@@ -2354,7 +2358,7 @@ namespace fmwkng {
{
config_t::platforms::for_each([this, value](auto rs) {
using platform_tag = pass_t<decltype(rs)>;
static constexpr auto index = config_t::platforms::template index_v<platform_tag>;
static constexpr std::size_t index = config_t::platforms::template index_v<platform_tag>;
auto&& cfg = std::get<index>(platform_enablers_);
cfg = (value == platform_tag::name());
});
......@@ -2365,7 +2369,7 @@ namespace fmwkng {
using range_tag = pass_t<decltype(rs)>;
if (name == range_tag::name())
{
static constexpr auto index = config_t::ranges::template index_v<range_tag>;
static constexpr std::size_t index = config_t::ranges::template index_v<range_tag>;
auto&& cfg = std::get<index>(range_configs_);
cfg.config.set_arg(value);
}
......@@ -2375,7 +2379,7 @@ namespace fmwkng {
using platform_tag = pass_t<decltype(rs)>;
if (name == platform_tag::name())
{
static constexpr auto index = config_t::platforms::template index_v<platform_tag>;
static constexpr std::size_t index = config_t::platforms::template index_v<platform_tag>;
auto&& cfg = std::get<index>(platform_enablers_);
if (value == "1" || value == "true" || value == "on")
cfg = true;
......@@ -2456,6 +2460,7 @@ namespace fmwkng {
os << "platform:";
}
using data_type = std::monostate;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type&)
{
os << platform_tag::name();
......@@ -2549,6 +2554,7 @@ namespace fmwkng {
using value_data_type = enumerator_value_t< range_tag>;
using aggregator_data_type = typename range_config_holder< range_tag>::enumerator_t;
using data_type = std::pair< value_data_type, aggregator_data_type>;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << d.first;
......@@ -2597,6 +2603,46 @@ namespace fmwkng {
using aggregator = config_element< range_tag, sense>;
};
template<>
struct config_element_traits< version_tag_category, version_tag>
{
static void metadata_marker_open(std::ostream& os)
{
os << "version:";
}
static void metadata_marker_close(std::ostream& os)
{
os << ".";
}
static bool relevant(element_relevance er)
{
return true; // distinguish aggregation over version_tag
}
using data_type = std::monostate; //typename element_traits_t<version_tag,element_sense::OPEN>::data_type;
static bool has_data(const data_type&) { return 0; }
static void data_text(std::ostream&, const data_type&)
{
}
static void gold_comparison_text(std::ostream& os, const data_type& d, const data_type& gold_d)
{
assert(0);
}
static void code_data(std::ostream& os, const data_type& d)
{
os << "std::monostate()";
}
template< element_sense sense>
using aggregator = config_element< version_tag, sense>;
static data_type aggregator_data(const data_type&)
{
return {};
}
static void aggregate(data_type& r, const data_type& v)
{
// nothing to do with monostate
}
};
template<>
struct config_element_traits< platform_tag_category, all_platforms_tag>
{
......@@ -2613,6 +2659,7 @@ namespace fmwkng {
return true; // distinguish between a particular platform and the aggregate
}
using data_type = std::monostate;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << "all";
......@@ -2653,6 +2700,7 @@ namespace fmwkng {
return true; // distinguish from debug (no thread) mode
}
using data_type = std::monostate;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << "all";
......@@ -2693,6 +2741,7 @@ namespace fmwkng {
return true;
}
using data_type = typename range_config_holder< range_tag>::enumerator_t;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type & d)
{
d.data_text(os);
......@@ -2816,6 +2865,7 @@ namespace fmwkng {
os << "thr:";
}
using data_type = std::size_t;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << d;
......@@ -3051,6 +3101,7 @@ namespace fmwkng {
os << ">";
}
using data_type = clock::duration;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << d.count();
......@@ -3103,6 +3154,7 @@ namespace fmwkng {
return er == element_relevance::TIME;
}
using data_type = std::pair< clock::duration, std::size_t>;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << (d.first.count() / d.second);
......@@ -3193,6 +3245,7 @@ namespace fmwkng {
os << ">";
}
using data_type = typename result_tag::value_type;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << d;
......@@ -3321,10 +3374,10 @@ namespace fmwkng {
template< typename ... range_tags>
struct ranges {
static constexpr auto size_v = sizeof...(range_tags);
static constexpr std::size_t size_v = sizeof...(range_tags);
template< typename tag>
static constexpr auto index_v = impl::index_of< tag, range_tags...>::value;
static constexpr std::size_t index_v = impl::index_of< tag, range_tags...>::value;
using tuple_t = std::tuple< impl::range_config_holder< range_tags> ...>;
......@@ -3366,6 +3419,7 @@ namespace fmwkng {
using data_type = void;
/*
using data_type = std::size_t;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << d;
......@@ -3385,6 +3439,7 @@ namespace fmwkng {
os << measurement_policy::name() << "[ns]]";
}
using data_type = double;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << d;
......@@ -3437,6 +3492,7 @@ namespace fmwkng {
return er == element_relevance::TIME;
}
using data_type = std::pair< double, std::size_t>;
static bool has_data(const data_type&) { return true; }
static void data_text(std::ostream& os, const data_type& d)
{
os << std::exp(d.first / d.second);
......@@ -3542,7 +3598,7 @@ namespace fmwkng {
template< typename range_tag>
auto& get_range_config() const
{
static constexpr auto index = my_ranges::template index_v<range_tag>;
static constexpr std::size_t index = my_ranges::template index_v<range_tag>;
return std::get<index>(range_configs_);
}
......@@ -3571,7 +3627,7 @@ namespace fmwkng {
my_ranges::for_each([this, root, multiplier, divisor](auto p) {
using range_tag = impl::pass_t<decltype(p)>;
using c_type = typename range_config_holder<range_tag>::enumerator_t;
static constexpr auto index = my_ranges::template index_v<range_tag>;
static constexpr std::size_t index = my_ranges::template index_v<range_tag>;
auto&& base_c = root->template get_range_config<range_tag>();
auto&& my_c = std::get<index>(range_configs_);
my_c.config = c_type(base_c.config, multiplier, divisor);
......@@ -3587,7 +3643,7 @@ namespace fmwkng {
my_ranges::for_each([this, thread](auto p) {
using range_tag = impl::pass_t<decltype(p)>;
using my_config_element = config_element< range_tag, element_sense::OPEN>;
static constexpr auto index = my_ranges::template index_v<range_tag>;
static constexpr std::size_t index = my_ranges::template index_v<range_tag>;
auto&& my_c = std::get<index>(range_configs_);
thread->push_element_ptr(std::make_unique<my_config_element>(my_c.config));
});
......@@ -3600,7 +3656,7 @@ namespace fmwkng {
my_ranges::for_each([this, thread](auto p) {
using range_tag = impl::pass_t<decltype(p)>;
using my_config_element = config_element< range_tag, element_sense::CLOSE>;
static constexpr auto index = my_ranges::template index_v<range_tag>;
static constexpr std::size_t index = my_ranges::template index_v<range_tag>;
auto&& my_c = std::get<index>(range_configs_);
thread->push_element_ptr(std::make_unique<my_config_element>());
});
......@@ -3975,10 +4031,10 @@ namespace fmwkng {
template< typename ... platform_tags>
struct platforms {
static constexpr auto size_v = sizeof...(platform_tags);
static constexpr std::size_t size_v = sizeof...(platform_tags);
template< typename tag>
static constexpr auto index_v = impl::index_of< tag, platform_tags...>::value;
static constexpr std::size_t index_v = impl::index_of< tag, platform_tags...>::value;
template< std::size_t index>
using at_t = typename impl::at_position< index, platform_tags...>::type;
......
#ifndef matrixasgn_hpp_
#define matrixasgn_hpp_
#include <cstddef>
#include <memory>
#include <vector>
#include <cassert>
#include <random>
#include <algorithm>
#include "fmwkng.hpp"
namespace matrixasgn {
using matrix_element = std::uint16_t;
inline matrix_element matrix_element_zero()
{
return 0xFFFF;
}
inline matrix_element matrix_element_add_mul(matrix_element c, matrix_element a, matrix_element b)
{
using std::min;
return min((int)c, a + b); // '+' done in int32_t; min() causes saturation
}
template< typename M>
inline std::int_fast64_t chksum(const M& m)
{
std::int_fast64_t chksum = 0;
for (std::size_t i = 0; i < m.vsize(); ++i)
for (std::size_t j = 0; j < m.hsize(); ++j)
{
matrix_element x = m.get(i, j);
chksum = chksum * 3 + (std::int_fast64_t)x;
}
return chksum;
}
template< typename P, typename N>
inline void fill_matrix(P& gen, N& s)
{
for (std::size_t i = 0; i < s.vsize(); ++i)
{
for (std::size_t j = 0; j < s.hsize(); ++j)
{
s.set(i, j, gen.get());
}
}
}
struct policy_zero {
static std::string name() { return "zero"; }
policy_zero(std::size_t seed)
{
}
matrix_element get()
{
return 0;
}
};
const int one = 1000;
struct policy_one {
static std::string name() { return "one"; }
policy_one(std::size_t seed)
{
}
matrix_element get()
{
return matrix_element(one);
}
};
struct policy_random {
static std::string name() { return "random"; }
policy_random(std::size_t seed)
: engine_(seed), ui_(0, 0x7FFF) // avoid overflow for 16-bit add
{
}
matrix_element get()
{
return matrix_element(ui_(engine_));
}
private:
std::mt19937_64 engine_;
fmwkng::well_defined_uniform ui_;
};
struct policy_linear {
static std::string name() { return "linear"; }
policy_linear(std::size_t seed)
: counter(0)
{
}
void reset()
{
counter = 0;
}
matrix_element get()
{
return matrix_element((counter++) & 0x7FFF); // avoid overflow in '+'
}
private:
unsigned counter;
};
template< typename logger, typename CT, typename AT, typename BT>
inline void verify(logger& log, const CT& c, const AT& a, const BT& b)
{
for (std::size_t i = 0; i < c.vsize(); ++i)
for (std::size_t j = 0; j < c.hsize(); ++j)
{
auto cc = matrix_element_zero();
for (std::size_t k = 0; k < a.hsize(); ++k)
{
cc = matrix_element_add_mul(cc, a.get(i, k), b.get(k, j));
}
if (cc != c.get(i, j))
{
log << "VERIFY FAILED: C[" << i << "," << j << "] = " << c.get(i, j) << " EXPECTED " << cc << std::endl;
for (std::size_t k = 0; k < a.hsize(); ++k)
{
auto ccc = matrix_element_add_mul(matrix_element_zero(), a.get(i, k), b.get(k, j));
if (ccc == cc)
{
log << "A[" << i << "," << k << "] = " << a.get(i, k) << " B[" << k << "," << j << "] = " << b.get(k, j)
<< " C = " << ccc << std::endl;
}
}
return;
}
}
log << "VERIFIED." << std::endl;
}
}
namespace matrixsol {
//struct policy_scalar;
struct policy_sse;
struct policy_avx;
struct policy_avx512;
}
namespace matrixmain {
/*
struct platform_scalar {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "scalar"; }
static auto code_name() { return "matrixmain::platform_scalar"; }
using policy = matrixsol::policy_scalar;
};
*/
struct platform_sse {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "sse"; }
static auto code_name() { return "matrixmain::platform_sse"; }
using policy = matrixsol::policy_sse;
};
struct platform_avx {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "avx"; }
static auto code_name() { return "matrixmain::platform_avx"; }
using policy = matrixsol::policy_avx;
};
struct platform_avx512 {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "avx512"; }
static auto code_name() { return "matrixmain::platform_avx512"; }
using policy = matrixsol::policy_avx512;
};
struct size {
using tag_category = fmwkng::range_tag_category;
static auto name() { return "size"; }
static auto code_name() { return "matrixmain::size"; }
static auto enumerator() {
return fmwkng::logarithmic(
0x40,
#ifdef NDEBUG
0x400,
#else
0x40,
#endif
0x2
);
}
};
struct repeats {
using tag_category = fmwkng::range_tag_category;
static auto name() { return "repeats"; }
static auto code_name() { return "matrixmain::repeats"; }
static auto enumerator() {
return fmwkng::auto_repeat(
#ifdef NDEBUG
0x1000000
#else
0x80000
#endif
);
}
};
struct repeat_policy {
using ranges = fmwkng::ranges< repeats>;
static auto name() { return "time_per_cell"; }
static auto code_name() { return "matrixmain::repeat_policy"; }
template< typename CTX>
static auto complexity(CTX&& ctx)
{
return (std::uint_fast64_t)fmwkng::get<size>(ctx) * fmwkng::get<size>(ctx) * fmwkng::get<size>(ctx);
}
static constexpr fmwkng::average_t minimum_count =
#ifdef NDEBUG
1000000000ULL
#else
100000000ULL
#endif
;
};
struct chksum {
using tag_category = fmwkng::result_tag_category;
static auto name() { return "chksum"; }
static auto code_name() { return "matrixmain::chksum"; }
using value_type = std::size_t;
};
struct root_config {
static auto code_name() { return "matrixmain::root_config"; }
static auto code_header_name() { return "matrixasgn.hpp"; }
static auto code_namespace_name() { return "matrixmain"; }
using platforms = fmwkng::platforms<
/*
platform_scalar
,
*/
platform_sse
#ifdef USE_AVX
, platform_avx
#endif
#ifdef USE_AVX512
, platform_avx512
#endif
>;
using ranges = fmwkng::ranges<size, repeats>;
};
fmwkng::gold_holder& gold_master();
}
#endif
This diff is collapsed.
This diff is collapsed.