stop melting my laptop when generating scenarios

This commit is contained in:
Dustin Carlino 2020-07-23 09:15:25 -07:00
parent f1ef02b907
commit 328cbcd1f1
9 changed files with 51 additions and 22 deletions

View File

@ -20,8 +20,8 @@ pub use crate::io::{
};
pub use crate::random::{fork_rng, WeightedUsizeChoice};
pub use crate::time::{
elapsed_seconds, prettyprint_usize, start_profiler, stop_profiler, MeasureMemory, Profiler,
Timer, TimerSink,
elapsed_seconds, prettyprint_usize, start_profiler, stop_profiler, MeasureMemory, Parallelism,
Profiler, Timer, TimerSink,
};
use std::collections::BTreeSet;
use std::fmt::Write;

View File

@ -125,6 +125,13 @@ struct TimerSpan {
nested_time: f64,
}
pub enum Parallelism {
// Use all CPUs
Fastest,
// Use half of CPUs
Polite,
}
impl<'a> Timer<'a> {
pub fn new<S: Into<String>>(raw_name: S) -> Timer<'a> {
let name = raw_name.into();
@ -335,6 +342,7 @@ impl<'a> Timer<'a> {
pub fn parallelize<I, O, F: Fn(I) -> O>(
&mut self,
timer_name: &str,
parallelism: Parallelism,
requests: Vec<I>,
cb: F,
) -> Vec<O>
@ -358,7 +366,12 @@ impl<'a> Timer<'a> {
#[cfg(not(target_arch = "wasm32"))]
{
scoped_threadpool::Pool::new(num_cpus::get() as u32).scoped(|scope| {
let cpus = match parallelism {
Parallelism::Fastest => num_cpus::get(),
Parallelism::Polite => num_cpus::get() / 2,
}
.max(1) as u32;
scoped_threadpool::Pool::new(cpus).scoped(|scope| {
let (tx, rx) = std::sync::mpsc::channel();
let mut results: Vec<Option<O>> = std::iter::repeat_with(|| None)
.take(requests.len())

View File

@ -9,7 +9,7 @@ use crate::game::{msg, DrawBaselayer, State, Transition, WizardState};
use crate::helpers::ID;
use crate::managed::{WrappedComposite, WrappedOutcome};
use crate::render::{calculate_corners, DrawOptions};
use abstutil::{Tags, Timer};
use abstutil::{Parallelism, Tags, Timer};
use ezgui::{
hotkey, lctrl, Btn, Checkbox, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx,
HorizontalAlignment, Key, Line, Outcome, Text, UpdateType, VerticalAlignment, Widget, Wizard,
@ -404,12 +404,15 @@ fn calc_all_routes(ctx: &EventCtx, app: &mut App) -> (usize, Drawable) {
let mut cnt = 0;
let sim = &app.primary.sim;
let map = &app.primary.map;
for maybe_trace in
Timer::new("calculate all routes").parallelize("route to geometry", agents, |id| {
for maybe_trace in Timer::new("calculate all routes").parallelize(
"route to geometry",
Parallelism::Fastest,
agents,
|id| {
sim.trace_route(id, map, None)
.map(|trace| trace.make_polygons(NORMAL_LANE_THICKNESS))
})
{
},
) {
if let Some(t) = maybe_trace {
cnt += 1;
batch.push(app.cs.route, t);

View File

@ -2,7 +2,7 @@ use crate::app::App;
use crate::colors::ColorScheme;
use crate::game::{State, Transition};
use aabb_quadtree::QuadTree;
use abstutil::prettyprint_usize;
use abstutil::{prettyprint_usize, Parallelism};
use ezgui::{
hotkey, Btn, Choice, Color, Composite, Drawable, EventCtx, GeomBatch, GfxCtx,
HorizontalAlignment, Key, Line, Outcome, Text, TextExt, VerticalAlignment, Widget,
@ -56,6 +56,7 @@ impl ViewKML {
let objects: Vec<Object> = timer
.parallelize(
"convert shapes",
Parallelism::Fastest,
raw_shapes.shapes.into_iter().enumerate().collect(),
|(idx, shape)| {
let pts = bounds.convert(&shape.points);

View File

@ -1,5 +1,5 @@
use crate::soundcast::popdat::{Endpoint, OrigTrip, PopDat};
use abstutil::{prettyprint_usize, MultiMap, Timer};
use abstutil::{prettyprint_usize, MultiMap, Parallelism, Timer};
use geom::LonLat;
use map_model::{BuildingID, IntersectionID, Map, PathConstraints, PathRequest, PathStep};
use sim::{
@ -204,8 +204,11 @@ fn clip_trips(map: &Map, popdat: &PopDat, huge_map: &Map, timer: &mut Timer) ->
.collect();
let total_trips = popdat.trips.len();
let maybe_results: Vec<Option<Trip>> =
timer.parallelize("clip trips", popdat.trips.iter().collect(), |orig| {
let maybe_results: Vec<Option<Trip>> = timer.parallelize(
"clip trips",
Parallelism::Polite,
popdat.trips.iter().collect(),
|orig| {
let (from, to) = endpoints(
&orig.from,
&orig.to,
@ -230,7 +233,8 @@ fn clip_trips(map: &Map, popdat: &PopDat, huge_map: &Map, timer: &mut Timer) ->
to,
orig: orig.clone(),
})
});
},
);
let trips: Vec<Trip> = maybe_results.into_iter().flatten().collect();
timer.note(format!(
@ -255,16 +259,19 @@ pub fn make_weekday_scenario(
// person -> (trip seq, index into individ_trips)
let mut trips_per_person: MultiMap<OrigPersonID, ((usize, bool, usize), usize)> =
MultiMap::new();
for (trip, depart, person, seq) in
timer.parallelize("turn Soundcast trips into SpawnTrips", trips, |trip| {
for (trip, depart, person, seq) in timer.parallelize(
"turn Soundcast trips into SpawnTrips",
Parallelism::Polite,
trips,
|trip| {
(
SpawnTrip::new(trip.from, trip.to, trip.orig.mode, map),
trip.orig.depart_at,
trip.orig.person,
trip.orig.seq,
)
})
{
},
) {
if let Some(trip) = trip {
let idx = individ_trips.len();
individ_trips.push(Some(IndividTrip::new(depart, trip)));

View File

@ -14,7 +14,7 @@ use crate::{
IntersectionID, IntersectionType, Lane, LaneID, Map, MapEdits, PathConstraints, Position, Road,
RoadID, Zone,
};
use abstutil::Timer;
use abstutil::{Parallelism, Timer};
use enumset::EnumSet;
use geom::{Bounds, Distance, FindClosest, HashablePt2D, Polygon, Speed, EPSILON_DIST};
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
@ -409,6 +409,7 @@ fn match_points_to_lanes<F: Fn(&Lane) -> bool>(
timer
.parallelize(
"find closest lane point",
Parallelism::Fastest,
pts.into_iter().collect(),
|query_pt| {
if let Some((l, pt)) = closest.closest_pt(query_pt.to_pt2d(), max_dist_away) {

View File

@ -178,6 +178,7 @@ impl Road {
.iter()
.rev()
.chain(self.children(!fwds).iter())
// TODO Bug, bus lanes OK. use PathConstraints::Bike.
.find(|(_, lt)| *lt == LaneType::Driving || *lt == LaneType::Biking)
.map(|(id, _)| *id)
}

View File

@ -2,7 +2,7 @@ use crate::{
CarID, Command, DrivingGoal, OffMapLocation, Person, PersonID, Scheduler, SidewalkSpot,
TripEndpoint, TripLeg, TripManager, TripMode, VehicleType, BIKE_LENGTH, MAX_CAR_LENGTH,
};
use abstutil::Timer;
use abstutil::{Parallelism, Timer};
use geom::{Duration, Time, EPSILON_DIST};
use map_model::{
BuildingID, BusRouteID, BusStopID, IntersectionID, Map, PathConstraints, PathRequest, Position,
@ -157,8 +157,9 @@ impl TripSpawner {
spec = backup_plan.unwrap();
} else {
panic!(
"Can't start biking from {}; no biking or driving lane nearby?",
start
"Can't start biking from {}; no biking or driving lane nearby? Can't \
walk instead, goal is {:?}",
start, goal
);
}
} else if let DrivingGoal::ParkNear(b) = goal {
@ -207,6 +208,7 @@ impl TripSpawner {
}
let paths = timer.parallelize(
"calculate paths",
Parallelism::Fastest,
std::mem::replace(&mut self.trips, Vec::new()),
|tuple| {
let req = tuple.2.get_pathfinding_request(map);

View File

@ -8,7 +8,7 @@ use crate::{
UnzoomedAgent, Vehicle, VehicleSpec, VehicleType, WalkingSimState, BUS_LENGTH,
LIGHT_RAIL_LENGTH, MIN_CAR_LENGTH,
};
use abstutil::Timer;
use abstutil::{Parallelism, Timer};
use derivative::Derivative;
use geom::{Distance, Duration, PolyLine, Pt2D, Speed, Time};
use instant::Instant;
@ -837,6 +837,7 @@ impl Sim {
pub fn restore_paths(&mut self, map: &Map, timer: &mut Timer) {
let paths = timer.parallelize(
"calculate paths",
Parallelism::Fastest,
self.scheduler.get_requests_for_savestate(),
|req| map.pathfind(req).unwrap(),
);