mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'christof/parallel_economy' into 'master'
Parallel economic simulation, based on shredded_economy2 See merge request veloren/veloren!3288
This commit is contained in:
commit
a8a8ee181d
@ -1,3 +1,4 @@
|
||||
use rayon::prelude::*;
|
||||
use std::{
|
||||
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
|
||||
fmt, hash,
|
||||
@ -85,6 +86,15 @@ impl<T> Store<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Send + Sync> Store<T> {
|
||||
pub fn par_iter_mut(&mut self) -> impl ParallelIterator<Item = (Id<T>, &mut T)> {
|
||||
self.items
|
||||
.par_iter_mut()
|
||||
.enumerate()
|
||||
.map(|(idx, obj)| (Id(idx as u64, PhantomData), obj))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Index<Id<T>> for Store<T> {
|
||||
type Output = T;
|
||||
|
||||
|
@ -1,21 +1,21 @@
|
||||
use crate::{
|
||||
sim::WorldSim,
|
||||
site::{
|
||||
economy::{good_list, vergleich, LaborIndex, COIN_INDEX, INTER_SITE_TRADE, MONTH, YEAR},
|
||||
economy::{
|
||||
good_list, vergleich, LaborIndex, COIN_INDEX, DAYS_PER_MONTH, DAYS_PER_YEAR,
|
||||
INTER_SITE_TRADE,
|
||||
},
|
||||
Site, SiteKind,
|
||||
},
|
||||
Index,
|
||||
};
|
||||
use common::store::Id;
|
||||
use rayon::prelude::*;
|
||||
use tracing::{debug, info};
|
||||
|
||||
// const MONTH: f32 = 30.0;
|
||||
// const YEAR: f32 = 12.0 * MONTH;
|
||||
const TICK_PERIOD: f32 = 3.0 * MONTH; // 3 months
|
||||
const HISTORY_DAYS: f32 = 500.0 * YEAR; // 500 years
|
||||
const TICK_PERIOD: f32 = 3.0 * DAYS_PER_MONTH; // 3 months
|
||||
const HISTORY_DAYS: f32 = 500.0 * DAYS_PER_YEAR; // 500 years
|
||||
|
||||
const GENERATE_CSV: bool = false;
|
||||
// const INTER_SITE_TRADE: bool = true;
|
||||
|
||||
/// Statistics collector (min, max, avg)
|
||||
#[derive(Debug)]
|
||||
@ -129,8 +129,9 @@ fn simulate_return(index: &mut Index, world: &mut WorldSim) -> Result<(), std::i
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))?;
|
||||
vr.set_epsilon(0.1);
|
||||
for i in 0..(HISTORY_DAYS / TICK_PERIOD) as i32 {
|
||||
if (index.time / YEAR) as i32 % 50 == 0 && (index.time % YEAR) as i32 == 0 {
|
||||
debug!("Year {}", (index.time / YEAR) as i32);
|
||||
if (index.time / DAYS_PER_YEAR) as i32 % 50 == 0 && (index.time % DAYS_PER_YEAR) as i32 == 0
|
||||
{
|
||||
debug!("Year {}", (index.time / DAYS_PER_YEAR) as i32);
|
||||
}
|
||||
|
||||
tick(index, world, TICK_PERIOD, vr.context(&i.to_string()));
|
||||
@ -236,22 +237,39 @@ fn check_money(index: &mut Index) {
|
||||
);
|
||||
}
|
||||
|
||||
pub fn tick(index: &mut Index, _world: &mut WorldSim, dt: f32, mut vc: vergleich::Context) {
|
||||
let site_ids = index.sites.ids().collect::<Vec<_>>();
|
||||
for site in site_ids {
|
||||
tick_site_economy(index, site, dt, vc.context(&site.id().to_string()));
|
||||
}
|
||||
pub fn tick(index: &mut Index, _world: &mut WorldSim, dt: f32, _vc: vergleich::Context) {
|
||||
if INTER_SITE_TRADE {
|
||||
// move deliverables to recipient cities
|
||||
for (id, deliv) in index.trade.deliveries.drain() {
|
||||
index.sites.get_mut(id).economy.deliveries.extend(deliv);
|
||||
}
|
||||
}
|
||||
index.sites.par_iter_mut().for_each(|(site_id, site)| {
|
||||
if site.do_economic_simulation() {
|
||||
site.economy.tick(site_id, dt, vergleich::Context::dummy());
|
||||
// helpful for debugging but not compatible with parallel execution
|
||||
// vc.context(&site_id.id().to_string()));
|
||||
}
|
||||
});
|
||||
if INTER_SITE_TRADE {
|
||||
// distribute orders (travelling merchants)
|
||||
for (_id, site) in index.sites.iter_mut() {
|
||||
for (i, mut v) in site.economy.orders.drain() {
|
||||
index
|
||||
.trade
|
||||
.orders
|
||||
.entry(i)
|
||||
.or_insert(Vec::new())
|
||||
.append(&mut v);
|
||||
}
|
||||
}
|
||||
// trade at sites
|
||||
for (&site, orders) in index.trade.orders.iter_mut() {
|
||||
let siteinfo = index.sites.get_mut(site);
|
||||
if siteinfo.do_economic_simulation() {
|
||||
// let name: String = siteinfo.name().into();
|
||||
siteinfo.economy.trade_at_site(
|
||||
site,
|
||||
orders,
|
||||
// &mut siteinfo.economy,
|
||||
&mut index.trade.deliveries,
|
||||
);
|
||||
siteinfo
|
||||
.economy
|
||||
.trade_at_site(site, orders, &mut index.trade.deliveries);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -260,26 +278,6 @@ pub fn tick(index: &mut Index, _world: &mut WorldSim, dt: f32, mut vc: vergleich
|
||||
index.time += dt;
|
||||
}
|
||||
|
||||
pub fn tick_site_economy(index: &mut Index, site_id: Id<Site>, dt: f32, vc: vergleich::Context) {
|
||||
let site = &mut index.sites[site_id];
|
||||
if !site.do_economic_simulation() {
|
||||
return;
|
||||
}
|
||||
let deliveries = index.trade.deliveries.get_mut(&site_id);
|
||||
|
||||
let economy = &mut site.economy;
|
||||
economy.tick(deliveries, site_id, dt, vc);
|
||||
|
||||
for (i, mut v) in economy.orders.drain() {
|
||||
index
|
||||
.trade
|
||||
.orders
|
||||
.entry(i)
|
||||
.or_insert(Vec::new())
|
||||
.append(&mut v);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{sim, site::economy::GoodMap, util::seed_expan};
|
||||
|
@ -17,8 +17,8 @@ mod map_types;
|
||||
pub use map_types::{GoodIndex, GoodMap, Labor, LaborIndex, LaborMap, NaturalResources};
|
||||
|
||||
pub const INTER_SITE_TRADE: bool = true;
|
||||
pub const MONTH: f32 = 30.0;
|
||||
pub const YEAR: f32 = 12.0 * MONTH;
|
||||
pub const DAYS_PER_MONTH: f32 = 30.0;
|
||||
pub const DAYS_PER_YEAR: f32 = 12.0 * DAYS_PER_MONTH;
|
||||
|
||||
// this is an empty replacement for https://github.com/cpetig/vergleich
|
||||
// which can be used to compare values acros runs
|
||||
@ -43,6 +43,8 @@ pub mod vergleich {
|
||||
pub fn context(&mut self, _: &str) -> Context { Context {} }
|
||||
|
||||
pub fn value(&mut self, _: &str, val: f32) -> f32 { val }
|
||||
|
||||
pub fn dummy() -> Self { Context {} }
|
||||
}
|
||||
}
|
||||
|
||||
@ -115,6 +117,8 @@ pub struct Economy {
|
||||
|
||||
/// outgoing trade, per provider
|
||||
pub orders: DHashMap<Id<Site>, Vec<TradeOrder>>,
|
||||
/// incoming trade - only towards this site
|
||||
pub deliveries: Vec<TradeDelivery>,
|
||||
}
|
||||
|
||||
impl Default for Economy {
|
||||
@ -142,6 +146,7 @@ impl Default for Economy {
|
||||
unconsumed_stock: Default::default(),
|
||||
|
||||
orders: Default::default(),
|
||||
deliveries: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -652,7 +657,7 @@ impl Economy {
|
||||
fn collect_deliveries(
|
||||
// site: &mut Site,
|
||||
&mut self,
|
||||
deliveries: &mut Vec<TradeDelivery>,
|
||||
// deliveries: &mut Vec<TradeDelivery>,
|
||||
// ctx: &mut vergleich::Context,
|
||||
) {
|
||||
// collect all the goods we shipped
|
||||
@ -664,7 +669,7 @@ impl Economy {
|
||||
0.0,
|
||||
);
|
||||
// TODO: properly rate benefits created by merchants (done below?)
|
||||
for mut d in deliveries.drain(..) {
|
||||
for mut d in self.deliveries.drain(..) {
|
||||
// let mut ictx = ctx.context(&format!("suppl {}", d.supplier.id()));
|
||||
for i in d.amount.iter() {
|
||||
last_exports[i.0] -= *i.1;
|
||||
@ -685,9 +690,9 @@ impl Economy {
|
||||
}
|
||||
}
|
||||
}
|
||||
if !deliveries.is_empty() {
|
||||
info!("non empty deliveries {:?}", deliveries);
|
||||
deliveries.clear();
|
||||
if !self.deliveries.is_empty() {
|
||||
info!("non empty deliveries {:?}", self.deliveries);
|
||||
self.deliveries.clear();
|
||||
}
|
||||
std::mem::swap(&mut last_exports, &mut self.last_exports);
|
||||
//self.active_exports.clear();
|
||||
@ -722,16 +727,16 @@ impl Economy {
|
||||
|
||||
pub fn tick(
|
||||
&mut self,
|
||||
deliveries: Option<&mut Vec<TradeDelivery>>,
|
||||
//deliveries: Option<&mut Vec<TradeDelivery>>,
|
||||
site_id: Id<Site>,
|
||||
dt: f32,
|
||||
mut vc: vergleich::Context,
|
||||
) {
|
||||
// collect goods from trading
|
||||
if INTER_SITE_TRADE {
|
||||
if let Some(deliveries) = deliveries {
|
||||
self.collect_deliveries(deliveries);
|
||||
}
|
||||
// if let Some(deliveries) = deliveries {
|
||||
self.collect_deliveries();
|
||||
// }
|
||||
}
|
||||
|
||||
let orders = self.get_orders();
|
||||
@ -1068,7 +1073,10 @@ impl Economy {
|
||||
} else {
|
||||
0.0
|
||||
};
|
||||
self.pop += vc.value("pop", dt / YEAR * self.pop * (birth_rate - DEATH_RATE));
|
||||
self.pop += vc.value(
|
||||
"pop",
|
||||
dt / DAYS_PER_YEAR * self.pop * (birth_rate - DEATH_RATE),
|
||||
);
|
||||
|
||||
// calculate the new unclaimed stock
|
||||
//let next_orders = self.get_orders();
|
||||
|
Loading…
Reference in New Issue
Block a user