#include <LoadBalancerP2.hpp>
#include <primecount-internal.hpp>
#include <imath.hpp>
#include <min.hpp>
#include <stdint.h>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <iomanip>
namespace primecount {
LoadBalancerP2::LoadBalancerP2(maxint_t x,
int64_t sieve_limit,
int threads,
bool is_print) :
low_(isqrt(x)),
sieve_limit_(sieve_limit),
precision_(get_status_precision(x)),
is_print_(is_print)
{
int64_t chunks_per_thread = 8;
int64_t O_primepi = (int64_t) std::pow(sieve_limit, 2.0 / 3.0);
min_thread_dist_ = O_primepi * 10;
min_thread_dist_ = max(min_thread_dist_, 1 << 22);
low_ = min(low_, sieve_limit_);
int64_t dist = sieve_limit_ - low_;
thread_dist_ = dist / (threads * chunks_per_thread);
thread_dist_ = max(min_thread_dist_, thread_dist_);
threads_ = ideal_num_threads(threads, dist, thread_dist_);
}
int LoadBalancerP2::get_threads() const
{
return threads_;
}
bool LoadBalancerP2::get_work(int64_t& low, int64_t& high)
{
LockGuard lockGuard(lock_);
print_status();
low_ = min(low_, sieve_limit_);
int64_t dist = sieve_limit_ - low_;
if (threads_ == 1)
{
if (!is_print_)
thread_dist_ = dist;
}
else
{
int64_t max_thread_dist = dist / threads_;
if (thread_dist_ > max_thread_dist)
thread_dist_ = max(min_thread_dist_, max_thread_dist);
}
low = low_;
low_ += thread_dist_;
low_ = min(low_, sieve_limit_);
high = low_;
return low < sieve_limit_;
}
void LoadBalancerP2::print_status()
{
if (is_print_)
{
double time = get_time();
double old = time_;
double threshold = 0.1;
if ((time - old) >= threshold)
{
time_ = time;
std::cout << "\rStatus: " << std::fixed << std::setprecision(precision_)
<< get_percent(low_, sieve_limit_) << '%' << std::flush;
}
}
}
}