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

Rayon's Minimal Parallel Infrastructure With Bevy Task #11492

Open
wants to merge 13 commits into
base: main
Choose a base branch
from

Conversation

re0312
Copy link
Contributor

@re0312 re0312 commented Jan 23, 2024

Objective

  • Currently ,bevy_task provides a basic abstraction for parallel data,however,it faces some drawbacks that hinder its compatibility with Bevy's requirements:
  1. Lack Of Maintenance. it had been 3 years since last update and not used in bevys internal crate now.
  2. Not fully Optimized. for example, vec.par_splat_map().map(**).collect() can lead to unnecessary memory alloc and free.
  3. Poor Ergonomics.the ergonomic design is subpar and does not align with the philosophy of using Rust's standard iterators.
  4. Limited Ecosystem and Difficult to Extend.

Solution

  • Rayon is a popular and powerful library for the Rust programming language designed for parallel and concurrent programming. it easy to use and extend, this pr introduces rayon's parallel architecture to intergrate with bevys task pool.

  • For more detailed information about Rayon's parallel infrastructure, you can find comprehensive documentation in the official Rayon documentation.

Future

Once this pr or a similar one gets accepted, I would like to implement it into Bevy-ecs query and some rendering systems to enhance ergonomic usage and squeeze out more performance.

we can do something like :

query.par_iter().zip(**).map/filter_map(**).collect()/collect_to_vec(visiblie_entites)  

instead of using 

Local<ThreadLocal<Cell<**>> 

Extend

Compare to directly use Rayon

  • This pr only adopts the abstraction design for data parallelism from Rayon.Currently bevy's parallel iteration design can not support its demand.
  • Rayon has its own implementation of a task pool, but we aim to retain our custom task pool system. Bevy's task pool is more lightweight and async friendly.
  • Rayon includes numerous redundant code and features that are not needed for our purposes.
  • Rayon operates somewhat as a closed box, limiting our ability to modify specific details to cater to our requirements.

@re0312
Copy link
Contributor Author

re0312 commented Jan 23, 2024

As most of the code is migrated from Rayon, I am uncertain about the possibility of encountering any copyright/license issues.

@Kanabenki Kanabenki added C-Feature A new feature, making something new possible A-Tasks Tools for parallel and async work labels Jan 23, 2024
@SkiFire13
Copy link
Contributor

I wonder, what are the advantages of this approach vs integrating rayon?

@re0312
Copy link
Contributor Author

re0312 commented Jan 23, 2024

I wonder, what are the advantages of this approach vs integrating rayon?

this pr uses bevy's task pool rather than rayon's pool, and only pick up the design architecture of rayon. It aims to minimize redundant code, striking a balance between lightweight implementation and ergonomic design.

@re0312
Copy link
Contributor Author

re0312 commented Jan 23, 2024

I wonder, what are the advantages of this approach vs integrating rayon?

I really like rayon, with #384 ,we replaced rayon with our own task pool system ,despite this, our current system lacks a robust abstraction design for data parallelism, resulting in numerous instances of Local<ThreadLocal<Cell<**>> within Bevy's internal crate. This not only diminishes ergonomics but also leads to performance losses."

@re0312 re0312 changed the title introduce rayon's minimal parallel infrastructure to bevy_task Rayon's Minimal Parallel Infrastructure With Bevy Task Jan 24, 2024
@SkiFire13
Copy link
Contributor

I really like rayon, with #384 ,we replaced rayon with our own task pool system

I asked on Discord and this PR came up there too. Looks like Rayon did have some problems but they were supposedly solved (or at least partially) with some update, no? This is not a complete reason to switch back but I guess it may be worth testing how it compares now.

It's also worth mentioning that the original implementation used only the global rayon threadpool (you can create custom threadpools and install them to make any parallel iterator inside use that one). Also, rayon is not async frindly in and of itself, but I don't see why it couldn't be extended with something like async-task to run Futures on its thread pool.

I would also argue that we don't really have a Bevy's implementation of a task pool, we're just offloading most work in the executor to async-executor (which I sometimes see some complains related to its overhead in the multithreaded scheduler), so we don't really control the most important part but we still have to build the ergonomics (e.g. scopes, and now parallel iterators) on top of it.

I'm not saying that rayon would be better than the status quo, but I definitely feel like it could be given a second chance. I briefly looked at what it would take to change bevy_tasks's internals to rayon, but I don't really understand what's the whole business in TaskPool::scope_with_executor and all the executors inside Scope is.


Some of the points in the first post also feel like a reason to use rayon/an existing crate over a custom solution:

Lack Of Maintenance. it had been 3 years since last update and not used in bevys internal crate now.

I don't think adding a lot more code is gonna help with the maintenance. If anything this will increase the amount of work to do.

Limited Ecosystem and Difficult to Extend.

I don't think most of the ecosystem will adopt Bevy's parallel iterator traits. There are however already a lot of crates that do provide implementations of rayon's ParallelIterator trait.

@re0312
Copy link
Contributor Author

re0312 commented Jan 24, 2024

Sorry for the unclear wording. I initial thought to open this pull request because we don't really have a good parallel infrastructure for Bevy's internal (e.g. extract , render system ). Using Rayon directly could be more controversial and hard to move forwar , so I opted to cherry-pick the essential parts from Rayon and integrate them with the current Bevy task system.

It's also worth mentioning that the original implementation used only the global rayon threadpool (you can create custom threadpools and install them to make any parallel iterator inside use that one). Also, rayon is not async frindly in and of itself, but I don't see why it couldn't be extended with something like async-task to run Futures on its thread pool.

I would also argue that we don't really have a Bevy's implementation of a task pool, we're just offloading most work in the executor to async-executor (which I sometimes see some complains related to its overhead in the multithreaded scheduler), so we don't really control the most important part but we still have to build the ergonomics (e.g. scopes, and now parallel iterators) on top of it.

Fair,bevy task system built on async-executor ,It masks many implementation details and has certain limitations .And IIRC, someone in the community trying out Rayon instead of Bevy's task pool, and it looked like it could bring a nice performance boost.

I'm not saying that rayon would be better than the status quo, but I definitely feel like it could be given a second chance. I briefly looked at what it would take to change bevy_tasks's internals to rayon, but I don't really understand what's the whole business in TaskPool::scope_with_executor and all the executors inside Scope is.

yup,That's exactly what I meant. Bevy's task system has been stagnant for a while now. Whether we improve its ergonomics based on the current implementation or switch to Rayon, both options seem promising. We just need more test and to make a decision then move forward.

@NthTensor
Copy link
Contributor

Looks promising. I also really like Rayon and feel bevy_tasks could use some attention.

Rayon seems to be dual licensed just like bevy, and as I understand it this use is acceptable under MIT, so no issue there.

I'm going to spend some time evaluating this after 0.13 is out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Tasks Tools for parallel and async work C-Feature A new feature, making something new possible
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants