[thin] Adopt stateful random number generators

This commit is contained in:
Ming-Hung Tsai 2020-08-04 11:45:36 +08:00
parent 06dfb976c2
commit 3f19818c56
3 changed files with 39 additions and 9 deletions

View File

@ -1,5 +1,7 @@
#include "base/io_generator.h" #include "base/io_generator.h"
#include "base/sequence_generator.h" #include "base/sequence_generator.h"
#include <chrono>
#include <random>
#include <stdexcept> #include <stdexcept>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
@ -31,19 +33,23 @@ namespace {
typedef std::shared_ptr<op_generator> ptr; typedef std::shared_ptr<op_generator> ptr;
op_generator(base::req_op op1) op_generator(base::req_op op1)
: op1_(op1), op2_(op1), op1_pct_(100) { : op1_(op1), op2_(op1), op1_pct_(100),
rand_seed_(std::chrono::high_resolution_clock::now().time_since_epoch().count()),
op_engine_(rand_seed_) {
} }
op_generator(base::req_op op1, op_generator(base::req_op op1,
base::req_op op2, base::req_op op2,
unsigned op1_pct) unsigned op1_pct)
: op1_(op1), op2_(op2), op1_pct_(op1_pct) { : op1_(op1), op2_(op2), op1_pct_(op1_pct),
rand_seed_(std::chrono::high_resolution_clock::now().time_since_epoch().count()),
op_engine_(rand_seed_) {
if (op1_pct > 100) if (op1_pct > 100)
throw std::runtime_error("invalid percentage"); throw std::runtime_error("invalid percentage");
} }
base::req_op next_op() { base::req_op next_op() {
if (static_cast<unsigned>(std::rand()) % 100 > op1_pct_) if (op_engine_() % 100 > op1_pct_)
return op2_; return op2_;
return op1_; return op1_;
} }
@ -52,6 +58,9 @@ namespace {
base::req_op op1_; base::req_op op1_;
base::req_op op2_; base::req_op op2_;
unsigned op1_pct_; unsigned op1_pct_;
uint64_t rand_seed_;
std::mt19937 op_engine_;
}; };
//-------------------------------- //--------------------------------

View File

@ -1,5 +1,7 @@
#include "base/run_set.h" #include "base/run_set.h"
#include "base/sequence_generator.h" #include "base/sequence_generator.h"
#include <chrono>
#include <random>
#include <stdexcept> #include <stdexcept>
//---------------------------------------------------------------- //----------------------------------------------------------------
@ -80,6 +82,9 @@ namespace {
: begin_(begin), : begin_(begin),
step_(step), step_(step),
max_forward_steps_(seq_nr), max_forward_steps_(seq_nr),
rand_seed_(std::chrono::high_resolution_clock::now().time_since_epoch().count()),
results_engine_(rand_seed_),
steps_engine_(rand_seed_),
nr_generated_(0) nr_generated_(0)
{ {
if (!size || !step || !seq_nr) if (!size || !step || !seq_nr)
@ -93,9 +98,15 @@ namespace {
if (!max_forward_steps_ || max_forward_steps_ > nr_steps_) if (!max_forward_steps_ || max_forward_steps_ > nr_steps_)
throw std::runtime_error("invalid number of forward steps"); throw std::runtime_error("invalid number of forward steps");
if (max_forward_steps_ > 1) results_distr_ = std::uniform_int_distribution<uint64_t>(0,
nr_steps_ - 1);
if (max_forward_steps_ > 1) {
steps_distr_ = std::uniform_int_distribution<uint64_t>(1,
max_forward_steps_);
reset_forward_generator(); reset_forward_generator();
} }
}
uint64_t next() { uint64_t next() {
// FIXME: eliminate if-else // FIXME: eliminate if-else
@ -109,7 +120,7 @@ namespace {
void reset_forward_generator() { void reset_forward_generator() {
uint64_t begin = peek_random_step(); uint64_t begin = peek_random_step();
unsigned seq_nr = (std::rand() % max_forward_steps_) + 1; unsigned seq_nr = steps_distr_(steps_engine_);
base::run_set<uint64_t>::const_iterator it = rand_map_.upper_bound(begin); base::run_set<uint64_t>::const_iterator it = rand_map_.upper_bound(begin);
if (it != rand_map_.end()) if (it != rand_map_.end())
seq_nr = std::min<uint64_t>(seq_nr, *it->begin_ - begin); seq_nr = std::min<uint64_t>(seq_nr, *it->begin_ - begin);
@ -148,12 +159,13 @@ namespace {
} }
} }
uint64_t peek_random_step() const { // TODO: improve the complexity of generating unique sequence
uint64_t peek_random_step() {
uint64_t step_idx; uint64_t step_idx;
bool found = true; bool found = true;
while (found) { while (found) {
step_idx = std::rand() % nr_steps_; step_idx = results_distr_(results_engine_);
found = rand_map_.member(step_idx); found = rand_map_.member(step_idx);
} }
@ -164,7 +176,12 @@ namespace {
uint64_t nr_steps_; uint64_t nr_steps_;
uint64_t step_; uint64_t step_;
unsigned max_forward_steps_; unsigned max_forward_steps_;
uint64_t rand_seed_;
std::mt19937_64 results_engine_;
std::mt19937_64 steps_engine_;
std::uniform_int_distribution<uint64_t> results_distr_;
std::uniform_int_distribution<uint64_t> steps_distr_;
base::run_set<uint64_t> rand_map_; base::run_set<uint64_t> rand_map_;
uint64_t nr_generated_; uint64_t nr_generated_;
forward_sequence_generator forward_gen_; forward_sequence_generator forward_gen_;

View File

@ -1,3 +1,5 @@
#include <chrono>
#include <random>
#include "damage_generator.h" #include "damage_generator.h"
using namespace thin_provisioning; using namespace thin_provisioning;
@ -13,12 +15,14 @@ namespace {
base::run_set<block_address> visited; base::run_set<block_address> visited;
block_address nr_visited = 0; block_address nr_visited = 0;
srand(time(NULL)); uint64_t rand_seed(std::chrono::high_resolution_clock::now().time_since_epoch().count());
std::mt19937 rand_engine(rand_seed);
while (nr_blocks) { while (nr_blocks) {
if (nr_visited == sm_size) if (nr_visited == sm_size)
break; break;
block_address b = rand() % sm_size; block_address b = rand_engine() % sm_size;
if (visited.member(b)) if (visited.member(b))
continue; continue;