-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
Task System for Bevy #384
Merged
Merged
Task System for Bevy #384
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
0bf6700
Add bevy_tasks crate to replace rayon.
lachlansneff fe6cf0d
More tuning of bevy_tasks api
lachlansneff 058e26c
Add global task pool to bevy_tasks
lachlansneff d6cbe59
Replace uses of rayon with bevy_tasks
lachlansneff 1a55abe
Fix leaked task_pool when attempting to install while a task pool was…
lachlansneff c76cb5f
Fix typo
lachlansneff cd7ce62
Add spawn() public function to pass raw futures through to the execut…
aclysma 3014032
Merge branch 'master' of https://github.com/bevyengine/bevy into bevy…
lachlansneff 4b3619f
Merge branch 'bevy-tasks' of github.com:lachlansneff/bevy into bevy-t…
lachlansneff 4232e75
Update bevy_tasks with new Usage type parameter and make the task poo…
lachlansneff 93fcd7d
Add to root Cargo.toml and lib.rs
lachlansneff e406b07
Add default task pools and method for configuring them (#2)
aclysma 5a59d62
Fix tests
lachlansneff d092add
Fix thread_pool_resources example
lachlansneff 8996109
Bevy tasks (#3)
aclysma 224f358
Merge branch 'master' into bevy-tasks
aclysma 879afa9
Fix tests
aclysma 77b126d
Add version to bevy_tasks references in cargo.toml files
aclysma File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
use bevy_ecs::Resources; | ||
use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IOTaskPool, TaskPoolBuilder}; | ||
|
||
/// Defines a simple way to determine how many threads to use given the number of remaining cores | ||
/// and number of total cores | ||
#[derive(Clone)] | ||
pub struct TaskPoolThreadAssignmentPolicy { | ||
/// Force using at least this many threads | ||
pub min_threads: usize, | ||
/// Under no circumstance use more than this many threads for this pool | ||
pub max_threads: usize, | ||
/// Target using this percentage of total cores, clamped by min_threads and max_threads. It is | ||
/// permitted to use 1.0 to try to use all remaining threads | ||
pub percent: f32, | ||
} | ||
|
||
impl TaskPoolThreadAssignmentPolicy { | ||
/// Determine the number of threads to use for this task pool | ||
fn get_number_of_threads(&self, remaining_threads: usize, total_threads: usize) -> usize { | ||
assert!(self.percent >= 0.0); | ||
let mut desired = (total_threads as f32 * self.percent).round() as usize; | ||
|
||
// Limit ourselves to the number of cores available | ||
desired = desired.min(remaining_threads); | ||
|
||
// Clamp by min_threads, max_threads. (This may result in us using more threads than are | ||
// available, this is intended. An example case where this might happen is a device with | ||
// <= 2 threads. | ||
bevy_math::clamp(desired, self.min_threads, self.max_threads) | ||
} | ||
} | ||
|
||
/// Helper for configuring and creating the default task pools. For end-users who want full control, | ||
/// insert the default task pools into the resource map manually. If the pools are already inserted, | ||
/// this helper will do nothing. | ||
#[derive(Clone)] | ||
pub struct DefaultTaskPoolOptions { | ||
/// If the number of physical cores is less than min_total_threads, force using min_total_threads | ||
pub min_total_threads: usize, | ||
/// If the number of physical cores is grater than max_total_threads, force using max_total_threads | ||
pub max_total_threads: usize, | ||
|
||
/// Used to determine number of IO threads to allocate | ||
pub io: TaskPoolThreadAssignmentPolicy, | ||
/// Used to determine number of async compute threads to allocate | ||
pub async_compute: TaskPoolThreadAssignmentPolicy, | ||
/// Used to determine number of compute threads to allocate | ||
pub compute: TaskPoolThreadAssignmentPolicy, | ||
} | ||
|
||
impl Default for DefaultTaskPoolOptions { | ||
fn default() -> Self { | ||
DefaultTaskPoolOptions { | ||
// By default, use however many cores are available on the system | ||
min_total_threads: 1, | ||
max_total_threads: std::usize::MAX, | ||
|
||
// Use 25% of cores for IO, at least 1, no more than 4 | ||
io: TaskPoolThreadAssignmentPolicy { | ||
min_threads: 1, | ||
max_threads: 4, | ||
percent: 0.25, | ||
}, | ||
|
||
// Use 25% of cores for async compute, at least 1, no more than 4 | ||
async_compute: TaskPoolThreadAssignmentPolicy { | ||
min_threads: 1, | ||
max_threads: 4, | ||
percent: 0.25, | ||
}, | ||
|
||
// Use all remaining cores for compute (at least 1) | ||
compute: TaskPoolThreadAssignmentPolicy { | ||
min_threads: 1, | ||
max_threads: std::usize::MAX, | ||
percent: 1.0, // This 1.0 here means "whatever is left over" | ||
}, | ||
} | ||
} | ||
} | ||
|
||
impl DefaultTaskPoolOptions { | ||
/// Create a configuration that forces using the given number of threads. | ||
pub fn with_num_threads(thread_count: usize) -> Self { | ||
let mut options = Self::default(); | ||
options.min_total_threads = thread_count; | ||
options.max_total_threads = thread_count; | ||
|
||
options | ||
} | ||
|
||
/// Inserts the default thread pools into the given resource map based on the configured values | ||
pub fn create_default_pools(&self, resources: &mut Resources) { | ||
let total_threads = bevy_math::clamp( | ||
bevy_tasks::logical_core_count(), | ||
self.min_total_threads, | ||
self.max_total_threads, | ||
); | ||
|
||
let mut remaining_threads = total_threads; | ||
|
||
if !resources.contains::<IOTaskPool>() { | ||
cart marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Determine the number of IO threads we will use | ||
let io_threads = self | ||
.io | ||
.get_number_of_threads(remaining_threads, total_threads); | ||
remaining_threads -= io_threads; | ||
|
||
resources.insert(IOTaskPool( | ||
TaskPoolBuilder::default() | ||
.num_threads(io_threads) | ||
.thread_name("IO Task Pool".to_string()) | ||
.build(), | ||
)); | ||
} | ||
|
||
if !resources.contains::<AsyncComputeTaskPool>() { | ||
// Determine the number of async compute threads we will use | ||
let async_compute_threads = self | ||
.async_compute | ||
.get_number_of_threads(remaining_threads, total_threads); | ||
remaining_threads -= async_compute_threads; | ||
|
||
resources.insert(AsyncComputeTaskPool( | ||
TaskPoolBuilder::default() | ||
.num_threads(async_compute_threads) | ||
.thread_name("Async Compute Task Pool".to_string()) | ||
.build(), | ||
)); | ||
} | ||
|
||
if !resources.contains::<ComputeTaskPool>() { | ||
// Determine the number of compute threads we will use | ||
// This is intentionally last so that an end user can specify 1.0 as the percent | ||
let compute_threads = self | ||
.compute | ||
.get_number_of_threads(remaining_threads, total_threads); | ||
|
||
resources.insert(ComputeTaskPool( | ||
TaskPoolBuilder::default() | ||
.num_threads(compute_threads) | ||
.thread_name("Compute Task Pool".to_string()) | ||
.build(), | ||
)); | ||
} | ||
} | ||
} |
This file contains 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
This file contains 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
This file contains 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
Oops, something went wrong.
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.
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.
I'm not convinced bevy_tasks should be hard-coded into apps, especially given that we're just adding resources. Can we make this a plugin that we add with
add_default_plugins()
?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.
Making a plugin in bevy_tasks will cause circular dependencies (app depends on ecs, ecs depends on tasks). Where to do you want it to be?