Skip to content

feat: add multithreading to batch raycasting - #16

Open
thomas-bl-christensen wants to merge 4 commits into
trimesh:mainfrom
thomas-bl-christensen:feat/threads-raycast
Open

feat: add multithreading to batch raycasting#16
thomas-bl-christensen wants to merge 4 commits into
trimesh:mainfrom
thomas-bl-christensen:feat/threads-raycast

Conversation

@thomas-bl-christensen

@thomas-bl-christensen thomas-bl-christensen commented Aug 5, 2026

Copy link
Copy Markdown

I'm trying to migrate a raycasting module based on open3d to embreex at work, and need the batch raycasting performance to be comparable between the two. The only difference is that open3d does multi-threaded raycasting while embreex does not. This PR implements multithreading for batch raycasting in embreex, that results in near-linear speedup in the number of cores on low CPU count and matches open3d.
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 openMP or std::thread, since embree already uses it internally. This way we don't add another dependency, just some headers, and share the threading pool.
For the threads semantics i just copied what is done in open3d. Both 0 (default) and -1 spawn a thread per core available to oneTBB, threads=N caps the number of threads via tbb::task_arena (performance for threads=1 has 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.md contains 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 embreex

I expect this to be an improvement for the majority of users, but I can think of 2 groups that will experience performance degradation.

  1. Users who wrap embreex in their own multithreading, leading to oversubscription on CPU cores
  2. Users with workloads in cpu-limited containers. The version of oneTBB that embree uses 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.

thomas-bl-christensen and others added 4 commits August 5, 2026 13:52
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 thomas-bl-christensen changed the title Feat: add multithreading to batch raycasting feat: add multithreading to batch raycasting Aug 5, 2026
@thomas-bl-christensen
thomas-bl-christensen marked this pull request as ready for review August 5, 2026 12:20
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.

1 participant