src/parallelism.rs

Fri, 13 Oct 2023 13:32:15 -0500

author
Tuomo Valkonen <tuomov@iki.fi>
date
Fri, 13 Oct 2023 13:32:15 -0500
changeset 22
013274b0b388
parent 8
4e09b7829b51
child 11
fc50a2d39053
permissions
-rw-r--r--

Update Cargo.lock to stop build failures with current nightly rust.

8
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
1 /*!
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
2 Parallel computing helper routines.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
3
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
4 It mains the number of threads to use, a thread pool, and provides a budgeting tool
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
5 to limit the number of threads spawned in recursive computations.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
6
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
7 For actually spawning scoped tasks in a thread pool, it currently uses [`rayon`].
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
8 */
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
9
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
10 use std::sync::Once;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
11 use std::num::NonZeroUsize;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
12 use std::thread::available_parallelism;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
13 pub use rayon::{Scope, ThreadPoolBuilder, ThreadPool};
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
14 use std::sync::atomic::{
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
15 AtomicUsize,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
16 Ordering::{Release, Relaxed},
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
17 };
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
18
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
19 #[cfg(use_custom_thread_pool)]
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
20 type Pool = ThreadPool;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
21 #[cfg(not(use_custom_thread_pool))]
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
22 type Pool = GlobalPool;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
23
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
24 const ONE : NonZeroUsize = unsafe { NonZeroUsize::new_unchecked(1) };
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
25 static mut TASK_OVERBUDGETING : AtomicUsize = AtomicUsize::new(1);
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
26 static mut N_THREADS : NonZeroUsize = ONE;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
27 static mut POOL : Option<Pool> = None;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
28 static INIT: Once = Once::new();
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
29
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
30 #[cfg(not(use_custom_thread_pool))]
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
31 mod global_pool {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
32 /// This is a nicer way to use the global pool of [`rayon`].
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
33 pub struct GlobalPool;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
34
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
35 #[cfg(not(use_custom_thread_pool))]
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
36 impl GlobalPool {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
37 #[inline]
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
38 pub fn scope<'scope, OP, R>(&self, op: OP) -> R
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
39 where
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
40 OP: FnOnce(&rayon::Scope<'scope>) -> R + Send,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
41 R: Send {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
42 rayon::scope(op)
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
43 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
44 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
45 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
46
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
47 #[cfg(not(use_custom_thread_pool))]
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
48 pub use global_pool::GlobalPool;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
49
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
50 /// Set the number of threads.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
51 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
52 /// This routine can only be called once.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
53 /// It also calls [`set_task_overbudgeting`] with $m = (n + 1) / 2$.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
54 pub fn set_num_threads(n : NonZeroUsize) {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
55 INIT.call_once(|| unsafe {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
56 N_THREADS = n;
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
57 let n = n.get();
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
58 set_task_overbudgeting((n + 1) / 2);
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
59 POOL = if n > 1 {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
60 #[cfg(use_custom_thread_pool)] {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
61 Some(ThreadPoolBuilder::new().num_threads(n).build().unwrap())
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
62 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
63 #[cfg(not(use_custom_thread_pool))] {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
64 ThreadPoolBuilder::new().num_threads(n).build_global().unwrap();
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
65 Some(GlobalPool)
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
66 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
67 } else {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
68 None
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
69 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
70 });
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
71 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
72
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
73 /// Set overbudgeting count for [`TaskBudget`].
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
74 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
75 /// The initial value is 1. Calling [`set_num_threads`] sets this to $m = (n + 1) / 2$, where
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
76 /// $n$ is the number of threads.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
77 pub fn set_task_overbudgeting(m : usize) {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
78 unsafe { TASK_OVERBUDGETING.store(m, Relaxed) }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
79 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
80
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
81 /// Set the number of threads to the minimum of `n` and [`available_parallelism`].
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
82 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
83 /// This routine can only be called once.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
84 pub fn set_max_threads(n : NonZeroUsize) {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
85 let available = available_parallelism().unwrap_or(ONE);
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
86 set_num_threads(available.min(n));
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
87 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
88
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
89
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
90 /// Get the number of threads
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
91 pub fn num_threads() -> NonZeroUsize {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
92 unsafe { N_THREADS }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
93 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
94
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
95 /// Get the thread pool.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
96 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
97 /// If the number of configured threads is less than 2, this is None.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
98 /// The pool has [`num_threads`]` - 1` threads.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
99 pub fn thread_pool() -> Option<&'static Pool> {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
100 unsafe { POOL.as_ref() }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
101 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
102
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
103 /// Get the number of thread pool workers.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
104 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
105 /// This is [`num_threads`]` - 1`.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
106 pub fn thread_pool_size() -> usize {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
107 unsafe { N_THREADS }.get() - 1
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
108 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
109
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
110 /// Thread budgeting tool.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
111 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
112 /// This allows limiting the number of tasks inserted into the queue in nested computations.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
113 /// Otherwise it wraps [`rayon`] when not single-threaded.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
114 pub enum TaskBudget<'scope, 'scheduler> {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
115 /// No threading performed.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
116 SingleThreaded,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
117 /// Initial multi-threaded state
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
118 MultiThreadedInitial {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
119 /// Thread budget counter
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
120 budget : AtomicUsize,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
121 /// Thread pool
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
122 pool : &'scheduler Pool,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
123 },
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
124 /// Nested multi-threaded state
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
125 MultiThreadedZoom {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
126 /// Thread budget reference
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
127 budget : &'scope AtomicUsize,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
128 scope : &'scheduler Scope<'scope>,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
129 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
130 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
131
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
132 /// Task execution scope for [`TaskBudget`].
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
133 pub enum TaskBudgetScope<'scope, 'scheduler> {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
134 SingleThreaded,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
135 MultiThreaded {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
136 budget : &'scope AtomicUsize,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
137 scope : &'scheduler Scope<'scope>,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
138 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
139 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
140
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
141 impl<'scope, 'b> TaskBudget<'scope, 'b> {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
142 /// Initialise a task budget in the main thread pool.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
143 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
144 /// The number of tasks [executed][TaskBudgetScope::execute] in [scopes][TaskBudget::zoom]
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
145 /// created through the budget is limited to [`num_threads()`]` + overbudget`. If `overbudget`
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
146 /// is `None`, the [global setting][set_task_overbudgeting] is used.ยง
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
147 pub fn init(overbudget : Option<usize>) -> Self {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
148 let n = num_threads().get();
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
149 let m = overbudget.unwrap_or_else(|| unsafe { TASK_OVERBUDGETING.load(Relaxed) });
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
150 if n <= 1 {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
151 Self::SingleThreaded
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
152 } else if let Some(pool) = thread_pool() {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
153 let budget = AtomicUsize::new(n + m);
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
154 Self::MultiThreadedInitial { budget, pool }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
155 } else {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
156 Self::SingleThreaded
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
157 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
158 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
159
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
160 /// Initialise single-threaded thread budgeting.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
161 pub fn none() -> Self { Self::SingleThreaded }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
162 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
163
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
164 impl<'scope, 'scheduler> TaskBudget<'scope, 'scheduler> {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
165 /// Create a sub-scope for launching tasks
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
166 pub fn zoom<'smaller, F, R : Send>(&self, scheduler : F) -> R
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
167 where 'scope : 'smaller,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
168 F : for<'a> FnOnce(TaskBudgetScope<'smaller, 'a>) -> R + Send + 'smaller {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
169 match self {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
170 &Self::SingleThreaded => scheduler(TaskBudgetScope::SingleThreaded),
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
171 &Self::MultiThreadedInitial { ref budget, pool } => {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
172 let budget_ref = unsafe {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
173 // Safe: scheduler is dropped when 'smaller becomes invalid.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
174 std::mem::transmute::<&AtomicUsize, &'smaller AtomicUsize>(budget)
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
175 };
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
176 pool.scope(move |scope| {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
177 scheduler(TaskBudgetScope::MultiThreaded { scope, budget: budget_ref })
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
178 })
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
179 },
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
180 &Self::MultiThreadedZoom { budget, .. /* scope */ } => {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
181 rayon::scope(move |scope| {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
182 scheduler(TaskBudgetScope::MultiThreaded { scope, budget })
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
183 })
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
184 },
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
185 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
186 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
187 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
188
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
189 impl<'scope, 'scheduler> TaskBudgetScope<'scope, 'scheduler> {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
190 /// Queue a task or execute it in this thread if the thread budget is exhausted.
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
191 pub fn execute<F>(&self, job : F)
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
192 where F : for<'b> FnOnce(TaskBudget<'scope, 'b>) + Send + 'scope {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
193 match self {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
194 Self::SingleThreaded => job(TaskBudget::SingleThreaded),
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
195 Self::MultiThreaded { scope, budget } => {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
196 let spawn = budget.fetch_update(Release,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
197 Relaxed,
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
198 |n| (n > 1).then_some(n - 1))
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
199 .is_ok();
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
200 if spawn {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
201 scope.spawn(|scope| {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
202 let task_budget = TaskBudget::MultiThreadedZoom { scope, budget };
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
203 job(task_budget);
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
204 budget.fetch_add(1, Release);
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
205 })
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
206 } else {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
207 job(TaskBudget::MultiThreadedZoom { scope, budget })
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
208 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
209 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
210 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
211 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
212 }
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
213
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
214 /// Runs `scheduler` with a [`TaskBudget`].
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
215 ///
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
216 /// This corresponds to calling `scheduler` with [`TaskBudget::init(None)`].
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
217 pub fn with_task_budget<'scope, F, R>(scheduler : F) -> R
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
218 where F : for<'b> FnOnce(TaskBudget<'scope, 'b>) -> R + 'scope {
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
219 scheduler(TaskBudget::init(None))
4e09b7829b51 Multithreaded bisection tree operations
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff changeset
220 }

mercurial