Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

integrate census scenario #426

Merged

Conversation

michaelkirk
Copy link
Collaborator

@michaelkirk michaelkirk commented Dec 15, 2020

Based on #425 so review that first.

Integrates the census based scenario and does some perf work to speed up the census scenario's creation.

Previously it'd take ~440s.

I got it down to something like 40s by caching the boundary nodes and the activity->building_ids map.

Then down to about 15s by parallelizing the make_person calls.

Oh! And some proof that it works:
lower_manhattan mov

@@ -145,7 +145,8 @@ impl Scenario {
timer.next();

if let Err(err) = p.check_schedule() {
panic!("{}", err);
error!("skipping invalid schedule: {}", err);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't miss this bit! I haven't looked into why this is happening yet, but skipping these invalid one still results in lots of trips being made.

I suppose we need some kind of disqualifying criteria to prevent these kinds of schedules from being created upstream, but for now I just switched it to an error log.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hesitant to remove this check, because there are other places that create scenarios. And if a weird schedule gets through, I don't remember how the sim spawning layer handles it -- I think there'll be some assertion failure when the trip transition happens, which is a pretty deferred way to discover a bug.

Could we use scenario.remove_weird_schedules() instead? And maybe update the printlns there to log

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Didn't know about remove_weird_schedules - thanks. Done!

@michaelkirk michaelkirk mentioned this pull request Dec 15, 2020
Currently this is really slow. We'll either need to speed it up
significantly or find some way to cache the scenarios and maybe
pregenerate them.

Here's a breakdown of the time spent:

    - generate census scenario took 424.5807s
      - building population areas for map took 2.8061s
	- parsing geojson took 0.4573s
	- converting to `CensusArea`s took 2.3351s
	- ... plus 0.0137s
      - assigning people to houses took 1.5885s
      - building people took 420.1861s

It's almost entirely in the `building people` step which we can
parallelize. I'm sure there are other improvements to make after that.
activity->building map

Before:

- generate census scenario took 424.5807s
  - building population areas for map took 2.8061s
    - parsing geojson took 0.4573s
    - converting to `CensusArea`s took 2.3351s
    - ... plus 0.0137s
  - assigning people to houses took 1.5885s
  - building people took 420.1861s

After:

- generate census scenario took 47.6638s
  - building population areas for map took 3.0067s
    - parsing geojson took 0.3655s
    - converting to `CensusArea`s took 2.6192s
    - ... plus 0.0220s
  - assigning people to houses took 1.6294s
  - building people took 43.0277s
- generate census scenario took 15.4418s
  - building population areas for map took 2.7773s
    - parsing geojson took 0.3764s
    - converting to `CensusArea`s took 2.3754s
    - ... plus 0.0254s
  - assigning people to houses took 1.7802s
  - building people took 10.8842s
    - making people in parallel (290,079)... 10.7447s
    - ... plus 0.1395s
  - ... plus 0.0001s
@michaelkirk michaelkirk force-pushed the mkirk/integrate-census-scenario branch from e4b344c to 97d21e4 Compare December 15, 2020 01:49
@michaelkirk
Copy link
Collaborator Author

(just rebased atop master since #425 was merged)

// either pick the closest choice, or even better, randomize, but weight based on
// the cost of getting there. map.pathfind() may be helpful.

// For now, just pick a random one
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

behavioral change: I switched this to random rather than first.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

.push(make_person::make_person(person, map, rng, &config));
}

scenario.people.append(&mut make_person::make_people(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The API of append is funny, I would expect it to consume...

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is mostly just my lack of fluency in rust.

I think append is intended for things where it makes sense to clear out but re-use the buffer like:

let buffer = vec![];
while read_into_buffer(&mut buffer) {
    results.append(buffer);
}

I've switched to extend which has better semantics for this type of call.

// Only consider two-way intersections, so the agent can return the same way
// they came.
// TODO: instead, if it's not a two-way border, we should find an intersection
// an incoming border "near" the outgoing border, to allow a broader set of
// realistic options.
// TODO: prefer larger thoroughfares to better reflect reality.
let commuter_borders: Vec<IntersectionID> = map
let commuter_borders: Vec<map_model::IntersectionID> = map
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: IntersectionID is already imported

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed!

// No buildings satisfy the activity. Just go somewhere off-map.
TripEndpoint::Border(*commuter_borders.choose(rng).unwrap())
};
let person_factory = PersonFactory::new(map);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Serious Java flashbacks :D

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just trying to keep the hype wave down.

// either pick the closest choice, or even better, randomize, but weight based on
// the cost of getting there. map.pathfind() may be helpful.

// For now, just pick a random one
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM

@@ -145,7 +145,8 @@ impl Scenario {
timer.next();

if let Err(err) = p.check_schedule() {
panic!("{}", err);
error!("skipping invalid schedule: {}", err);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm hesitant to remove this check, because there are other places that create scenarios. And if a weird schedule gets through, I don't remember how the sim spawning layer handles it -- I think there'll be some assertion failure when the trip transition happens, which is a pretty deferred way to discover a bug.

Could we use scenario.remove_weird_schedules() instead? And maybe update the printlns there to log

@dabreegster
Copy link
Collaborator

LGTM, thanks for the PR! I'd say 440s -> 15s is quite impressive.

I'm guessing the next steps are to automate the census data prep, or come up with the large-but-indexable preprocessed file. Keep me posted!

@dabreegster dabreegster merged commit 375e0ca into a-b-street:master Dec 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants