[SGLang] Decoding on a non-default stream still waits for work queued on the default stream
Maintainers usually reply within 3 days
@eromomon is already working on this.
Since Nov 2, 2026.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 8/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Domain
- audio-video-rtc, performance
Research direction
Start by running the attached host_sync_stall_repro.py with --device xpu to reproduce the stall, then compare it with --device cuda. The cause is likely a host-side synchronization point in the XPU decode path that waits on the default stream, so trace how torch.xpu.stream is handled in the decode code. Done means decoding on its own stream stays near the idle time even while default-stream work is queued, matching the CUDA numbers.
Written by the indexing model from the issue text.
Description
Environment
torch 2.14.0+xpu, torchcodec 0.17.0 (+cpu wheel from download.pytorch.org/whl/xpu), torchcodec-xpu 0.17.0 (PyPI), FFmpeg 7.1 (libavcodec 61), Python 3.12, Intel Arc Pro B60 (BMG, 8086:E211, 2 codec engines), xe kernel driver (Linux 6.14), intel-media-driver iHD 25.4.5, libva 2.22, Level Zero loader 1.26.
Summary
While another thread in the same process keeps queuing GPU work on the default stream, XPU decoding slows in proportion to that work even when the decode runs on a stream of its own (with torch.xpu.stream(s):). On CUDA, the same script shows decoding on its own stream unaffected by work on the default stream, so an application can isolate decode there but not on XPU.
Reproduction
Single file, attached: host_sync_stall_repro.py. It generates its own 3 min 720p H.264 test clip (needs the ffmpeg CLI) and decodes 512 sampled frames while a background thread runs an image-processor-like compute op (bilinear resize + normalize of 64 frames of 720p; it does not use the media engine) in batches of 1, 3 or 10 ops, waiting for its stream after each batch. The decode runs on the default stream or on a stream of its own. The two streams share no tensors and the script adds no synchronization between them.
python host_sync_stall_repro.py --device xpu # or --device cuda
Results
XPU
# Arc Pro B60, one card of 8 (ZE_AFFINITY_MASK=4), torchcodec 0.17.0+cpu + torchcodec-xpu 0.17.0, ffmpeg version 7.1.1-1ubuntu1.3
$ python host_sync_stall_repro.py --device xpu
torch 2.14.0+xpu, device Intel(R) Arc(TM) Pro B60 Graphics, 512 frames sampled from 5400, background op 17 ms
idle 5.2 s 1.0x idle
load on its own stream, 1 op per wait 13.9 s 2.7x idle
load on the same stream, 1 op(s) per wait 22.6 s 4.3x idle
load on the same stream, 3 op(s) per wait 50.1 s 9.6x idle
load on the same stream, 10 op(s) per wait 83.1 s 15.8x idle
decode on its own stream, 1 op(s) per wait 13.6 s 2.6x idle
decode on its own stream, 3 op(s) per wait 20.0 s 3.8x idle
decode on its own stream, 10 op(s) per wait 66.4 s 12.7x idle
CUDA, same script
# NVIDIA L40S, driver 580.178.04, torchcodec 0.17.0+cu130 (NVDEC backend), ffmpeg version 7.1.1
$ python host_sync_stall_repro.py --device cuda
torch 2.14.0+cu130, device NVIDIA L40S, 512 frames sampled from 5400, background op 7 ms
idle 2.9 s 1.0x idle
load on its own stream, 1 op per wait 5.3 s 1.8x idle
load on the same stream, 1 op(s) per wait 14.5 s 5.0x idle
load on the same stream, 3 op(s) per wait 41.0 s 14.1x idle
load on the same stream, 10 op(s) per wait 96.8 s 33.3x idle
decode on its own stream, 1 op(s) per wait 5.3 s 1.8x idle
decode on its own stream, 3 op(s) per wait 5.4 s 1.9x idle
decode on its own stream, 10 op(s) per wait 5.4 s 1.9x idle
| Background ops queued on the default stream per wait | B60, decode on default stream | B60, decode on own stream | L40S, decode on default stream | L40S, decode on own stream |
|---|---|---|---|---|
| 1 | 4.3x idle | 2.6x | 5.0x | 1.8x |
| 3 | 9.6x | 3.8x | 14.1x | 1.9x |
| 10 | 15.8x | 12.7x | 33.3x | 1.9x |
On CUDA a decode on its own stream stays at about 1.9x idle (the GPU is busy) however much work waits on the default stream. On XPU it still grows with that work.
Impact
We are moving request-video decode in SGLang serving from the CPU onto the XPU media engine. In a serving process other requests' image processing runs on the default stream, and putting decode on its own stream does not protect it on XPU, so with dense frame sampling individual hardware decodes took 100-300 s and SGLang falls back to CPU decode for such videos.
CC: @eromomon , @dvrogozh
- Dominant language
- C++
- Stars
- 5
- Forks
- 9
- Avg merge
- 3d 10h
- Merged PRs (30d)
- 11
Getting set up
- No Dockerfile or Docker Compose file
- No pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from intel/torchlib-xpu
-
[SGLang] Concurrent VideoDecoders in one process fail with "Failed to import fd=N"Possibly taken @eromomon claimed this 2 days ago. Open
Difficulty 5/5 Over a week Newbie friendliness 22/100
intel/torchlib-xpu#161 · 1 assignee ·
Maintainers usually reply within 3 days
-
Support pytorch 2.15 releasePossibly taken @mkrze claimed this 6 days ago. Open
intel/torchlib-xpu#160 · 1 assignee ·
Maintainers usually reply within 3 days
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
intel/torchlib-xpu#159 ·
Maintainers usually reply within 3 days
-
Difficulty 4/5 3-5 days Newbie friendliness 22/100
intel/torchlib-xpu#155 ·
Maintainers usually reply within 3 days
-
Difficulty 4/5 3-5 days Newbie friendliness 22/100
intel/torchlib-xpu#154 ·
Maintainers usually reply within 3 days
All issues in intel/torchlib-xpu
Similar issues
-
Linux npm packaging leaves workspace files that block subsequent CI checkoutPossibly taken @Spockkk0225 claimed this today. Openci
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
alibaba/neug#1195 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 3 days
-
QA/No release-notes/exclude tests tests/missing-coverage tests/test-quality
Difficulty 2/5 1-3 hours Newbie friendliness 71/100
brave/brave-browser#61019 ·
Maintainers usually reply within 1 day
-
? - Needs Triage bug CUTLASS C++
Difficulty 1/5 Under an hour Newbie friendliness 88/100
Maintainers usually reply within 4 days