From 328cbcd1f149ce438d92f866cc7aa5f04b83450b Mon Sep 17 00:00:00 2001 From: Dustin Carlino Date: Thu, 23 Jul 2020 09:15:25 -0700 Subject: [PATCH] stop melting my laptop when generating scenarios --- abstutil/src/lib.rs | 4 ++-- abstutil/src/time.rs | 15 ++++++++++++++- game/src/debug/mod.rs | 13 ++++++++----- game/src/devtools/kml.rs | 3 ++- importer/src/soundcast/trips.rs | 23 +++++++++++++++-------- map_model/src/make/mod.rs | 3 ++- map_model/src/objects/road.rs | 1 + sim/src/make/spawner.rs | 8 +++++--- sim/src/sim.rs | 3 ++- 9 files changed, 51 insertions(+), 22 deletions(-) diff --git a/abstutil/src/lib.rs b/abstutil/src/lib.rs index 5670fd7479..a5a79b6f68 100644 --- a/abstutil/src/lib.rs +++ b/abstutil/src/lib.rs @@ -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; diff --git a/abstutil/src/time.rs b/abstutil/src/time.rs index 857213f1ed..896cdb49eb 100644 --- a/abstutil/src/time.rs +++ b/abstutil/src/time.rs @@ -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>(raw_name: S) -> Timer<'a> { let name = raw_name.into(); @@ -335,6 +342,7 @@ impl<'a> Timer<'a> { pub fn parallelize O>( &mut self, timer_name: &str, + parallelism: Parallelism, requests: Vec, cb: F, ) -> Vec @@ -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> = std::iter::repeat_with(|| None) .take(requests.len()) diff --git a/game/src/debug/mod.rs b/game/src/debug/mod.rs index 455617046e..9f33a25caf 100644 --- a/game/src/debug/mod.rs +++ b/game/src/debug/mod.rs @@ -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); diff --git a/game/src/devtools/kml.rs b/game/src/devtools/kml.rs index 273b6bd253..9d63a3bfdd 100644 --- a/game/src/devtools/kml.rs +++ b/game/src/devtools/kml.rs @@ -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 = timer .parallelize( "convert shapes", + Parallelism::Fastest, raw_shapes.shapes.into_iter().enumerate().collect(), |(idx, shape)| { let pts = bounds.convert(&shape.points); diff --git a/importer/src/soundcast/trips.rs b/importer/src/soundcast/trips.rs index cd70a07a78..e825a91e16 100644 --- a/importer/src/soundcast/trips.rs +++ b/importer/src/soundcast/trips.rs @@ -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> = - timer.parallelize("clip trips", popdat.trips.iter().collect(), |orig| { + let maybe_results: Vec> = 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 = 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 = 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))); diff --git a/map_model/src/make/mod.rs b/map_model/src/make/mod.rs index cbb60d1c3a..4e1bdf158f 100644 --- a/map_model/src/make/mod.rs +++ b/map_model/src/make/mod.rs @@ -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 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) { diff --git a/map_model/src/objects/road.rs b/map_model/src/objects/road.rs index 9cdbcd2255..bfb8213042 100644 --- a/map_model/src/objects/road.rs +++ b/map_model/src/objects/road.rs @@ -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) } diff --git a/sim/src/make/spawner.rs b/sim/src/make/spawner.rs index 1fce776508..df80f2e636 100644 --- a/sim/src/make/spawner.rs +++ b/sim/src/make/spawner.rs @@ -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); diff --git a/sim/src/sim.rs b/sim/src/sim.rs index 3f78f1472a..29c226b35d 100644 --- a/sim/src/sim.rs +++ b/sim/src/sim.rs @@ -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(), );