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

Merge branch 'build_test' into 'master'

bsearch

See merge request teaching/nprg054/asgn!10
parents 05d761fd 054942c0
......@@ -10,6 +10,7 @@ include("CMakeConf.cmake")
MAKE_TARGET("MACRO" "macro")
MAKE_TARGET("LEVEN" "leven")
MAKE_TARGET("BSEARCH" "bsearch")
add_subdirectory ("asgn")
add_subdirectory ("sol")
target_include_directories(${TARGET_MACRO} PUBLIC ".")
target_include_directories(${TARGET_LEVEN} PUBLIC ".")
target_include_directories(${TARGET_BSEARCH} PUBLIC ".")
target_sources(${TARGET_MACRO} PUBLIC "fmwkng.hpp" "macroasgn.hpp" "macroasgn.cpp" "macromain.cpp")
TARGET_GOLD_SOURCES(${TARGET_MACRO} "macrogold")
target_sources(${TARGET_LEVEN} PUBLIC "fmwkng.hpp" "levenasgn.hpp" "levenmain.cpp")
TARGET_GOLD_SOURCES(${TARGET_LEVEN} "levengold")
target_sources(${TARGET_BSEARCH} PUBLIC "fmwkng.hpp" "bsearchasgn.hpp" "bsearchmain.cpp")
TARGET_GOLD_SOURCES(${TARGET_BSEARCH} "bsearchgold")
#ifndef bsearchasgn_hpp_
#define bsearchasgn_hpp_
#include <cstddef>
#include <memory>
#include <vector>
#include <cassert>
#include <random>
#include "fmwkng.hpp"
//#include <emmintrin.h>
///////////////////////////////
namespace bsearchasgn {
using data_element = std::int32_t;
struct core_generator {
template< typename E>
core_generator(std::size_t opsize, E&& engine)
: data_(opsize)
{
fmwkng::well_defined_uniform uni(0, 0x7FFFFFFF);
for (std::size_t j = 0; j < opsize; ++j)
{
data_[j] = data_element(uni(engine));
}
}
std::vector< data_element> data_;
};
struct core_generator_sorted : public core_generator {
template< typename E>
core_generator_sorted(std::size_t opsize, E&& engine)
: core_generator(opsize, std::forward<E>(engine))
{
std::sort(data_.begin(), data_.end());
}
};
struct generator_inner {
const data_element* inner_data() const
{
return inner_data_.data_.data();
}
std::size_t inner_size() const
{
return inner_data_.data_.size();
}
generator_inner(std::uint_fast64_t seed, std::size_t isize)
: engine_(seed),
inner_data_(isize, engine_)
{
}
private:
std::mt19937_64 engine_;
core_generator_sorted inner_data_;
};
struct generator_outer {
const data_element* outer_data() const
{
return outer_data_.data_.data();
}
std::size_t outer_size() const
{
return outer_data_.data_.size();
}
generator_outer(std::uint_fast64_t seed, std::size_t osize)
: engine_(seed),
outer_data_(osize, engine_)
{
}
private:
std::mt19937_64 engine_;
core_generator outer_data_;
};
inline void check_low(std::ostream& log, const data_element* bd, std::size_t bs, data_element cmp, std::size_t k)
{
for (std::size_t j = 0; j < bs; ++j)
{
if (bd[j] < cmp)
{
log << "Too low value at bucket[" << k << "][" << j << "]" << std::endl;
}
}
}
inline void check_high(std::ostream& log, const data_element* bd, std::size_t bs, data_element cmp, std::size_t k)
{
for (std::size_t j = 0; j < bs; ++j)
{
if (bd[j] >= cmp)
{
log << "Too high value at bucket[" << k << "][" << j << "]" << std::endl;
}
}
}
template< typename D>
inline void final_check(std::ostream & log, const generator_inner& igen, const generator_outer& ogen, const D& output)
{
std::size_t total = 0;
{
// inspect first bucket
std::pair< const data_element*, std::size_t> rv = output.bucket(0);
check_high(log, rv.first, rv.second, igen.inner_data()[0], 0);
total += rv.second;
}
for (std::size_t k = 1; k < igen.inner_size(); ++k)
{
// inspect k-th bucket
std::pair< const data_element*, std::size_t> rv = output.bucket(k);
check_low(log, rv.first, rv.second, igen.inner_data()[k - 1], k);
check_high(log, rv.first, rv.second, igen.inner_data()[k], k);
total += rv.second;
}
{
// inspect last bucket
std::pair< const data_element*, std::size_t> rv = output.bucket(igen.inner_size());
check_low(log, rv.first, rv.second, igen.inner_data()[igen.inner_size() - 1], igen.inner_size());
total += rv.second;
}
if (total != ogen.outer_size())
{
log << "TOTAL SIZE OF BUCKETS " << total << " DOES NOT MATCH OUTER DATA SIZE " << ogen.outer_size() << std::endl;
}
}
template< typename D>
inline std::uint_fast64_t chksum(const generator_inner& igen, const D& output)
{
std::uint_fast64_t total = 0;
for (std::size_t k = 0; k <= igen.inner_size(); ++k)
{
// inspect k-th bucket
std::pair< const data_element*, std::size_t> rv = output.bucket(k);
std::uint_fast64_t chash = 0;
for (std::size_t i = 0; i < rv.second; ++i)
{
static constexpr auto prime = (std::uint_fast64_t(1) << 61) - 1;
auto v = rv.first[i];
chash += prime / v;
}
total = (total << 7) ^ (total >> 57) ^ chash;
}
return total;
}
}
namespace bsearchsol {
struct policy_scalar;
struct policy_sse;
struct policy_avx;
struct policy_avx512;
};
namespace bsearchmain {
struct platform_scalar {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "scalar"; }
static auto code_name() { return "bsearchmain::platform_scalar"; }
using policy = bsearchsol::policy_scalar;
};
struct platform_sse {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "sse"; }
static auto code_name() { return "bsearchmain::platform_sse"; }
using policy = bsearchsol::policy_sse;
};
struct platform_avx {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "avx"; }
static auto code_name() { return "bsearchmain::platform_avx"; }
using policy = bsearchsol::policy_avx;
};
struct platform_avx512 {
using tag_category = fmwkng::platform_tag_category;
static auto name() { return "avx512"; }
static auto code_name() { return "bsearchmain::platform_avx512"; }
using policy = bsearchsol::policy_avx512;
};
struct isize {
using tag_category = fmwkng::range_tag_category;
static auto name() { return "isize"; }
static auto code_name() { return "bsearchmain::isize"; }
static auto enumerator() {
return fmwkng::logarithmic(
0x40,
#ifdef NDEBUG
0x100000,
#else
0x4000,
#endif
#ifdef NDEBUG
0x4
#else
0x10
#endif
);
}
};
struct osize {
using tag_category = fmwkng::range_tag_category;
static auto name() { return "osize"; }
static auto code_name() { return "bsearchmain::osize"; }
static auto enumerator() {
return fmwkng::logarithmic(
0x400,
#ifdef NDEBUG
0x40000,
#else
0x4000,
#endif
0x10
);
}
};
struct repeats {
using tag_category = fmwkng::range_tag_category;
static auto name() { return "repeats"; }
static auto code_name() { return "bsearchmain::repeats"; }
static auto enumerator() {
return fmwkng::auto_repeat(
#ifdef NDEBUG
0x1000000
#else
0x10000
#endif
);
}
};
inline std::size_t log2(std::size_t s)
{
std::size_t i = 0;
for (; s; s >>= 1)
++i;
return i;
}
struct repeat_policy {
using ranges = fmwkng::ranges< repeats>;
static auto name() { return "time_per_comparison"; }
static auto code_name() { return "bsearchmain::repeat_policy"; }
template< typename CTX>
static auto complexity(CTX&& ctx)
{
return (std::uint_fast64_t)log2(fmwkng::get<isize>(ctx)) * fmwkng::get<osize>(ctx) + fmwkng::get<isize>(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 "bsearchmain::chksum"; }
using value_type = std::size_t;
};
struct root_config {
static auto code_name() { return "bsearchmain::root_config"; }
static auto code_header_name() { return "bsearchasgn.hpp"; }
static auto code_namespace_name() { return "bsearchmain"; }
using platforms = fmwkng::platforms<
platform_scalar
,
platform_sse
#ifdef USE_AVX
, platform_avx
#endif
#ifdef USE_AVX512
, platform_avx512
#endif
>;
using ranges = fmwkng::ranges<isize, osize, repeats>;
};
fmwkng::gold_holder& gold_master();
}
#endif
This diff is collapsed.
This diff is collapsed.
#include "fmwkng.hpp"
#include "bsearchasgn.hpp"
namespace bsearchmain {
static fmwkng::gold_pair gr_1()
{
fmwkng::gold_pair rv;
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<fmwkng::all_platforms_tag,fmwkng::impl::element_sense::OPEN>>(std::monostate()));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(fmwkng::logarithmic(64,16384,16)));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(fmwkng::logarithmic(1024,16384,16)));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(9));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(1730852694183081859U));
return rv;
}
static fmwkng::impl::element_list gp_1()
{
fmwkng::impl::element_list rv;
return rv;
}
static fmwkng::gold_pair gr_1_1()
{
fmwkng::gold_pair rv;
rv.key = gp_1();
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(fmwkng::logarithmic(64,16384,16)));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(fmwkng::logarithmic(1024,16384,16)));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(9));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(1730852694183081859U));
return rv;
}
static fmwkng::impl::element_list gp_1_1()
{
fmwkng::impl::element_list rv = gp_1();
return rv;
}
static fmwkng::gold_pair gr_1_1_1()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(64,fmwkng::logarithmic(64,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(fmwkng::logarithmic(1024,16384,16)));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(9));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(1730852694183081859U));
return rv;
}
static fmwkng::impl::element_list gp_1_1_1()
{
fmwkng::impl::element_list rv = gp_1_1();
rv.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(64,fmwkng::logarithmic(64,16384,16))));
return rv;
}
static fmwkng::gold_pair gr_1_1_1_1()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1_1();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(1024,fmwkng::logarithmic(1024,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(9));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(1730852694183081859U));
return rv;
}
static fmwkng::gold_pair gr_1_1_1_2()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1_1();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(16384,fmwkng::logarithmic(1024,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(1));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(17681662555332696405U));
return rv;
}
static fmwkng::gold_pair gr_1_1_2()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(1024,fmwkng::logarithmic(64,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(fmwkng::logarithmic(1024,16384,16)));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(5));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(7971570962169211603U));
return rv;
}
static fmwkng::impl::element_list gp_1_1_2()
{
fmwkng::impl::element_list rv = gp_1_1();
rv.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(1024,fmwkng::logarithmic(64,16384,16))));
return rv;
}
static fmwkng::gold_pair gr_1_1_2_1()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1_2();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(1024,fmwkng::logarithmic(1024,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(5));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(7971570962169211603U));
return rv;
}
static fmwkng::gold_pair gr_1_1_2_2()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1_2();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(16384,fmwkng::logarithmic(1024,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(1));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(11235176029046567341U));
return rv;
}
static fmwkng::gold_pair gr_1_1_3()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(16384,fmwkng::logarithmic(64,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(fmwkng::logarithmic(1024,16384,16)));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(2));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(17171989284742472370U));
return rv;
}
static fmwkng::impl::element_list gp_1_1_3()
{
fmwkng::impl::element_list rv = gp_1_1();
rv.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::isize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(16384,fmwkng::logarithmic(64,16384,16))));
return rv;
}
static fmwkng::gold_pair gr_1_1_3_1()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1_3();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(1024,fmwkng::logarithmic(1024,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(2));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(17171989284742472370U));
return rv;
}
static fmwkng::gold_pair gr_1_1_3_2()
{
fmwkng::gold_pair rv;
rv.key = gp_1_1_3();
rv.key.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::osize,fmwkng::impl::element_sense::OPEN>>(std::make_pair(16384,fmwkng::logarithmic(1024,16384,16))));
rv.key.push_back(std::make_unique<fmwkng::impl::config_element<bsearchmain::repeats,fmwkng::impl::element_sense::OPEN>>(1));
rv.value.push_back(std::make_unique<fmwkng::impl::element_t<bsearchmain::chksum,fmwkng::impl::element_sense::CLOSE>>(16336879692101326291U));
return rv;
}
static fmwkng::gold_data gold_results_()
{
fmwkng::gold_data rv;
rv.insert(gr_1_1_1_1());
rv.insert(gr_1_1_1_2());
rv.insert(gr_1_1_1());
rv.insert(gr_1_1_2_1());
rv.insert(gr_1_1_2_2());
rv.insert(gr_1_1_2());
rv.insert(gr_1_1_3_1());
rv.insert(gr_1_1_3_2());
rv.insert(gr_1_1_3());
rv.insert(gr_1_1());
rv.insert(gr_1());
return rv;
}
static fmwkng::gold_holder gh_(gold_master(), gold_results_);
}
This diff is collapsed.
This diff is collapsed.
#include "bsearchsol.hpp"
#include "bsearchasgn.hpp"
#include "fmwkng.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
///////////////////////////////
///////////////////////////////
///////////////////////////////
namespace bsearchmain {
template< typename policy>
struct run_thread_ftor {
run_thread_ftor(const bsearchasgn::generator_inner & igen, const bsearchsol::bsearch_inner<policy> & idata)
: igen(igen), idata(idata)
{}
template< typename CTX>
void operator()(CTX&& ctx2) const
{
using namespace fmwkng;
for (auto&& ctx4 : for_range<osize>(ctx2))
{
bsearchasgn::generator_outer ogen(
std::mt19937_64::default_seed + 1 + ctx4.thread_index(),
get<osize>(ctx4));
bsearchsol::bsearch_outer<policy> odata(idata, ogen.outer_size());
for (auto&& ctx5 : auto_measurement<repeat_policy>(ctx4, 1024))
{
for (auto i : for_index<repeats>(ctx5))
{
odata.bucketize(ogen.outer_data());
}
if (stop_for_results(ctx5))
{
#ifndef NDEBUG
bsearchasgn::final_check(std::cerr, igen, ogen, odata);
#endif
auto h = bsearchasgn::chksum(igen, odata);
store_result<chksum>(ctx5, h);
}
}
}
}
const bsearchasgn::generator_inner& igen;
const bsearchsol::bsearch_inner<policy>& idata;
};
struct run_platform_ftor {
template< typename CTX>
void operator()(CTX&& ctx1) const
{
using namespace fmwkng;
using policy = typename platform_t<decltype(ctx1)>::policy;
for (auto&& ctx3 : for_range<isize>(ctx1))
{
bsearchasgn::generator_inner igen(
std::mt19937_64::default_seed,
get<isize>(ctx3));
bsearchsol::bsearch_inner<policy> idata(igen.inner_data(), igen.inner_size());
#ifdef NDEBUG
for_parallel(ctx3, run_thread_ftor<policy>(igen, idata));
#else
run_thread_ftor<policy>(igen, idata)(ctx3);
#endif
}
}
};
fmwkng::gold_holder& gold_master()
{
static fmwkng::gold_holder the;
return the;
}
}
///////////////////////////////
int main( int argc, char * * argv)
{
using namespace fmwkng;
root<bsearchmain::root_config> ctx1(argc, argv, bsearchmain::gold_master().collect());
//std::cout << "Running..." << std::endl;
for_platforms(ctx1, bsearchmain::run_platform_ftor());
//std::cout << "Done." << std::endl;
return 0;
}
///////////////////////////////