Skip to content
This repository was archived by the owner on Oct 14, 2025. It is now read-only.

Speedup semantic rasterizer#140

Closed
pestipeti wants to merge 5 commits intowoven-by-toyota:masterfrom
pestipeti:speedup_semantic_rasterizer
Closed

Speedup semantic rasterizer#140
pestipeti wants to merge 5 commits intowoven-by-toyota:masterfrom
pestipeti:speedup_semantic_rasterizer

Conversation

@pestipeti
Copy link
Copy Markdown

I achieved ~ 7-8% speedup with these modifications.

Copy link
Copy Markdown
Contributor

@lucabergamini lucabergamini left a comment

Choose a reason for hiding this comment

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

Amazing work! minors, you can either pick them up yourself or I can also do them, just let me know :)

)

return {"xyz": xyz}
xyz[:, -1] = 1.0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why is this required? We ignore the z coordinates in the following so this shouldn't make any difference right?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

In the current implementation, first you cut the z-coordinate lane_coords["xyz_right"][:, :2] and later in the transform method you stack it back np.vstack((points[:num_dims, :], np.ones(points.shape[1]))). With this we can save the one cut, the np.ones creation, the stack.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Another way of doing this would be to only use the first 2x2 of the matrix (only XY) in the semantic rasterizer. My issue with setting 1 here is that we're removing information in a very hidden part of the code, which may render debugging problematic in the future (also considering there is a cache system in between)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I see. You can move it to the semantic rasterizer method; before the dot product calls.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like this idea also :) Today was quite busy, but I should be able to work on this tomorrow (hopefully)


return {"xyz": xyz}
xyz[:, -1] = 1.0
return {"xyz": xyz.T}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I can see the point of caching this to avoid stack at runtime, but we may still want to include either the two lanes or at least the length of the first, so that we can always unpack the two apart (I'm thinking about centre line support right now)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The cheapest/easiest solution if you add the length of the first line. I think map_api should handle the centerline calculation as well (cachable).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

yeah, I agree on that and I'm fine with having the length included

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

One note: I changed the returned xyz format to xyz.T.

xy_left = cv2_subpixel(transform_points(lane_coords["xyz_left"][:, :2], world_to_image_space))
xy_right = cv2_subpixel(transform_points(lane_coords["xyz_right"][:, :2], world_to_image_space))
lanes_area = np.vstack((xy_left, np.flip(xy_right, 0))) # start->end left then end->start right
lanes_xy = cv2_subpixel(world_to_image_space.dot(lane_coords["xyz"]).T[:, :2])
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why not using transform or transform_transpose functions here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

It seemed a bit complicated. Transposes, vstack, np.ones, cut z-axis, etc. I did not want to break other parts of the code by modifying those methods.

(Feel free to correct anything you want.)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Yeah you're perfectly right about that. Let me see if we can also handle this case there (same len for matrix and points)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I did these modifications only to save as many CPU cycles as I possibly can. I did not consider long term usability, I only care about speeding up for the competition, so it is fine if you drop all of or part of this PR.

@pascal-pfeiffer
Copy link
Copy Markdown
Contributor

render_semantic_map is the bottleneck when using a low count of history_frames.
This PR speeds up the render_semantic_map function by ~200%.
Even for higher count of history_frames this change is still significant and I suggest to accept it.

@lucabergamini
Copy link
Copy Markdown
Contributor

This PR speeds up the render_semantic_map function by ~200%.

did you compare this against #196?

@pascal-pfeiffer
Copy link
Copy Markdown
Contributor

pascal-pfeiffer commented Jan 6, 2021

did you compare this against #196?

thanks for pointing to that PR. It does even better once the caching is done:

52 ms ± 4.77 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) no changes
24.8 ms ± 777 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) this PR #140

32.9 ms ± 17.2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) PR #196
The slowest run took 4.23 times longer than the fastest. This could mean that an intermediate result is being cached.

after caching:
17.5 ms ± 880 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) PR #196

timings are for the full dataset loading (448x224 raster, 0 history frames) so the speedups are normalized to include all other operations such as box_rasterizer as well)

@ossama-othman ossama-othman deleted the branch woven-by-toyota:master October 14, 2025 01:32
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants