Skip to content
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

A way to multithread or multiprocess ray intersection. #4

Closed
bsavery opened this issue Jun 18, 2020 · 5 comments
Closed

A way to multithread or multiprocess ray intersection. #4

bsavery opened this issue Jun 18, 2020 · 5 comments

Comments

@bsavery
Copy link
Contributor

bsavery commented Jun 18, 2020

This is probably trying to push the python interpreter past where it is designed but here's the problem.

If tracing many rays (like in a pathtracer). Calling rtcIntersect 1 ray at a time is inefficient and only single threaded. Possible solutions I see are:

  1. Batch rays and call rtcIntersectM but my understanding is this is not multithreaded (https://software.intel.com/en-us/forums/embree-photo-realistic-ray-tracing-kernels/topic/520383)
  2. Fix embree device to allow multiprocessing (python doesn't allow multiple threads to execute concurrently). Right now the embree device can't be pickled for multiprocessing
  3. Wrap some call to do multiple intersect calls inside cython
  4. Add a way to use asyncio. This would allow other threads to do shading or other work while the intersect is happening.
@sampotter
Copy link
Owner

My goal for this wrapper is to keep it very simple and do as little as possible beyond what Embree does itself. The only "extra feature" I want this wrapper to provide is easy compatibility with numpy (for obvious reasons!).

That said, I think #2 is the only viable approach. The other options are things that user could experiment with themselves.

Adding pickling hopefully won't be too complicated. Cython describes its approach to automatically generating a __reduce__ method in their docs on extension types. The news is not so good. ;-) If a class has a __cinit__ method, it's necessary to write a __reduce__ method by hand.

So, we will need to go through and make sure that all of the extension classes can be pickled.

@bsavery
Copy link
Contributor Author

bsavery commented Jun 19, 2020

Yeah, I played around with it a bit and couldn't come up with a great option. That's why I bring it up.

@sampotter
Copy link
Owner

sampotter commented Nov 22, 2020

Had a chance to look into this more.

There are two issues over on the Embree repo which discuss serialization of Embree's BVH:

RenderKit/embree#238
RenderKit/embree#137

It looks like it isn't possible to serialize Embree's BVH and Embree's developers aren't planning on making this possible any time soon. On the other hand, they say that in most cases, just rebuilding the BVH from the geometry is fast enough that just serializing geometry is the way to go.

Our use case is a little different in that, for parallelism, we'll potentially want to serialize and deserialize classes defined in embree.pyx a large number of times, so ideally this would be fast.

I'm going to try implementing __getstate__ and __setstate__ pairs for each class in embree.pyx and see how this goes. Will update here once I've done so.

@sampotter
Copy link
Owner

OK, @bsavery, I spent some more time digging into this. My conclusion is that it would be too much work and would go outside the scope of this library to try to directly parallelize the extension classes provided by embree.pyx. In order to do this, you would need to record the history of all of the different calls and store extra vertex and index data with these classes to be able to implement __reduce__ correctly, reproducing each of the Embree API calls in the correct order.

That said, it should be very easy to get the behavior you want. In my library python-flux, the class flux.shape.TrimeshShapeModel (in this file) wraps a triangle mesh created from a set of vertices and indices to do raytracing using python-embree. Because it stores these vertices and indices as member variables, it's straightforward to implement a __reduce__ method. I recommend creating a class similar to TrimeshShapeModel and implement __reduce__ yourself.

@aluo-x
Copy link

aluo-x commented Dec 1, 2020

Thanks for the fantastic package and the example.

I think extreme caution needs to be used when utilizing this package for scientific purposes. I observed a lot of numerical instability, and significant variance in the results between runs, even with the robust flag set.

This is not a flaw of the python-embree wrapper, but I think inherent in embree itself. My use case is multi-hit along a single ray. Embree2 (using the pyembree) was numerically correct for the first two hits, Embree3 (using python-embree) seems to be correct up only the first hit. I've attempted the tnear=tfar technique, as well as offsetting the origin, both seem to give incorrect results when the offset is vectorized (a vector instead of a constant). Perhaps the dtype is incorrect?

Edit: typo

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

No branches or pull requests

3 participants