-
-
Notifications
You must be signed in to change notification settings - Fork 410
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
Making Points layer creation and update faster #6727
Conversation
I have realized that |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #6727 +/- ##
==========================================
- Coverage 92.45% 92.44% -0.01%
==========================================
Files 617 617
Lines 55166 55181 +15
==========================================
+ Hits 51001 51010 +9
- Misses 4165 4171 +6 ☔ View full report in Codecov by Sentry. |
This looks to be addressing: #6275 |
Thanks for the fantastic PR description @jules-vanaret, and for your attention on the points layer 👀
@psobolewskiPhD yep I'd say you're right. Based on the profiling and discussion in that thread it looks like both the |
Thank you both for taking a look! |
@brisvag Did you know what is required to release vispy 0.14.2? |
Nice work, I was never happy about this code ^^' @Czaki releasing a patch version for vispy can be done whenever we like I think. |
So maybe you could make release, and we could check how this PR works with the new vispy? |
Vispy 0.14.2 released :) |
FYI I ran the script from the OP (n= 10 mil) with newest vispy and psygnal and I get:
Virtually the same prior to updating them. However with this PR:
Adding a layer using |
Whoops you beat me to it ! :) |
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.
This looks great to me!
But I'd like @Czaki who wrote the previous implementation to take a look too.
@Czaki should I run additional benchmarks or add comments to the code ? |
I will try to review tomorrow. Please resolve the conflicts |
@Czaki any further comments on this one? |
Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
The Qt benchmark run requested by PR #6727 (e37f69c vs 2a22052) has finished with status 'failure'. See the CI logs and artifacts for further details. |
The Qt benchmark run requested by PR #6727 (f41f486 vs 2a22052) has finished with status 'failure'. See the CI logs and artifacts for further details. |
1 similar comment
The Qt benchmark run requested by PR #6727 (f41f486 vs 2a22052) has finished with status 'failure'. See the CI logs and artifacts for further details. |
It looks like a global translation dict solve the performance problems:
@jules-vanaret are you ok with these changes? For typing, I prefer to wait on #6866 as it will bump mypy and current output is false negative. |
Co-authored-by: Grzegorz Bokota <bokota+github@gmail.com>
for more information, see https://pre-commit.ci
Sorry for the delay. Thank you for your work @Czaki, precomputing the dict makes much more sense ! Some tests are still failing though. |
Yes, but I prefer to merge first #6866, as it will impact failing test. |
The Qt benchmark run requested by PR #6727 (0b86e44 vs 1dcbade) has finished with status 'success'. See the CI logs and artifacts for further details. |
Signed-off-by: Grzegorz Bokota <bokota+github@gmail.com>
@jules-vanaret Could you check current state? I have cleanup code a little and tweak documentation. For me, it is close to merging. @psobolewskiPhD could you also check? |
Everything still looks good to me.
|
I just rechecked the code and some cases are indeed faster (cases that are not are marginally so). |
Thanks @jni for merging the PR! :) |
References and relevant issues
I work with large points datasets (~10⁶ vertices), and creating/setting data of a Points layer is rather slow, on the order of 2 seconds on my machine). I have dug into the code and found that the culprit is this function to handle symbols associated to points in
napari/layers/points/_points_utils.py
, which takes around 80% of the full computation time:The purpose of
coerce_symbols
is to transform "raw" (e.g string like 'o') points symbols into properSymbol
instances.Note that even if
symbol
is not specified when creating the Points layer (and then it is just equal to 'o'), or specified with a unique symbol for all points, thesymbol
setter innapari/layers/points/points.py
:immediately transform this unique symbol into a potentially huge numpy array of size
N_vertices
.The main reason for the fact that
coerce_symbols
is slow in the case of largeN_vertices
is because it loops twice through this huge numpy array of (potentially simply duplicated) symbols: once with(str(x).lower() for x in array)
and more or less once withnp.vectorize(Symbol, otypes=[object])(array)
. I believe this can be improved with minor changesDescription
The PR stems from two ideas to reduce computation time.
Symbol
instance, it is much faster to first convert it to a properSymbol
instance and THEN to broadcast it to an array of sizeN_vertices
.N_vertices
symbols for the points (composed of strings orSymbol
instances), there are not that many valid symbols (currently 14 different ones) that they can choose from. This means that instead of converting each string symbol into a Symbol instance individually, it is faster to first find all unique raw symbols fromsymbol
provided by the user, convert them in toSymbol
, and then simply map each raw symbol to its correspondingSymbol
instance.The new
coerce_symbols
function I propose looks like this:Instead of operating on an already-broadcasted array of symbols, it can take as input either a single symbol, or a list of symbols.
The
symbol
setter innapari/layers/points/points.py
is modified to look like this:It now tries to broadcast symbols to the number of vertices AFTER converting them to proper
Symbol
instances.Finally,
coerce_symbols
is also used in thecurrent_symbol
setter, but this new implementation does not interfere with its current behavior.Performance changes
Qualitative performance changes can be assessed using the following script, which simulates a random points dataset with
N_vertices
vertices.For different values of
N_vertices
, I time the following duration to define the Points layer:N_vertices = 10_000
N_vertices = 1_000_000
N_vertices = 10_000_000
Note that the proposed implementation has a much nicer scaling with the number of vertices.
Benchmarks
From what I have been able to see, the current benchmarking suite already computes the time it takes to set the data of a Point layer, so there is no need to test for anything else.
Final Checklist