-
Notifications
You must be signed in to change notification settings - Fork 369
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
Optimize gathering of point cloud colors #3730
Merged
Merged
Changes from 13 commits
Commits
Show all changes
16 commits
Select commit
Hold shift + click to select a range
4fab5fe
Optimize gathering colors for point clouds: inline common case
emilk 39cc5a7
Remove unnecessary reference
emilk d0e4791
Clean up the points2d/3d code paths and make them more similar to eac…
emilk d0dc7fb
Move labels last
emilk fd71873
Pass in less powerful objects as parameters
emilk ce410d0
Break out the CPU-specific code so we can benchmark it
emilk 16825ee
Make it easy to construct DataRow and DataCell from archetypes
emilk 144387b
Make it easier to benchmark individual parts
emilk 00417f1
Add a high-level benchmark of Points3D rendering
emilk 7d6c14e
Compute the size of the row
emilk f727a72
Add profile-scopes around the `collect` calls
emilk 42a3b2e
Fix docstring
emilk 8a82d46
`#[inline]`
emilk f25d0b8
backticks
emilk 4c7298e
Make `from_component_batches` more complicated and add `from_archetype`
emilk a55c079
Remove unused import
emilk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
//! High-level benchmark of the CPU-side of our Points3D rendering. | ||
emilk marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
use re_arrow_store::{DataStore, LatestAtQuery}; | ||
use re_log_types::{DataRow, EntityPath, RowId, TimeInt, TimePoint, Timeline}; | ||
use re_space_view_spatial::LoadedPoints; | ||
use re_types::{ | ||
archetypes::Points3D, | ||
components::{Color, InstanceKey, Position3D}, | ||
Loggable as _, | ||
}; | ||
use re_viewer_context::Annotations; | ||
|
||
#[global_allocator] | ||
static GLOBAL: mimalloc::MiMalloc = mimalloc::MiMalloc; | ||
|
||
criterion::criterion_main!(benches); | ||
criterion::criterion_group!(benches, bench_points); | ||
|
||
// --- | ||
|
||
#[cfg(not(debug_assertions))] | ||
const NUM_POINTS: usize = 1_000_000; | ||
|
||
// `cargo test` also runs the benchmark setup code, so make sure they run quickly: | ||
#[cfg(debug_assertions)] | ||
const NUM_POINTS: usize = 10; | ||
|
||
// --- | ||
|
||
/// Mimics `examples/python/open_photogrammetry_format/main.py` | ||
fn bench_points(c: &mut criterion::Criterion) { | ||
let timeline = Timeline::log_time(); | ||
let ent_path = EntityPath::from("points"); | ||
|
||
let store = { | ||
let mut store = DataStore::new(InstanceKey::name(), Default::default()); | ||
|
||
let positions = vec![Position3D::new(0.1, 0.2, 0.3); NUM_POINTS]; | ||
let colors = vec![Color::from(0xffffffff); NUM_POINTS]; | ||
let points = Points3D::new(positions).with_colors(colors); | ||
let mut timepoint = TimePoint::default(); | ||
timepoint.insert(timeline, TimeInt::from_seconds(0)); | ||
let data_row = | ||
DataRow::from_component_batches(RowId::random(), timepoint, ent_path.clone(), &points) | ||
.unwrap(); | ||
store.insert_row(&data_row).unwrap(); | ||
store | ||
}; | ||
|
||
let latest_at = LatestAtQuery::latest(timeline); | ||
let annotations = Annotations::missing(); | ||
|
||
{ | ||
let mut group = c.benchmark_group("Points3D"); | ||
group.bench_function("query_archetype", |b| { | ||
b.iter(|| { | ||
let arch_view = | ||
re_query::query_archetype::<Points3D>(&store, &latest_at, &ent_path).unwrap(); | ||
assert_eq!(arch_view.num_instances(), NUM_POINTS); | ||
arch_view | ||
}); | ||
}); | ||
} | ||
|
||
let arch_view = re_query::query_archetype::<Points3D>(&store, &latest_at, &ent_path).unwrap(); | ||
assert_eq!(arch_view.num_instances(), NUM_POINTS); | ||
|
||
{ | ||
let mut group = c.benchmark_group("Points3D"); | ||
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); | ||
group.bench_function("load_all", |b| { | ||
b.iter(|| { | ||
let points = | ||
LoadedPoints::load(&arch_view, &ent_path, latest_at.at, &annotations).unwrap(); | ||
assert_eq!(points.positions.len(), NUM_POINTS); | ||
assert_eq!(points.colors.len(), NUM_POINTS); | ||
assert_eq!(points.radii.len(), NUM_POINTS); // NOTE: we don't log radii, but we should get a list of defaults! | ||
points | ||
}); | ||
}); | ||
} | ||
|
||
{ | ||
let mut group = c.benchmark_group("Points3D"); | ||
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); | ||
group.bench_function("load_positions", |b| { | ||
b.iter(|| { | ||
let positions = LoadedPoints::load_positions(&arch_view).unwrap(); | ||
assert_eq!(positions.len(), NUM_POINTS); | ||
positions | ||
}); | ||
}); | ||
} | ||
|
||
{ | ||
let points = LoadedPoints::load(&arch_view, &ent_path, latest_at.at, &annotations).unwrap(); | ||
|
||
let mut group = c.benchmark_group("Points3D"); | ||
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); | ||
group.bench_function("load_colors", |b| { | ||
b.iter(|| { | ||
let colors = | ||
LoadedPoints::load_colors(&arch_view, &ent_path, &points.annotation_infos) | ||
.unwrap(); | ||
assert_eq!(colors.len(), NUM_POINTS); | ||
colors | ||
}); | ||
}); | ||
} | ||
|
||
// NOTE: we don't log radii! | ||
{ | ||
let mut group = c.benchmark_group("Points3D"); | ||
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); | ||
group.bench_function("load_radii", |b| { | ||
b.iter(|| { | ||
let radii = LoadedPoints::load_radii(&arch_view, &ent_path).unwrap(); | ||
assert_eq!(radii.len(), NUM_POINTS); | ||
radii | ||
}); | ||
}); | ||
} | ||
|
||
{ | ||
let mut group = c.benchmark_group("Points3D"); | ||
group.throughput(criterion::Throughput::Elements(NUM_POINTS as _)); | ||
group.bench_function("load_picking_ids", |b| { | ||
b.iter(|| { | ||
let picking_ids = LoadedPoints::load_picking_ids(&arch_view); | ||
assert_eq!(picking_ids.len(), NUM_POINTS); | ||
picking_ids | ||
}); | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect this to take an iterator of
ComponentBatches
: it's strictly more expressive, easier to build / come by and more consistent with the rest of our APIs.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would we get the
num_instances
in that case? Take the max of all the batches? What if there are no batches, or if they are all splats?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that matches the behavior of our log methods (in all languages, even!):
Then there's nothing in the row and there are no instances
You cannot have "all splats", that would just result in a row with num_instances = 1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I thought we stored
num_instances
separately.So what happens if I log a full point cloud first and then later want to update all the colors with a splat color - that would be a new row with
num_instance = 1
then, even though it will affect several instances?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's where it becomes funky...
If you do this:
Then you're going to end up with the original
colors
being discarded, a single red point and the rest of the points using the default color for this entity path (because thatColorBatch
is not a splat).Now, there is a trick at your disposal... you could do this:
And now you'll end up with only red points, because you explicitly said that the data was 2 instances wide, and so the log function considers the
ColorBatch
to be a splat...Of course we could change things so that logging 1 thing is always considered a splat, but then you have the opposite problem, which might or might not be better depending on the situation 🤷.
And this is why I don't like that splats are a logging-time rather than a query-time concern: the view should get to decide what to do with the data that it has as its disposal, and that behavior should be configurable through blueprints and through the UI.
This instance key business is pretty similar to e.g. configurable texture clamping modes in gfx APIs after all.