@@ -27,6 +27,11 @@ its result will be passed into the function receiving the argument. If the
27
27
argument is * not* an [ ` DTask ` ] ( @ref ) (instead, some other type of Julia object),
28
28
it'll be passed as-is to the function ` f ` (with some exceptions).
29
29
30
+ !!! note "Task / thread occupancy"
31
+ By default, ` Dagger ` assumes that tasks saturate the thread they are running on and does not try to schedule other tasks on the thread.
32
+ This default can be controlled by specifying [ ` Sch.ThunkOptions ` ] ( @ref ) (more details can be found under [ Scheduler and Thunk options] ( @ref ) ).\
33
+ The section [ Changing the thread occupancy for low-utilization tasks] ( @ref ) shows a runnable example of how to achieve this.
34
+
30
35
## Options
31
36
32
37
The [ ` Options ` ] (@ref Dagger.Options) struct in the second argument position is
@@ -215,3 +220,55 @@ Dagger.spawn(+, Dagger.Options(;single=1), 1, 2)
215
220
216
221
delayed (+ ; single= 1 )(1 , 2 )
217
222
```
223
+
224
+ ### Changing the thread occupancy for low-utilization tasks
225
+
226
+ One of the supported [ ` Sch.ThunkOptions ` ] ( @ref ) is the ` occupancy ` keyword.
227
+ The basic usage looks like this:
228
+
229
+ ``` julia
230
+ Dagger. @spawn occupancy= Dict (Dagger. ThreadProc=> 0 ) fn
231
+ ```
232
+
233
+ Consider the following function definitions:
234
+
235
+ ``` @example sleep
236
+ using Dagger
237
+
238
+ function inner()
239
+ sleep(0.1)
240
+ end
241
+
242
+ function outer_full_occupancy()
243
+ @sync for _ in 1:2
244
+ # By default, full occupancy is assumed
245
+ Dagger.@spawn inner()
246
+ end
247
+ end
248
+
249
+ function outer_low_occupancy()
250
+ @sync for _ in 1:2
251
+ # Here, we're explicitly telling the scheduler to assume low occupancy
252
+ Dagger.@spawn occupancy=Dict(Dagger.ThreadProc => 0) inner()
253
+ end
254
+ end
255
+ nothing #hide
256
+ ```
257
+
258
+ When running the first outer function N times in parallel, you should see parallelization until all threads are blocked:
259
+
260
+ ``` @example sleep
261
+ fetch.([Dagger.@spawn outer_full_occupancy() for _ in 1:1]); # hide
262
+ for N in [1, 2, 4, 8, 16]
263
+ @time fetch.([Dagger.@spawn outer_full_occupancy() for _ in 1:N])
264
+ end
265
+ ```
266
+
267
+ Whereas running the outer function that communicates a low occupancy (` outer_low_occupancy ` ) should run fully in parallel:
268
+
269
+ ``` @example sleep
270
+ fetch.([Dagger.@spawn outer_low_occupancy() for _ in 1:1]); # hide
271
+ for N in [1, 2, 4, 8, 16]
272
+ @time fetch.([Dagger.@spawn outer_low_occupancy() for _ in 1:N])
273
+ end
274
+ ```
0 commit comments