feat: add multithreading to batch raycasting - #16
Open
thomas-bl-christensen wants to merge 4 commits into
Open
Conversation
Embree ships the TBB runtime but not headers. Add a pinned tbb-headers archive to the fetch manifest and wire includes and libs through setup.py and cibuildwheel before-build hooks. Co-authored-by: Cursor <cursoragent@cursor.com>
Move the per-ray Embree calls into a nogil RayJob callback with raw buffer pointers and strides. Behavior is unchanged; this commit still runs the batch on a single thread and sets up parallel dispatch in the next commit. Co-authored-by: Cursor <cursoragent@cursor.com>
Dispatch batches through oneTBB parallel_for using a threads= keyword on EmbreeScene.run(). Match Open3D RaycastingScene semantics: any threads <= 0 uses the TBB default pool, and values greater than 0 cap concurrency via task_arena. Add buffer validation for parallel runs. Co-authored-by: Cursor <cursoragent@cursor.com>
Verify Open3D-style thread counts agree on results: a threads=1 baseline against automatic (0 and negative) and capped (2, 3, 8) runs across query types, buffer layouts, and error paths. Co-authored-by: Cursor <cursoragent@cursor.com>
thomas-bl-christensen
marked this pull request as ready for review
August 5, 2026 12:20
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
I'm trying to migrate a raycasting module based on
open3dtoembreexat work, and need the batch raycasting performance to be comparable between the two. The only difference is thatopen3ddoes multi-threaded raycasting whileembreexdoes not. This PR implements multithreading for batch raycasting inembreex, that results in near-linear speedup in the number of cores on low CPU count and matchesopen3d.On my laptop casting 2M incoherent rays goes from ~5.4M rays/s serially to ~68M rays/s multithreaded.
Design choices
This implementation uses oneTBB for multithreading. I decided to use this over
openMPorstd::thread, sinceembreealready uses it internally. This way we don't add another dependency, just some headers, and share the threading pool.For the
threadssemantics i just copied what is done inopen3d. Both0(default) and-1spawn a thread per core available to oneTBB,threads=Ncaps the number of threads viatbb::task_arena(performance forthreads=1has not measurably changed for me)Profiling
A throwaway branch with profiling scripts can be found here for anyone who wants to experience the near-linear speedup in the number of cores. The
README.mdcontains instructions on the script.Testing
Results are bit-identical to the current serial implementation, which is asserted by the added tests. Note that some tests are flaky until the bugfix PR #14 is implemented.
Implications for users of
embreexI expect this to be an improvement for the majority of users, but I can think of 2 groups that will experience performance degradation.
embreexin their own multithreading, leading to oversubscription on CPU coresembreeuses does not respect CFS quotas, and will spawn too many threads when a container has a CPU quota.For (1) I prefer to prioritize that default calling semantics use multi-threading, even at the cost of their performance until they set
threads=1.For (2) I also prefer to keep it like this. It seems that the issue of oneTBB not respecting cgroups has been fixed and work on updating the oneTBB version in embree is underway. This group of users can hot-fix by setting
threads=...until the oneTBB version is updated and we get quota-awareness for free with no changes.I don't know how big any of these 2 groups of users actually are. I'm also open to a discussion on this.
The code in this PR is mainly AI-generated, but I have reviewed it manually and stand by it.