Linkgraph: Fix numeric overflow in cost estimate/duration multiplier.
Bump cost estimate type to 64 bits
This commit is contained in:
@@ -524,8 +524,8 @@ public:
|
|||||||
NodeID AddNode(const Station *st);
|
NodeID AddNode(const Station *st);
|
||||||
void RemoveNode(NodeID id);
|
void RemoveNode(NodeID id);
|
||||||
|
|
||||||
inline uint CalculateCostEstimate() const {
|
inline uint64 CalculateCostEstimate() const {
|
||||||
uint64_t size_squared = this->Size() * this->Size();
|
uint64 size_squared = this->Size() * this->Size();
|
||||||
return size_squared * FindLastBit(size_squared * size_squared); // N^2 * 4log_2(N)
|
return size_squared * FindLastBit(size_squared * size_squared); // N^2 * 4log_2(N)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -46,7 +46,7 @@ void LinkGraphSchedule::SpawnNext()
|
|||||||
if (this->schedule.empty()) return;
|
if (this->schedule.empty()) return;
|
||||||
|
|
||||||
GraphList schedule_to_back;
|
GraphList schedule_to_back;
|
||||||
uint total_cost = 0;
|
uint64 total_cost = 0;
|
||||||
for (auto iter = this->schedule.begin(); iter != this->schedule.end();) {
|
for (auto iter = this->schedule.begin(); iter != this->schedule.end();) {
|
||||||
auto current = iter;
|
auto current = iter;
|
||||||
++iter;
|
++iter;
|
||||||
@@ -62,22 +62,22 @@ void LinkGraphSchedule::SpawnNext()
|
|||||||
total_cost += it->Graph().CalculateCostEstimate();
|
total_cost += it->Graph().CalculateCostEstimate();
|
||||||
}
|
}
|
||||||
uint scaling = 1 + FindLastBit(total_cost);
|
uint scaling = 1 + FindLastBit(total_cost);
|
||||||
uint cost_budget = total_cost / scaling;
|
uint64 cost_budget = total_cost / scaling;
|
||||||
uint used_budget = 0;
|
uint64 used_budget = 0;
|
||||||
std::vector<LinkGraphJobGroup::JobInfo> jobs_to_execute;
|
std::vector<LinkGraphJobGroup::JobInfo> jobs_to_execute;
|
||||||
while (used_budget < cost_budget && !this->schedule.empty()) {
|
while (used_budget < cost_budget && !this->schedule.empty()) {
|
||||||
LinkGraph *lg = this->schedule.front();
|
LinkGraph *lg = this->schedule.front();
|
||||||
assert(lg == LinkGraph::Get(lg->index));
|
assert(lg == LinkGraph::Get(lg->index));
|
||||||
this->schedule.pop_front();
|
this->schedule.pop_front();
|
||||||
uint cost = lg->CalculateCostEstimate();
|
uint64 cost = lg->CalculateCostEstimate();
|
||||||
used_budget += cost;
|
used_budget += cost;
|
||||||
if (LinkGraphJob::CanAllocateItem()) {
|
if (LinkGraphJob::CanAllocateItem()) {
|
||||||
uint duration_multiplier = CeilDiv(scaling * cost, total_cost);
|
uint duration_multiplier = CeilDivT<uint64_t>(scaling * cost, total_cost);
|
||||||
std::unique_ptr<LinkGraphJob> job(new LinkGraphJob(*lg, duration_multiplier));
|
std::unique_ptr<LinkGraphJob> job(new LinkGraphJob(*lg, duration_multiplier));
|
||||||
jobs_to_execute.emplace_back(job.get(), cost);
|
jobs_to_execute.emplace_back(job.get(), cost);
|
||||||
if (this->running.empty() || job->JoinDateTicks() >= this->running.back()->JoinDateTicks()) {
|
if (this->running.empty() || job->JoinDateTicks() >= this->running.back()->JoinDateTicks()) {
|
||||||
this->running.push_back(std::move(job));
|
this->running.push_back(std::move(job));
|
||||||
DEBUG(linkgraph, 3, "LinkGraphSchedule::SpawnNext(): Running job: id: %u, nodes: %u, cost: %u, duration_multiplier: %u",
|
DEBUG(linkgraph, 3, "LinkGraphSchedule::SpawnNext(): Running job: id: %u, nodes: %u, cost: " OTTD_PRINTF64U ", duration_multiplier: %u",
|
||||||
lg->index, lg->Size(), cost, duration_multiplier);
|
lg->index, lg->Size(), cost, duration_multiplier);
|
||||||
} else {
|
} else {
|
||||||
// find right place to insert
|
// find right place to insert
|
||||||
@@ -85,7 +85,7 @@ void LinkGraphSchedule::SpawnNext()
|
|||||||
return a < b->JoinDateTicks();
|
return a < b->JoinDateTicks();
|
||||||
});
|
});
|
||||||
this->running.insert(iter, std::move(job));
|
this->running.insert(iter, std::move(job));
|
||||||
DEBUG(linkgraph, 3, "LinkGraphSchedule::SpawnNext(): Running job (re-ordering): id: %u, nodes: %u, cost: %u, duration_multiplier: %u",
|
DEBUG(linkgraph, 3, "LinkGraphSchedule::SpawnNext(): Running job (re-ordering): id: %u, nodes: %u, cost: " OTTD_PRINTF64U ", duration_multiplier: %u",
|
||||||
lg->index, lg->Size(), cost, duration_multiplier);
|
lg->index, lg->Size(), cost, duration_multiplier);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -97,7 +97,7 @@ void LinkGraphSchedule::SpawnNext()
|
|||||||
|
|
||||||
LinkGraphJobGroup::ExecuteJobSet(std::move(jobs_to_execute));
|
LinkGraphJobGroup::ExecuteJobSet(std::move(jobs_to_execute));
|
||||||
|
|
||||||
DEBUG(linkgraph, 2, "LinkGraphSchedule::SpawnNext(): Linkgraph job totals: cost: %u, budget: %u, scaling: %u, scheduled: %zu, running: %zu",
|
DEBUG(linkgraph, 2, "LinkGraphSchedule::SpawnNext(): Linkgraph job totals: cost: " OTTD_PRINTF64U ", budget: " OTTD_PRINTF64U ", scaling: %u, scheduled: %zu, running: %zu",
|
||||||
total_cost, cost_budget, scaling, this->schedule.size(), this->running.size());
|
total_cost, cost_budget, scaling, this->schedule.size(), this->running.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user