Skip to content

Poll an event capturing the context's work when synchronizing the device - #3396

Merged
maleadt merged 2 commits into
mainfrom
tb/context-sync-event
Oct 15, 2026
Merged

maleadt merged 2 commits into
mainfrom
tb/context-sync-event

Conversation

@maleadt

@maleadt maleadt commented Oct 15, 2026

Copy link
Copy Markdown
Member

Since #3315, device_synchronize() always hands the synchronization to a worker thread, because a context can't be polled. On the benchmark dashboard, cuda/synchronization/context/auto went from ~1.0 µs to ~6.8 µs as a result. It reached ~7.8 µs after the #3318 stack landed: the worker handoff got ~10% slower, and gpuci1's clocks were locked the same day.

CUDA 12.5 added cuCtxRecordEvent, which records an event capturing all of a context's work (including its green contexts). Unlike the context, that event can be polled. On 12.5+ drivers, nonblocking device_synchronize now goes through the existing event path: poll, and if done, synchronize the event so that kernel output is flushed; otherwise wait on a worker as before. The event gets EVENT_BLOCKING_SYNC when the context is configured with CTX_SCHED_BLOCKING_SYNC, so long waits keep following the context's scheduling policy. Blocking synchronization and older drivers still use cuCtxSynchronize.

Median times on an RTX 5080 (3 interleaved runs):

main PR
context/auto 2.04–2.25 µs 0.66–0.77 µs
context/nonblocking 2.01–2.44 µs 1.94–1.99 µs
context/blocking 172–176 ns 171–176 ns

The printf-flush test now covers device_synchronize as well, and the non-blocking-stream gate test also runs with spin=false.

@maleadt maleadt added the performance Runtime performance. label Oct 15, 2026
@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

CUDA.jl Benchmarks

Details
Benchmark suite Current: 282fa89 Previous: ea49380 Ratio
array/accumulate/Float32/1d 64294 ns 64036 ns 1.00
array/accumulate/Float32/dims=1 209193 ns 208812 ns 1.00
array/accumulate/Float32/dims=1L 231191 ns 230609 ns 1.00
array/accumulate/Float32/dims=2 93552 ns 92377 ns 1.01
array/accumulate/Float32/dims=2L 4414263 ns 4414351 ns 1.00
array/accumulate/Int64/1d 106455 ns 106105 ns 1.00
array/accumulate/Int64/dims=1 224501 ns 222970 ns 1.01
array/accumulate/Int64/dims=1L 404588 ns 403514 ns 1.00
array/accumulate/Int64/dims=2 112681 ns 111534 ns 1.01
array/accumulate/Int64/dims=2L 5302726 ns 5303201 ns 1.00
array/broadcast 10789 ns 10425 ns 1.03
array/broadcast launch 7303.75 ns 6876 ns 1.06
array/construct 951.0416666666666 ns 958.1 ns 0.99
array/copy 17160 ns 17084 ns 1.00
array/copyto!/cpu_to_gpu 210619 ns 206949 ns 1.02
array/copyto!/gpu_to_cpu 242513 ns 240012 ns 1.01
array/copyto!/gpu_to_gpu 9057 ns 8931 ns 1.01
array/iteration/findall/bool 47968 ns 48499 ns 0.99
array/iteration/findall/int 71072 ns 69835 ns 1.02
array/iteration/findfirst/bool 116565 ns 114590 ns 1.02
array/iteration/findfirst/int 113982 ns 112292 ns 1.02
array/iteration/findmin/1d 67618 ns 66134 ns 1.02
array/iteration/findmin/2d 68300 ns 67092 ns 1.02
array/iteration/logical 52954 ns 52718 ns 1.00
array/iteration/scalar 61768 ns 62269 ns 0.99
array/permutedims/2d 47814 ns 47213 ns 1.01
array/permutedims/3d 45014 ns 44662 ns 1.01
array/permutedims/4d 48297 ns 47947 ns 1.01
array/random/rand/Float32 11289 ns 11026 ns 1.02
array/random/rand/Int64 18093 ns 17878 ns 1.01
array/random/rand!/Float32 8452 ns 8338.333333333334 ns 1.01
array/random/rand!/Int64 15869 ns 15757 ns 1.01
array/random/randn/Float32 34339 ns 34043 ns 1.01
array/random/randn!/Float32 25136 ns 25361 ns 0.99
array/reductions/mapreduce/Float32/1d 50875 ns 49702 ns 1.02
array/reductions/mapreduce/Float32/dims=1 43934 ns 42350 ns 1.04
array/reductions/mapreduce/Float32/dims=1L 73017 ns 72621 ns 1.01
array/reductions/mapreduce/Float32/dims=2 45479 ns 44306 ns 1.03
array/reductions/mapreduce/Float32/dims=2L 74455 ns 73613 ns 1.01
array/reductions/mapreduce/Int64/1d 52227 ns 50450 ns 1.04
array/reductions/mapreduce/Int64/dims=1 46088 ns 45556 ns 1.01
array/reductions/mapreduce/Int64/dims=1L 113518 ns 113168 ns 1.00
array/reductions/mapreduce/Int64/dims=2 46770 ns 46043 ns 1.02
array/reductions/mapreduce/Int64/dims=2L 100916 ns 99328 ns 1.02
array/reductions/reduce/Float32/1d 50629 ns 48970 ns 1.03
array/reductions/reduce/Float32/dims=1 44848 ns 42528 ns 1.05
array/reductions/reduce/Float32/dims=1L 73899 ns 72521 ns 1.02
array/reductions/reduce/Float32/dims=2 46348 ns 44789 ns 1.03
array/reductions/reduce/Float32/dims=2L 74798 ns 73801 ns 1.01
array/reductions/reduce/Int64/1d 52012 ns 50745 ns 1.02
array/reductions/reduce/Int64/dims=1 46296 ns 45758 ns 1.01
array/reductions/reduce/Int64/dims=1L 113841 ns 112810 ns 1.01
array/reductions/reduce/Int64/dims=2 46848 ns 46313 ns 1.01
array/reductions/reduce/Int64/dims=2L 101315 ns 100440 ns 1.01
array/reverse/1d 24024 ns 23468 ns 1.02
array/reverse/1dL 129723 ns 129150 ns 1.00
array/reverse/1dL_inplace 71117 ns 70962 ns 1.00
array/reverse/1d_inplace 13010 ns 12558 ns 1.04
array/reverse/2d 23213 ns 22933 ns 1.01
array/reverse/2dL 81687 ns 81376 ns 1.00
array/reverse/2dL_inplace 71643 ns 71131 ns 1.01
array/reverse/2d_inplace 15545 ns 15114 ns 1.03
array/sorting/1d 750713 ns 751253 ns 1.00
array/sorting/2d 195436 ns 194701 ns 1.00
array/sorting/by 928926 ns 928545 ns 1.00
cuda/graph/capture 38199 ns 39420 ns 0.97
cuda/graph/eager 36085 ns 35936 ns 1.00
cuda/graph/launch 13919 ns 13848 ns 1.01
cuda/synchronization/context/auto 2321 ns 7882 ns 0.29
cuda/synchronization/context/blocking 898.3 ns 900.695652173913 ns 1.00
cuda/synchronization/context/nonblocking 8450 ns 7934 ns 1.07
cuda/synchronization/stream/auto 858.6666666666666 ns 827.6833333333333 ns 1.04
cuda/synchronization/stream/blocking 756.2641509433962 ns 766.9134615384615 ns 0.99
cuda/synchronization/stream/nonblocking 7826.333333333333 ns 7800.75 ns 1.00
integration/byval/reference 147781 ns 147547 ns 1.00
integration/byval/slices=1 148894 ns 148428 ns 1.00
integration/byval/slices=2 290159 ns 289979 ns 1.00
integration/byval/slices=3 432385 ns 432003 ns 1.00
integration/cudadevrt 105190 ns 104936 ns 1.00
integration/volumerhs 9611281 ns 9609908 ns 1.00
kernel/indexing 11531 ns 11544 ns 1.00
kernel/indexing_checked 12287 ns 11943 ns 1.03
kernel/launch 2280.5555555555557 ns 2340.1111111111113 ns 0.97
kernel/occupancy 690.8095238095239 ns 688.5234899328859 ns 1.00
kernel/rand 15143 ns 14871 ns 1.02
latency/import 4750753782 ns 4767312023 ns 1.00
latency/precompile 5379427551 ns 5382871355 ns 1.00
latency/ttfp 5216826222 ns 5251068778 ns 0.99

