mirror of
https://github.com/a-b-street/abstreet.git
synced 2024-11-28 03:35:51 +03:00
Parallelize part of scenario spawning. One of the code paths calls
biking_connection, which does a slow graph floodfill. Prolet robot in Krakow: from 22.6s to 10.1s Because Krakow now uses separate sidewalks and they're not properly connected to the road graph yet, biking_connection has to search very far. The speedup isn't noticeable in other cases.
This commit is contained in:
parent
b9ff94f275
commit
754749a578
@ -485,7 +485,7 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) {
|
||||
vec![vehicle_spec.clone()],
|
||||
);
|
||||
spawner.schedule_trip(
|
||||
person,
|
||||
person.id,
|
||||
now,
|
||||
TripSpec::VehicleAppearing {
|
||||
start_pos: Position::new(
|
||||
@ -509,7 +509,8 @@ pub fn spawn_agents_around(i: IntersectionID, app: &mut App) {
|
||||
} else if lane.is_walkable() {
|
||||
for _ in 0..5 {
|
||||
spawner.schedule_trip(
|
||||
sim.random_person(Scenario::rand_ped_speed(&mut rng), Vec::new()),
|
||||
sim.random_person(Scenario::rand_ped_speed(&mut rng), Vec::new())
|
||||
.id,
|
||||
now,
|
||||
TripSpec::JustWalking {
|
||||
start: SidewalkSpot::suddenly_appear(
|
||||
|
@ -6,7 +6,7 @@ use rand::{Rng, SeedableRng};
|
||||
use rand_xorshift::XorShiftRng;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use abstutil::{prettyprint_usize, Counter, MapName, Timer};
|
||||
use abstutil::{prettyprint_usize, Counter, MapName, Parallelism, Timer};
|
||||
use geom::{Distance, Duration, LonLat, Speed, Time};
|
||||
use map_model::{
|
||||
BuildingID, BusRouteID, BusStopID, DirectedRoadID, Map, OffstreetParking, PathConstraints,
|
||||
@ -161,8 +161,8 @@ impl Scenario {
|
||||
}
|
||||
|
||||
timer.start_iter("trips for People", self.people.len());
|
||||
let mut spawner = sim.make_spawner();
|
||||
let mut parked_cars: Vec<(Vehicle, BuildingID)> = Vec::new();
|
||||
let mut schedule_trips = Vec::new();
|
||||
for p in &self.people {
|
||||
timer.next();
|
||||
|
||||
@ -191,8 +191,8 @@ impl Scenario {
|
||||
&mut tmp_rng,
|
||||
map,
|
||||
);
|
||||
spawner.schedule_trip(
|
||||
person,
|
||||
schedule_trips.push((
|
||||
person.id,
|
||||
t.depart,
|
||||
spec,
|
||||
t.trip.start(map),
|
||||
@ -200,10 +200,23 @@ impl Scenario {
|
||||
t.cancelled,
|
||||
t.modified,
|
||||
map,
|
||||
);
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let mut spawner = sim.make_spawner();
|
||||
let results = timer.parallelize(
|
||||
"schedule trips",
|
||||
Parallelism::Fastest,
|
||||
schedule_trips,
|
||||
|tuple| {
|
||||
spawner.schedule_trip_fast(
|
||||
tuple.0, tuple.1, tuple.2, tuple.3, tuple.4, tuple.5, tuple.6, tuple.7,
|
||||
)
|
||||
},
|
||||
);
|
||||
spawner.schedule_trips(results);
|
||||
|
||||
// parked_cars is stable over map edits, so don't fork.
|
||||
parked_cars.shuffle(rng);
|
||||
seed_parked_cars(parked_cars, sim, map, rng, timer);
|
||||
|
@ -8,8 +8,8 @@ use geom::{Duration, Time};
|
||||
use map_model::{BuildingID, BusRouteID, BusStopID, Map, PathConstraints, PathRequest, Position};
|
||||
|
||||
use crate::{
|
||||
CarID, Command, DrivingGoal, OffMapLocation, Person, PersonID, Scheduler, SidewalkSpot,
|
||||
TripEndpoint, TripLeg, TripManager, TripMode, TripPurpose, VehicleType,
|
||||
CarID, Command, DrivingGoal, OffMapLocation, PersonID, Scheduler, SidewalkSpot, TripEndpoint,
|
||||
TripLeg, TripManager, TripMode, TripPurpose, VehicleType,
|
||||
};
|
||||
|
||||
// TODO Some of these fields are unused now that we separately pass TripEndpoint
|
||||
@ -61,17 +61,19 @@ pub enum TripSpec {
|
||||
},
|
||||
}
|
||||
|
||||
type TripSpawnPlan = (
|
||||
PersonID,
|
||||
Time,
|
||||
TripSpec,
|
||||
TripEndpoint,
|
||||
TripPurpose,
|
||||
bool,
|
||||
bool,
|
||||
);
|
||||
|
||||
/// This structure is created temporarily by a Scenario or to interactively spawn agents.
|
||||
pub struct TripSpawner {
|
||||
trips: Vec<(
|
||||
PersonID,
|
||||
Time,
|
||||
TripSpec,
|
||||
TripEndpoint,
|
||||
TripPurpose,
|
||||
bool,
|
||||
bool,
|
||||
)>,
|
||||
trips: Vec<TripSpawnPlan>,
|
||||
}
|
||||
|
||||
impl TripSpawner {
|
||||
@ -79,9 +81,11 @@ impl TripSpawner {
|
||||
TripSpawner { trips: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn schedule_trip(
|
||||
&mut self,
|
||||
person: &Person,
|
||||
/// Doesn't actually schedule anything yet; you can call this from multiple threads, then feed
|
||||
/// all the results to schedule_trips.
|
||||
pub fn schedule_trip_fast(
|
||||
&self,
|
||||
person: PersonID,
|
||||
start_time: Time,
|
||||
mut spec: TripSpec,
|
||||
trip_start: TripEndpoint,
|
||||
@ -89,7 +93,7 @@ impl TripSpawner {
|
||||
cancelled: bool,
|
||||
modified: bool,
|
||||
map: &Map,
|
||||
) {
|
||||
) -> TripSpawnPlan {
|
||||
// TODO We'll want to repeat this validation when we spawn stuff later for a second leg...
|
||||
match &spec {
|
||||
TripSpec::VehicleAppearing {
|
||||
@ -189,11 +193,32 @@ impl TripSpawner {
|
||||
TripSpec::Remote { .. } => {}
|
||||
};
|
||||
|
||||
self.trips.push((
|
||||
person.id, start_time, spec, trip_start, purpose, cancelled, modified,
|
||||
(
|
||||
person, start_time, spec, trip_start, purpose, cancelled, modified,
|
||||
)
|
||||
}
|
||||
|
||||
/// Immediately schedule the requested trip
|
||||
pub fn schedule_trip(
|
||||
&mut self,
|
||||
person: PersonID,
|
||||
start_time: Time,
|
||||
spec: TripSpec,
|
||||
trip_start: TripEndpoint,
|
||||
purpose: TripPurpose,
|
||||
cancelled: bool,
|
||||
modified: bool,
|
||||
map: &Map,
|
||||
) {
|
||||
self.trips.push(self.schedule_trip_fast(
|
||||
person, start_time, spec, trip_start, purpose, cancelled, modified, map,
|
||||
));
|
||||
}
|
||||
|
||||
pub fn schedule_trips(&mut self, trips: Vec<TripSpawnPlan>) {
|
||||
self.trips.extend(trips);
|
||||
}
|
||||
|
||||
pub fn finalize(
|
||||
mut self,
|
||||
map: &Map,
|
||||
|
Loading…
Reference in New Issue
Block a user