Skip to content

Commit fa7f828

Browse files
committed
docs: Update scope docs
1 parent d264e16 commit fa7f828

File tree

3 files changed

+23
-48
lines changed

3 files changed

+23
-48
lines changed

docs/src/index.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -198,15 +198,17 @@ While Dagger generally "just works", sometimes one needs to exert some more
198198
fine-grained control over how the scheduler allocates work. There are two
199199
parallel mechanisms to achieve this: Scheduler options (from
200200
`Dagger.Sch.SchedulerOptions`) and Thunk options (from
201-
`Dagger.Sch.ThunkOptions`). These two options structs generally contain the
202-
same options, with the difference being that Scheduler options operate
201+
`Dagger.Sch.ThunkOptions`). These two options structs contain many shared
202+
options, with the difference being that Scheduler options operate
203203
globally across an entire DAG, and Thunk options operate on a thunk-by-thunk
204-
basis. Scheduler options can be constructed and passed to `collect()` or
205-
`compute()` as the keyword argument `options` for lazy API usage:
204+
basis.
205+
206+
Scheduler options can be constructed and passed to `collect()` or `compute()`
207+
as the keyword argument `options` for lazy API usage:
206208

207209
```julia
208210
t = @par 1+2
209-
opts = Dagger.Sch.ThunkOptions(;single=1) # Execute on worker 1
211+
opts = Dagger.Sch.SchedulerOptions(;single=1) # Execute on worker 1
210212

211213
compute(t; options=opts)
212214

@@ -219,7 +221,6 @@ Thunk options can be passed to `@spawn/spawn`, `@par`, and `delayed` similarly:
219221
# Execute on worker 1
220222

221223
Dagger.@spawn single=1 1+2
222-
223224
Dagger.spawn(+, 1, 2; single=1)
224225

225226
opts = Dagger.Sch.ThunkOptions(;single=1)

docs/src/processors.md

Lines changed: 2 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -76,42 +76,13 @@ processor B. This mechanism uses Julia's Serialization library to serialize and
7676
deserialize data, so data must be serializable for this mechanism to work
7777
properly.
7878

79-
### Future: Hierarchy Generic Path Move
80-
81-
NOTE: This used to be the default move behavior, but was removed because it
82-
wasn't considered helpful, and there were not any processor implementations
83-
that made use of it.
84-
85-
Movement of data between any two processors is decomposable into a sequence of
86-
"moves" between a child and its parent, termed a "generic path move". Movement
87-
of data may also take "shortcuts" between nodes in the tree which are not
88-
directly connected if enabled by libraries or the user, which may make use of
89-
IPC mechanisms to transfer data more directly and efficiently (such as
90-
Infiniband, GPU RDMA, NVLINK, etc.). All data is considered local to some
91-
processor, and may only be operated on by another processor by first doing an
92-
explicit move operation to that processor.
93-
9479
## Processor Selection
9580

9681
By default, Dagger uses the CPU to process work, typically single-threaded per
9782
cluster node. However, Dagger allows access to a wider range of hardware and
9883
software acceleration techniques, such as multithreading and GPUs. These more
9984
advanced (but performant) accelerators are disabled by default, but can easily
100-
be enabled by using Scheduler/Thunk options in the `proclist` field. If
101-
`nothing`, all default processors will be used. If a vector of types, only the
102-
processor types contained in `options.proclist` will be used to compute all or
103-
a given thunk. If a function, it will be called for each processor (with the
104-
processor as the argument) until it returns `true`.
105-
106-
```julia
107-
opts = Dagger.Sch.ThunkOptions(;proclist=nothing) # default behavior
108-
# OR
109-
opts = Dagger.Sch.ThunkOptions(;proclist=[DaggerGPU.CuArrayProc]) # only execute on CuArrayProc
110-
# OR
111-
opts = Dagger.Sch.ThunkOptions(;proclist=(proc)->(proc isa Dagger.ThreadProc && proc.tid == 3)) # only run on ThreadProc with thread ID 3
112-
113-
t = Dagger.@par options=opts sum(X) # do sum(X) on the specified processor
114-
```
85+
be enabled by using scopes (see [Scopes](@ref) for details).
11586

11687
## Resource Control
11788

@@ -137,7 +108,7 @@ sufficient resources become available by thunks completing execution.
137108
The [DaggerGPU.jl](https://github.com/JuliaGPU/DaggerGPU.jl) package can be
138109
imported to enable GPU acceleration for NVIDIA and AMD GPUs, when available.
139110
The processors provided by that package are not enabled by default, but may be
140-
enabled via `options.proclist` as usual.
111+
enabled via custom scopes ([Scopes](@ref)).
141112

142113
### Future: Network Devices and Topology
143114

docs/src/scopes.md

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ considered valid.
1515

1616
Let's take the example of a webcam handle generated by VideoIO.jl. This handle
1717
is a C pointer, and thus has process scope. We can open the handle on a given
18-
process, and set the scope of the resulting data to a `ProcessScope()`, which
19-
defaults to the current Julia process:
18+
process, and set the scope of the resulting data to be locked to the current
19+
process with `Dagger.scope` to construct a `ProcessScope`:
2020

2121
```julia
22-
using VideoIO
22+
using VideoIO, Distributed
2323

