Commit c66b23a2 authored by Christoph Conrads's avatar Christoph Conrads

Update, improve ranlux-tools vs C++11 benchmark

parent d4e801a9
......@@ -4,8 +4,8 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
#include "benchmark.hpp"
#include <cassert>
#include "random-number-engine.hpp"
#include <cstdio>
#include <cstdint>
#include <ctime>
......@@ -18,138 +18,18 @@
namespace rlxt = ranlux_tools;
using awc16_base = rlxt::add_with_carry_engine<std::uint16_t, 16, 2, 9>;
using awc16 = std::discard_block_engine<awc16_base, 97, 9>;
using fast_awc16 = std::discard_block_engine<awc16_base, 23, 9>;
// do not use `clock()` because it does not work on raspberry pi
timespec get_cpu_time()
{
timespec tm = { 0, 0 };
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tm);
return tm;
}
std::uintmax_t get_time_nsec(const timespec& tm)
{
return tm.tv_nsec + std::uintmax_t{1000*1000*1000} * tm.tv_sec;
}
struct dummy_engine
{
using result_type = std::uint32_t;
static constexpr result_type max()
{ return std::numeric_limits<result_type>::max(); }
static constexpr result_type min()
{ return std::numeric_limits<result_type>::min(); }
result_type operator() ();
result_type state_ = 0;
};
dummy_engine::result_type dummy_engine::operator() () { return state_++; }
std::string get_name(const dummy_engine&) { return "dummy-prng"; }
std::string get_name(const std::mt19937&) { return "std::mt19937"; }
std::string get_name(const std::mt19937_64&) { return "std::mt19937_64"; }
std::string get_name(const std::ranlux24&) { return "std::ranlux24"; }
std::string get_name(const std::ranlux48&) { return "std::ranlux48"; }
std::string get_name(const ranlux_tools::xoshiro128plus&)
{
return "xoshiro128+";
}
template<typename T, std::size_t W, std::size_t S, std::size_t R>
std::string get_name(const ranlux_tools::add_with_carry_engine<T, W, S, R>&
)
{
constexpr auto FORMAT = "AWC(2^%-2zu, %2zu, %1zu)";
char buffer[80] = { 0 };
snprintf(buffer, sizeof(buffer), FORMAT, W, R, S);
return buffer;
}
using awc32_base = rlxt::add_with_carry_engine<std::uint32_t, 32, 3, 16>;
using awc32 = std::discard_block_engine<awc32_base, 277, 16>;
using fast_awc32 = std::discard_block_engine<awc32_base, 71, 16>;
using swb64_base = rlxt::subtract_with_borrow_engine<std::uint64_t, 64, 62, 3>;
using swb64 = std::discard_block_engine<swb64_base, 1303, 62>;
using fast_swb64 = std::discard_block_engine<swb64_base, 331, 62>;
template<typename T, std::size_t W, std::size_t P, std::size_t Q>
std::string get_name(
const ranlux_tools::subtract_with_borrow_engine<T, W, P, Q>&
)
{
constexpr auto FORMAT = "SWB(2^%-2zu, %2zu, %1zu)";
char buffer[80] = { 0 };
snprintf(buffer, sizeof(buffer), FORMAT, W, P, Q);
return buffer;
}
template<typename Generator, std::size_t P, std::size_t Q>
std::string get_name(const std::discard_block_engine<Generator, P, Q>& gen)
{
auto name = get_name(gen.base());
constexpr auto FORMAT = "[%4zu,%2zu]";
char buffer[80] = { 0 };
snprintf(buffer, sizeof(buffer), FORMAT, P, Q);
return name + buffer;
}
template<typename Generator>
typename Generator::result_type draw(Generator& gen) __attribute__((noinline));
template<typename Generator>
typename Generator::result_type draw(Generator& gen)
{
return gen();
}
template<typename Generator>
void run(std::uintmax_t num_draws)
{
static_assert(Generator::min() == 0, "");
auto w =
Generator::max() == std::numeric_limits<std::uint64_t>::max() ? 8u :
Generator::max() == (1ull<<48) - 1u ? 6u :
Generator::max() == std::numeric_limits<std::uint32_t>::max() ? 4u :
Generator::max() == (1u<<24) - 1u ? 3u :
Generator::max() == std::numeric_limits<std::uint16_t>::max() ? 2u :
Generator::max() == std::numeric_limits<std::uint8_t>::max() ? 1u : 0u
;
auto gen = Generator();
auto t_0 = get_cpu_time();
for(auto i = std::uintmax_t{0}; i < num_draws; ++i)
draw(gen);
auto t_1 = get_cpu_time();
auto t_nsec = get_time_nsec(t_1) - get_time_nsec(t_0);
auto t_msec = t_nsec / (1000u*1000u);
auto bytes_per_msec = w * num_draws * 1000u / double(t_msec);
auto name = get_name(gen);
auto dummy = std::uint16_t(gen());
std::printf(
"%-25s | %10ju | %20.2e | %hu\n",
name.c_str(), t_msec, bytes_per_msec, dummy
);
}
int main()
......@@ -157,25 +37,20 @@ int main()
constexpr auto num_draws = std::uintmax_t{1000} * 1000u * 1000u;
std::printf(
"%-25s | %10s | %20s | %s\n",
"%-26s | %10s | %20s | %s\n",
"generator", "time(sec)", "throughput(byte/sec)", "dummy"
);
run<rlxt::ranlux8_base>(num_draws);
run<rlxt::ranlux16_base>(num_draws);
run<rlxt::ranlux32_base>(num_draws);
run<rlxt::ranlux64_base>(num_draws);
run<rlxt::fast_ranlux8>(num_draws);
run<rlxt::fast_ranlux16>(num_draws);
run<rlxt::fast_ranlux32>(num_draws);
run<rlxt::fast_ranlux64>(num_draws);
run<rlxt::ranlux8>(num_draws);
run<rlxt::ranlux16>(num_draws);
run<rlxt::ranlux32>(num_draws);
run<rlxt::ranlux64>(num_draws);
run<std::ranlux24>(num_draws);
run<std::ranlux48>(num_draws);
run<std::mt19937>(num_draws);
run<std::mt19937_64>(num_draws);
run<rlxt::xoshiro128plus>(num_draws);
rlxt::run<rlxt::dummy_engine>(num_draws);
rlxt::run<fast_awc16>(num_draws);
rlxt::run<fast_awc32>(num_draws);
rlxt::run<fast_swb64>(num_draws);
rlxt::run<awc16>(num_draws);
rlxt::run<awc32>(num_draws);
rlxt::run<swb64>(num_draws);
rlxt::run<std::ranlux24>(num_draws);
rlxt::run<std::ranlux48>(num_draws);
rlxt::run<std::mt19937>(num_draws);
rlxt::run<std::mt19937_64>(num_draws);
rlxt::run<rlxt::xoshiro128plus>(num_draws);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment