Skip to content

Commit 933adf7

Browse files
vchuravymaleadtluraess
committed
Document the semantics of copyto! and add pagelock! (#555)
Co-authored-by: Tim Besard <[email protected]> Co-authored-by: Ludovic Räss <[email protected]>
1 parent da23939 commit 933adf7

File tree

2 files changed

+47
-2
lines changed

2 files changed

+47
-2
lines changed

src/KernelAbstractions.jl

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,53 @@ macro Const end
110110
"""
111111
copyto!(::Backend, dest::AbstractArray, src::AbstractArray)
112112
113-
Perform a `copyto!` operation that execution ordered with respect to the backend.
113+
Perform an asynchronous `copyto!` operation that is execution ordered with respect to the back-end.
114+
115+
For most users, `Base.copyto!` should suffice, performance a simple, synchronous copy.
116+
Only when you know you need asynchronicity w.r.t. the host, you should consider using
117+
this asynchronous version, which requires additional lifetime guarantees as documented below.
118+
119+
!!! warning
120+
121+
Because of the asynchronous nature of this operation, the user is required to guarantee that the lifetime
122+
of the source extends past the *completion* of the copy operation as to avoid a use-after-free. It is not
123+
sufficient to simply use `GC.@preserve` around the call to `copyto!`, because that only extends the
124+
lifetime past the operation getting queued. Instead, it may be required to `synchronize()`,
125+
or otherwise guarantee that the source will still be around when the copy is executed:
126+
127+
```julia
128+
arr = zeros(64)
129+
GC.@preserve arr begin
130+
copyto!(backend, arr, ...)
131+
# other operations
132+
synchronize(backend)
133+
end
134+
```
114135
115136
!!! note
116-
Backend implementations **must** implement this function.
137+
138+
On some back-ends it may be necessary to first call [`pagelock!`](@ref) on host memory
139+
to enable fully asynchronous behavior w.r.t to the host.
140+
141+
!!! note
142+
Backends **must** implement this function.
117143
"""
118144
function copyto! end
119145

146+
"""
147+
pagelock!(::Backend, dest::AbstractArray)
148+
149+
Pagelock (pin) a host memory buffer for a backend device. This may be necessary for [`copyto!`](@ref)
150+
to perform asynchronously w.r.t to the host/
151+
152+
This function should return `nothing`; or `missing` if not implemented.
153+
154+
155+
!!! note
156+
Backends **may** implement this function.
157+
"""
158+
function pagelock! end
159+
120160
"""
121161
synchronize(::Backend)
122162
@@ -562,6 +602,10 @@ function functional(::Backend)
562602
return missing
563603
end
564604

605+
function pagelock!(::Backend, x)
606+
return missing
607+
end
608+
565609
include("nditeration.jl")
566610
using .NDIteration
567611
import .NDIteration: get

src/cpu.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function copyto!(backend::CPU, A, B)
3333
end
3434

3535
functional(::CPU) = true
36+
pagelock!(::CPU, x) = nothing
3637

3738
function (obj::Kernel{CPU})(args...; ndrange = nothing, workgroupsize = nothing)
3839
ndrange, workgroupsize, iterspace, dynamic = launch_config(obj, ndrange, workgroupsize)

0 commit comments

Comments
 (0)