2424
function get_handle()
2525
handle = VideoIO.opencamera()
2626
proc = Dagger.thunk_processor()
27-
scope = ProcessScope()
27+
scope = Dagger.scope(worker=myid()) # constructs a `ProcessScope`
2828
return Dagger.tochunk(handle, proc, scope)
2929
end
3030

@@ -41,7 +41,7 @@ cam_frame = Dagger.@spawn read(cam_handle)
4141

4242
The `cam_frame` task is executed within any processor on the same process that
4343
the `cam_handle` task was executed on. Of course, the resulting camera frame is
44-
*not* scoped to anywhere specific (denoted as `AnyScope()`), and thus
44+
*not* scoped to anywhere specific (denoted as `AnyScope`), and thus
4545
computations on it may execute anywhere.
4646

4747
You may also encounter situations where you want to use a callable struct (such
@@ -53,13 +53,15 @@ using Flux
5353
m = Chain(...)
5454
# If `m` is only safe to transfer to and execute on this process,
5555
# we can set a `ProcessScope` on it:
56-
result = Dagger.@spawn scope=ProcessScope() m(rand(8,8))
56+
result = Dagger.@spawn scope=Dagger.scope(worker=myid()) m(rand(8,8))
5757
```
5858

5959
Setting a scope on the function treats it as a regular piece of data (like the
6060
arguments to the function), so it participates in the scoping rules described
6161
in the following sections all the same.
6262

63+
[`Dagger.scope`](@ref)
64+
6365
Now, let's try out some other kinds of scopes, starting with `NodeScope`. This
6466
scope encompasses the server that one or more Julia processes may be running
6567
on. Say we want to use memory mapping (mmap) to more efficiently send arrays
@@ -75,6 +77,7 @@ function generate()
7577
arr = Mmap.mmap(path, Matrix{Int}, (64,64))
7678
fill!(arr, 1)
7779
Mmap.sync!(arr)
80+
# Note: Dagger.scope() does not yet support node scopes
7881
Dagger.tochunk(path, Dagger.thunk_processor(), NodeScope())
7982
end
8083

@@ -87,14 +90,14 @@ a = Dagger.@spawn generate()
8790
@assert fetch(Dagger.@spawn consume(a)) == 64*64
8891
```
8992

90-
Whatever server `a` executed on, `b` will also execute on!
93+
Whatever server `a` executed on, `b` will also execute on it!
9194

9295
Finally, we come to the "lowest" scope on the scope hierarchy, the
9396
`ExactScope`. This scope specifies one exact processor as the bounding scope,
94-
and is typically useful in certain limited cases. We won't provide an example
95-
here, because you don't usually need to ever use this scope, but if you already
96-
understand the `NodeScope` and `ProcessScope`, the `ExactScope` should be easy
97-
to figure out.
97+
and is typically useful in certain limited cases (such as data existing only on
98+
a specific GPU). We won't provide an example here, because you don't usually
99+
need to ever use this scope, but if you already understand the `NodeScope` and
100+
`ProcessScope`, the `ExactScope` should be easy to figure out.
98101

99102
## Union Scopes
100103

0 commit comments

Comments
 (0)