Skip to content

Clarify what @spawn orders, for users and for backends - #833

Merged
maleadt merged 6 commits into
mainfrom
tb/spawn-host-access
Oct 9, 2026
Merged

maleadt merged 6 commits into
mainfrom
tb/spawn-host-access

Conversation

@maleadt

@maleadt maleadt commented Oct 4, 2026 •

Copy link
Copy Markdown
Member

On CUDA.jl, @spawn loses most of its overlap (#817). CUDA.jl records which stream last used each array, and synchronizes that stream before another stream uses the array. That waits for everything the parent has queued, including work it queued after @spawn, even though wait_event already ordered the child after the work that matters:

fill!(A, 1)                                   # parent's stream
task = KernelAbstractions.@spawn backend begin
    synchronize(backend)                      # waits for fill!, through wait_event
    MPI.Isend(A, comm; dest = 1)              # but taking A's pointer also waits for slow!
end
slow!(backend)(B; ndrange = length(B))        # unrelated work, queued after @spawn

This PR documents what @spawn promises:

  • Users: @spawn orders work on the device, but the host doesn't wait for it. Before passing the parent's results to something outside the backend, like MPI, call synchronize(backend) in the task, as above.
  • Backends: a backend that tracks the last queue of each array should skip that wait when the current queue is already ordered after the array's last use, through an event it waited for or a completed synchronize. Ignoring this is correct but reduces overlap, so it's a recommendation, like task-local queues. synchronize must not wait for work on other queues that the current queue isn't ordered after. That is also only about overlap, but every GPU backend except OpenCL.jl already meets it, so it's a requirement.

CUDA.jl implements this in JuliaGPU/CUDA.jl#3328 (on top of #3329). AMDGPU.jl, Metal.jl and OpenCL.jl track arrays the same way and keep the extra wait for now, which is correct, just with less overlap. OpenCL.jl's synchronize also waits for other queues to check its shared exception mailbox, which JuliaGPU/OpenCL.jl#549 will fix. oneAPI.jl and the CPU backend don't track arrays, so the recommendation doesn't apply to them.

The PR also tightens the @spawn and event docs, so that each fact is stated in one place. User-facing behavior goes in the @spawn docstring, requirements in the KernelInterface docstrings, and the protocol and recommendations on the backend notes page. It also fixes two broken sentences, and stops claiming which device a task started with plain Threads.@spawn uses, since that differs between backends.

Closes #817.

@maleadt
maleadt requested a review from vchuravy October 4, 2026 06:47
@codecov

codecov Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 79.86%. Comparing base (364ef91) to head (4403553).

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #833   +/-   ##
=======================================
  Coverage   79.86%   79.86%           
=======================================
  Files          26       26           
  Lines        2146     2146           
=======================================
  Hits         1714     1714           
  Misses        432      432           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Oct 4, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark Results

Show table
main ae55692... main / ae55692...
const/@Const/Float32/262144 0.523 ± 0.022 ms 0.523 ± 0.016 ms 1 ± 0.053
const/@Const/Float32/65536 0.181 ± 0.0071 ms 0.216 ± 0.0066 ms 0.838 ± 0.042
const/@Const/Float64/262144 0.895 ± 0.018 ms 0.892 ± 0.016 ms 1 ± 0.028
const/@Const/Float64/65536 0.366 ± 0.018 ms 0.365 ± 0.015 ms 1 ± 0.063
const/unmarked/Float32/262144 2.23 ± 0.019 ms 2.23 ± 0.025 ms 0.997 ± 0.014
const/unmarked/Float32/65536 0.594 ± 0.021 ms 0.593 ± 0.014 ms 1 ± 0.043
const/unmarked/Float64/262144 3.15 ± 0.039 ms 3.11 ± 0.049 ms 1.01 ± 0.021
const/unmarked/Float64/65536 0.805 ± 0.022 ms 0.807 ± 0.019 ms 0.998 ± 0.037
launch/3D static workgroup, dynamic ndrange 10.5 ± 39 μs 11.9 ± 0.34 μs 0.882 ± 3.3
launch/3D static workgroup, static ndrange 10.3 ± 0.63 μs 11.8 ± 0.68 μs 0.879 ± 0.074
launch/dynamic workgroup, dynamic ndrange 11.9 ± 0.39 μs 12.1 ± 0.6 μs 0.988 ± 0.059
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 12.2 ± 1.1 μs 12.3 ± 1.6 μs 0.998 ± 0.16
launch/static workgroup, dynamic ndrange 10.5 ± 0.25 μs 10.7 ± 0.6 μs 0.985 ± 0.06
launch/static workgroup, static ndrange 10.3 ± 0.58 μs 11.6 ± 0.39 μs 0.884 ± 0.058
partition/dynamic workgroup, dynamic ndrange 0.0575 ± 0.0047 μs 0.0599 ± 0.0044 μs 0.961 ± 0.11
partition/static workgroup, dynamic ndrange 0.0557 ± 0.0089 μs 0.0559 ± 0.011 μs 0.995 ± 0.26
partition/static workgroup, static ndrange 1.44 ± 0.12 ns 1.55 ± 0.12 ns 0.929 ± 0.11
saxpy/default/Float16/1024 0.0538 ± 0.0039 ms 0.0528 ± 0.0047 ms 1.02 ± 0.12
saxpy/default/Float16/1048576 1.46 ± 0.021 ms 1.47 ± 0.028 ms 0.999 ± 0.024
saxpy/default/Float16/16384 0.0713 ± 0.0084 ms 0.0704 ± 0.0083 ms 1.01 ± 0.17
saxpy/default/Float16/2048 0.0536 ± 0.0054 ms 0.0561 ± 0.005 ms 0.956 ± 0.13
saxpy/default/Float16/256 11.4 ± 0.34 μs 11.4 ± 0.46 μs 0.996 ± 0.05
saxpy/default/Float16/262144 0.399 ± 0.022 ms 0.403 ± 0.016 ms 0.991 ± 0.068
saxpy/default/Float16/32768 0.0924 ± 0.0071 ms 0.0939 ± 0.0071 ms 0.984 ± 0.11
saxpy/default/Float16/4096 0.0553 ± 0.0049 ms 0.0605 ± 0.0075 ms 0.915 ± 0.14
saxpy/default/Float16/512 11.5 ± 0.34 μs 11.7 ± 0.48 μs 0.985 ± 0.05
saxpy/default/Float16/64 11.2 ± 0.26 μs 11.3 ± 0.65 μs 0.992 ± 0.062
saxpy/default/Float16/65536 0.134 ± 0.011 ms 0.135 ± 0.0069 ms 0.991 ± 0.096
saxpy/default/Float32/1024 0.0422 ± 0.037 ms 0.0467 ± 0.037 ms 0.905 ± 1.1
saxpy/default/Float32/1048576 0.71 ± 0.076 ms 0.751 ± 0.11 ms 0.944 ± 0.17
saxpy/default/Float32/16384 0.0583 ± 0.0079 ms 0.059 ± 0.0073 ms 0.988 ± 0.18
saxpy/default/Float32/2048 0.0518 ± 0.0054 ms 0.0547 ± 0.0036 ms 0.947 ± 0.12
saxpy/default/Float32/256 11.2 ± 0.35 μs 11.4 ± 0.36 μs 0.981 ± 0.044
saxpy/default/Float32/262144 0.208 ± 0.023 ms 0.213 ± 0.024 ms 0.977 ± 0.15
saxpy/default/Float32/32768 0.0685 ± 0.0063 ms 0.0716 ± 0.0086 ms 0.956 ± 0.14
saxpy/default/Float32/4096 0.0536 ± 0.0045 ms 0.0541 ± 0.0052 ms 0.99 ± 0.13
saxpy/default/Float32/512 10.8 ± 4.9 μs 14.8 ± 41 μs 0.73 ± 2.1
saxpy/default/Float32/64 11.2 ± 0.4 μs 11.4 ± 0.44 μs 0.982 ± 0.052
saxpy/default/Float32/65536 0.0896 ± 0.0085 ms 0.0915 ± 0.0095 ms 0.979 ± 0.14
saxpy/default/Float64/1024 0.0456 ± 0.038 ms 15.2 ± 38 μs 2.99 ± 7.8
saxpy/default/Float64/1048576 1.04 ± 0.1 ms 1.16 ± 0.14 ms 0.902 ± 0.14
saxpy/default/Float64/16384 0.0604 ± 0.0062 ms 0.063 ± 0.0062 ms 0.957 ± 0.14
saxpy/default/Float64/2048 0.0543 ± 0.0073 ms 0.0556 ± 0.0045 ms 0.978 ± 0.15
saxpy/default/Float64/256 14.2 ± 1.8 μs 14.2 ± 2.2 μs 1.01 ± 0.2
saxpy/default/Float64/262144 0.261 ± 0.047 ms 0.263 ± 0.039 ms 0.995 ± 0.23
saxpy/default/Float64/32768 0.0755 ± 0.0084 ms 0.0791 ± 0.0088 ms 0.954 ± 0.15
saxpy/default/Float64/4096 0.0537 ± 0.0098 ms 0.0524 ± 0.0087 ms 1.02 ± 0.25
saxpy/default/Float64/512 15.2 ± 1 μs 16.3 ± 9.7 μs 0.933 ± 0.56
saxpy/default/Float64/64 11.3 ± 41 μs 11.2 ± 0.28 μs 1.01 ± 3.7
saxpy/default/Float64/65536 0.102 ± 0.011 ms 0.106 ± 0.013 ms 0.963 ± 0.16
saxpy/static workgroup=(1024,)/Float16/1024 0.0519 ± 0.0064 ms 0.0525 ± 0.0069 ms 0.988 ± 0.18
saxpy/static workgroup=(1024,)/Float16/1048576 1.47 ± 0.041 ms 1.47 ± 0.028 ms 1 ± 0.034
saxpy/static workgroup=(1024,)/Float16/16384 0.0715 ± 0.0071 ms 0.0697 ± 0.0071 ms 1.03 ± 0.15
saxpy/static workgroup=(1024,)/Float16/2048 0.0547 ± 0.0036 ms 0.0564 ± 0.0042 ms 0.971 ± 0.096
saxpy/static workgroup=(1024,)/Float16/256 11.1 ± 0.94 μs 11.9 ± 0.66 μs 0.935 ± 0.095
saxpy/static workgroup=(1024,)/Float16/262144 0.404 ± 0.018 ms 0.403 ± 0.018 ms 1 ± 0.062
saxpy/static workgroup=(1024,)/Float16/32768 0.0923 ± 0.0071 ms 0.0903 ± 0.008 ms 1.02 ± 0.12
saxpy/static workgroup=(1024,)/Float16/4096 0.0562 ± 0.0088 ms 0.0589 ± 0.0029 ms 0.956 ± 0.16
saxpy/static workgroup=(1024,)/Float16/512 11.6 ± 0.39 μs 12.7 ± 40 μs 0.919 ± 2.9
saxpy/static workgroup=(1024,)/Float16/64 11.5 ± 3.1 μs 10.8 ± 0.56 μs 1.07 ± 0.29
saxpy/static workgroup=(1024,)/Float16/65536 0.134 ± 0.0096 ms 0.134 ± 0.011 ms 0.996 ± 0.11
saxpy/static workgroup=(1024,)/Float32/1024 14.8 ± 5.2 μs 19.7 ± 37 μs 0.75 ± 1.4
saxpy/static workgroup=(1024,)/Float32/1048576 0.75 ± 0.086 ms 0.764 ± 0.078 ms 0.981 ± 0.15
saxpy/static workgroup=(1024,)/Float32/16384 0.0565 ± 0.0061 ms 0.0587 ± 0.0065 ms 0.962 ± 0.15
saxpy/static workgroup=(1024,)/Float32/2048 0.0532 ± 0.0046 ms 0.0499 ± 0.038 ms 1.07 ± 0.81
saxpy/static workgroup=(1024,)/Float32/256 11.6 ± 0.91 μs 11.3 ± 38 μs 1.02 ± 3.4
saxpy/static workgroup=(1024,)/Float32/262144 0.213 ± 0.023 ms 0.215 ± 0.021 ms 0.988 ± 0.14
saxpy/static workgroup=(1024,)/Float32/32768 0.0679 ± 0.007 ms 0.0717 ± 0.0077 ms 0.947 ± 0.14
saxpy/static workgroup=(1024,)/Float32/4096 0.0517 ± 0.0074 ms 0.0488 ± 0.012 ms 1.06 ± 0.3
saxpy/static workgroup=(1024,)/Float32/512 13.6 ± 42 μs 14.3 ± 5.7 μs 0.947 ± 3
saxpy/static workgroup=(1024,)/Float32/64 11.7 ± 0.92 μs 11.8 ± 0.63 μs 0.987 ± 0.094
saxpy/static workgroup=(1024,)/Float32/65536 0.0897 ± 0.0082 ms 0.0912 ± 0.009 ms 0.983 ± 0.13
saxpy/static workgroup=(1024,)/Float64/1024 0.0495 ± 0.039 ms 15.7 ± 37 μs 3.15 ± 7.7
saxpy/static workgroup=(1024,)/Float64/1048576 1.11 ± 0.14 ms 1.11 ± 0.17 ms 0.999 ± 0.2
saxpy/static workgroup=(1024,)/Float64/16384 0.0618 ± 0.0067 ms 0.0621 ± 0.0068 ms 0.995 ± 0.15
saxpy/static workgroup=(1024,)/Float64/2048 0.0528 ± 0.0066 ms 0.0527 ± 0.0059 ms 1 ± 0.17
saxpy/static workgroup=(1024,)/Float64/256 0.0503 ± 0.041 ms 13.8 ± 43 μs 3.65 ± 12
saxpy/static workgroup=(1024,)/Float64/262144 0.256 ± 0.029 ms 0.259 ± 0.036 ms 0.989 ± 0.18
saxpy/static workgroup=(1024,)/Float64/32768 0.0734 ± 0.0071 ms 0.0776 ± 0.01 ms 0.945 ± 0.15
saxpy/static workgroup=(1024,)/Float64/4096 0.054 ± 0.0075 ms 0.0542 ± 0.007 ms 0.996 ± 0.19
saxpy/static workgroup=(1024,)/Float64/512 19 ± 37 μs 0.0516 ± 0.037 ms 0.369 ± 0.77
saxpy/static workgroup=(1024,)/Float64/64 11.7 ± 0.43 μs 11.8 ± 0.73 μs 0.994 ± 0.072
saxpy/static workgroup=(1024,)/Float64/65536 0.1 ± 0.0096 ms 0.104 ± 0.012 ms 0.962 ± 0.15
time_to_load 0.492 ± 0.0072 s 0.499 ± 0.0052 s 0.988 ± 0.018
main ae55692... main / ae55692...
const/@Const/Float32/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/@Const/Float32/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/@Const/Float64/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/@Const/Float64/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float32/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float32/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float64/262144 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
const/unmarked/Float64/65536 9 allocs: 0.203 kB 9 allocs: 0.203 kB 1
launch/3D static workgroup, dynamic ndrange 9 allocs: 0.219 kB 9 allocs: 0.219 kB 1
launch/3D static workgroup, static ndrange 9 allocs: 0.219 kB 9 allocs: 0.219 kB 1
launch/dynamic workgroup, dynamic ndrange 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
launch/dynamic workgroup, dynamic ndrange, workgroupsize given 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
launch/static workgroup, dynamic ndrange 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
launch/static workgroup, static ndrange 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
partition/dynamic workgroup, dynamic ndrange 2 allocs: 0.0625 kB 2 allocs: 0.0625 kB 1
partition/static workgroup, dynamic ndrange 2 allocs: 32 B 2 allocs: 32 B 1
partition/static workgroup, static ndrange 0 allocs: 0 B 0 allocs: 0 B
saxpy/default/Float16/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float16/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float16/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float16/32768 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float16/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float16/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float16/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float32/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float32/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float32/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float32/32768 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float32/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float32/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float64/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float64/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float64/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float64/32768 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/default/Float64/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/default/Float64/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/default/Float64/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float16/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float16/16384 8 allocs: 0.141 kB 12 allocs: 0.25 kB 0.562
saxpy/static workgroup=(1024,)/Float16/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float16/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float16/32768 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float16/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float16/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float16/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float32/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float32/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float32/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float32/32768 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float32/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float32/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float32/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float64/1024 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/1048576 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float64/16384 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/2048 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/256 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float64/262144 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
saxpy/static workgroup=(1024,)/Float64/32768 8 allocs: 0.141 kB 12 allocs: 0.25 kB 0.562
saxpy/static workgroup=(1024,)/Float64/4096 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/512 8 allocs: 0.141 kB 8 allocs: 0.141 kB 1
saxpy/static workgroup=(1024,)/Float64/64 5 allocs: 0.0938 kB 5 allocs: 0.0938 kB 1
saxpy/static workgroup=(1024,)/Float64/65536 12 allocs: 0.25 kB 12 allocs: 0.25 kB 1
time_to_load 0.2 k allocs: 11.8 kB 0.2 k allocs: 11.8 kB 1

Benchmark Plots

A plot of the benchmark results have been uploaded as an artifact to the workflow run for this PR.
Go to "Actions"->"Benchmark a pull request"->[the most recent run]->"Artifacts" (at the bottom).

@maleadt
maleadt force-pushed the tb/spawn-host-access branch from 5571d1f to f3c60b0 Compare October 4, 2026 08:26
A sentence about the device of a new task was cut off, and the note on exceptions
lacked punctuation and ran into the next paragraph.
The spawned task's work is ordered after its parent's on the device, but code
in the task that passes the parent's results to something outside the backend,
e.g., an MPI call on a GPU buffer, has to synchronize first. Some backends
currently do so implicitly when the buffer's pointer is taken, which portable
code can't rely on. Also say that the child isn't ordered against the parent's
later work, rather than that it can't rely on that work's data.
@maleadt
maleadt force-pushed the tb/spawn-host-access branch from f3c60b0 to b63709f Compare October 7, 2026 15:59
Backends that track which queue last used an array make another queue wait
before using it. If that wait ignores the order set up by wait_event, or by a
completed synchronize, the spawned task's first use of an array shared with its
parent waits for everything the parent has queued, including work queued after
@Spawn (#817). CUDA.jl, AMDGPU.jl, Metal.jl and OpenCL.jl all track arrays this
way. Recommend respecting that order, and likewise for what synchronize waits
for. Like task-local queues, this is about overlap rather than correctness, so
it is a recommendation. Waits for memory accessibility or lifetime are not
affected.
@maleadt
maleadt force-pushed the tb/spawn-host-access branch from b63709f to 9ade488 Compare October 7, 2026 16:04
Device selection was explained three times and the implementation requirements of
record_event and wait_event were repeated on the notes page. Keep each fact in
one place: the user-facing behavior in the @Spawn docstring, the correctness
requirements in the KernelInterface docstrings, and the protocol and the
performance recommendations on the notes page. Also drop the note on exceptions,
which the guarantees at the top already cover, and stop claiming that switching
devices leaves the new queue unordered, since it may already be ordered by other
means.
@vchuravy
vchuravy marked this pull request as ready for review October 7, 2026 20:13
Comment thread docs/src/implementations.md Outdated
Comment thread docs/src/implementations.md Outdated
Comment thread lib/KernelInterface/src/host.jl Outdated
Comment thread src/spawn.jl Outdated
A synchronize that also waits for work on other queues, e.g. work another task
queued, costs overlap without making any program more correct. All GPU backends
except OpenCL.jl already wait only for the current queue (OpenCL.jl waits for
other queues to check its shared exception mailbox, JuliaGPU/OpenCL.jl#549), so
make this a requirement in the synchronize docstring rather than a
recommendation. Also state the purpose of the ownership recommendation as a goal
instead of describing what happens without it.
CUDA.jl and AMDGPU.jl make device! set the default device for new tasks as well,
while oneAPI.jl and OpenCL.jl keep it task-local, so a task started with
Threads.@Spawn may or may not run on its parent's device. Also say which work
record_event captures without describing what it doesn't.
@maleadt
maleadt requested a review from vchuravy October 9, 2026 08:51
@maleadt

maleadt commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

CI failures unrelated, this is a doc-only PR.

@maleadt
maleadt merged commit d048363 into main Oct 9, 2026
61 of 67 checks passed
@maleadt
maleadt deleted the tb/spawn-host-access branch October 9, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KernelAbstractions.@spawn runs into CUDA.jl's implicit cross-stream synchronization

2 participants