This comment was automatically generated by workflow using github-action-benchmark.

The resource callbacks run while the driver holds its locks, but
disassembling yields (temporary files, running nvdisasm). Any task that
calls into the driver meanwhile, like the timer draining retired
resources, then blocks on those locks and the process deadlocks. Only
copy the cubins in the callback, and disassemble them afterwards.
Since #3315, device_synchronize always handed the synchronization to a
worker thread, as a context can't be polled. That made synchronizing an
idle device take ~7 µs instead of ~1 µs on CI.

With CUDA 12.5, cuCtxRecordEvent records an event that captures all of a
context's work, which can be polled like any other event. Synchronize that
event instead, so that an idle device is detected without the round trip
to a worker. The event blocks when waited for if the context is configured
for blocking synchronization, as cuCtxSynchronize would. Blocking
synchronization, and older drivers, still use cuCtxSynchronize.
@maleadt
maleadt force-pushed the tb/context-sync-event branch from b9e4601 to 282fa89 Compare October 15, 2026 14:15
@codecov

codecov Bot commented Oct 15, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.59259% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 85.08%. Comparing base (ea49380) to head (282fa89).
⚠️ Report is 5 commits behind head on main.

Files with missing lines Patch % Lines
CUDACore/lib/cudadrv/synchronization.jl 85.71% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3396      +/-   ##
==========================================
- Coverage   86.56%   85.08%   -1.49%     
==========================================
  Files         192      191       -1     
  Lines       19497    19236     -261     
==========================================
- Hits        16878    16366     -512     
- Misses       2619     2870     +251     

☔ 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.

@maleadt
maleadt merged commit a746ee6 into main Oct 15, 2026
18 checks passed
@maleadt
maleadt deleted the tb/context-sync-event branch October 15, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance Runtime performance.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant