feat(cuda.core): add Stream.synchronization_policy via cuStreamSetAttribute - #2637
feat(cuda.core): add Stream.synchronization_policy via cuStreamSetAttribute#2637atiaomar1978-hub wants to merge 19 commits into
Conversation
Expose CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY through LaunchConfig so cuda.core users can set per-launch CPU wait policies without dropping to cuda.bindings.driver. Adds SynchronizationPolicyType and tests for native attribute mapping and real kernel launches. Closes NVIDIA#2628. Co-authored-by: Cursor <cursoragent@cursor.com>
Declare sync_policy_value at function scope so Cython can cast to CUsynchronizationPolicy when building the launch attribute. Co-authored-by: Cursor <cursoragent@cursor.com>
Use cuda.bindings.driver.CUsynchronizationPolicy constants for the public IntEnum and skip GPU launch smoke tests when CUDA 13 bindings run against a CUDA 12 driver. Co-authored-by: Cursor <cursoragent@cursor.com>
GPU validation report (RunPod, contributor-run)Validated this change on real NVIDIA hardware outside upstream CI. Environment
Command pytest cuda_core/tests/test_launcher.py -k "synchronization_policy" -vResults: 10 passed, 4 skipped, 0 failed
The four launch smoke tests were skipped because this host exposes a CUDA 12 driver while the build used CUDA 13 bindings ( Cost: ~ |
Sort imports in test_launcher.py (ruff I001) and regenerate _launch_config.pyi via stubgen-pyx after LaunchConfig changes. Co-authored-by: Cursor <cursoragent@cursor.com>
Expose CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY through LaunchConfig so cuda.core users can set per-launch CPU wait policies without dropping to cuda.bindings.driver. Adds SynchronizationPolicyType and tests for native attribute mapping and real kernel launches. Closes NVIDIA#2628. Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Omar Atie <atiaomar1978@gmail.com>
Declare sync_policy_value at function scope so Cython can cast to CUsynchronizationPolicy when building the launch attribute. Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Omar Atie <atiaomar1978@gmail.com>
Use cuda.bindings.driver.CUsynchronizationPolicy constants for the public IntEnum and skip GPU launch smoke tests when CUDA 13 bindings run against a CUDA 12 driver. Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Omar Atie <atiaomar1978@gmail.com>
Sort imports in test_launcher.py (ruff I001) and regenerate _launch_config.pyi via stubgen-pyx after LaunchConfig changes. Co-authored-by: Cursor <cursoragent@cursor.com> Signed-off-by: Omar Atie <atiaomar1978@gmail.com>
9f4bb0a to
0008aca
Compare
Fix ruff I001 unsorted-imports for pre-commit.ci on PR NVIDIA#2637. Signed-off-by: Omar Atie <atiaomar1978@gmail.com>
Clean up test_launcher.py after merging the pre-force-push commit lineage back into the branch. Signed-off-by: Omar Atie <omaratie@Omars-Mac-mini.local> Co-authored-by: Cursor <cursoragent@cursor.com>
Record that feat/launch-config-sync-policy-2628 includes upstream main at db28018. Future updates will use merge commits, not force-push. Signed-off-by: Omar Atie <atiaomar1978@gmail.com>
Branch update: history preserved, main merged, no force-pushForce-push fixThe earlier force-push (
The PR graph now shows both the original and rewritten commits. Main merge
Going forward
|
Note on commit signingThe two history-restore commits ( Re-signing those commits in place would require rewriting their SHAs and force-pushing the branch — which we're deliberately avoiding to preserve PR history per maintainer guidance. All new commits going forward on this branch will be SSH-signed with |
|
/ok to test 1e48c4e |
CI triage — commit
|
| Time (UTC) | GitHub Status |
|---|---|
| ~14:58 | Actions and API Requests degraded |
| ~16:16 | ~50% error rate on archive downloads; elevated API errors |
| 17:30–17:36 | Git Operations and Issues degraded (CI running here) |
| ~18:48 | API Requests degraded again |
| ~20:08+ | Incident still open; sporadic failures under investigation |
The HTTP 503 failures on artifact download align with GitHub's reported Actions, API, and archive download degradation — not compile or test regressions from this PR.
What passed
- API check (cuda_core vs. merge base) — pass
- API check (cuda_core vs. latest release) — pass
- Majority of build matrix cells (linux-64, linux-aarch64, win-64) — pass
- Contributor GPU validation (RunPod):
pytest tests/test_launcher.py -k synchronization_policy— 10 passed, 4 skipped (launch smoke tests skipped due to CUDA 12 driver vs CUDA 13 bindings on that host)
Request
Could you re-run the failed jobs once GitHub's Actions/artifact API is fully stable? I don't believe a code change on this branch is needed for these failures.
Happy to re-run locally or on RunPod again if helpful.
Sync PR NVIDIA#2637 with latest main (preserve branch history, no force-push).
Branch update: latest
|
| Item | Detail |
|---|---|
| Merge commit | 14ff25e900 |
| Previous HEAD | 1e48c4e |
| New upstream tip | 0b5d816560 |
| Push | origin/feat/launch-config-sync-policy-2628 (personal fork) |
Incoming changes from main
fix(cuda.core): emit -numba-debug with a single dash for NVVM(fix(cuda.core): emit -numba-debug with a single dash for NVVM #2639)Guard unsupported NVML clock-domain queries(Guard unsupported NVML clock-domain queries in tests #2651)- Remove unstable
test_pynvmlenergy-consumption test (Remove timing-sensitive NVML total-energy test #2644) - PR metadata check token scope update ([no-ci] ci: restrict PR metadata check token to pull-request read access #2081)
Merge was clean — no conflicts with the LaunchConfig.synchronization_policy changes.
CI should re-trigger on the updated branch. Let me know if you'd like another /ok to test or a re-run of the previously failed infra jobs.
|
/ok to test 14ff25e |
|
I think I should be maintainer to trigger CI build. @lijinf2 |
|
Quick follow-up: I merged latest Could you please re-run: when you have a moment? Happy to help triage any remaining infra failures from the previous run. |
|
/ok to test 14ff25e |
|
Use CUsynchronizationPolicy when setting syncPolicy in the Python _to_native_launch_config helper, and add SynchronizationPolicyType to api_private.rst for docs consistency checks. Co-authored-by: Cursor <cursoragent@cursor.com>
CI fix pushed (
|
CI fix pushed (
|
| Failure | Root cause | Fix |
|---|---|---|
10× test_launcher.py sync-policy tests |
_to_native_launch_config() assigned a bare int to attr.value.syncPolicy; cuda-bindings expects CUsynchronizationPolicy |
Wrap with driver.CUsynchronizationPolicy(...) |
1× test_api_docs_consistency.py[typing] |
SynchronizationPolicyType missing from docs |
Added to api_private.rst |
RunPod validation (contributor-run, RTX A4000)
pytest cuda_core/tests/test_launcher.py -k synchronization_policy -v
→ 10 passed, 4 skipped (CUDA 13 bindings vs CUDA 12 driver), 0 failed
pytest cuda_core/tests/test_api_docs_consistency.py -k typing -v
→ 2 passed
@lijinf2 Could you trigger CI again with /ok to test 21c56b041a when you have a moment? Thanks!
|
/ok to test 21c56b0 |
|
@lijinf2 I'm checking |
) CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY is not accepted by cuLaunchKernelEx, so the per-launch API requested in NVIDIA#2628 cannot be implemented. Every GPU test job rejected the launch with CUDA_ERROR_INVALID_VALUE on CUDA 12.9, 13.0 and 13.3 across linux-64, linux-aarch64 and win-64. CUDA documents this attribute as "Valid for streams", unlike CU_LAUNCH_ATTRIBUTE_COOPERATIVE which is "Valid for graph nodes, launches". A driver-level probe on an RTX A4000 (driver 550.144.03, cuda-bindings 12.9.7) confirms the distinction is real: the same no-op kernel launches successfully with no attributes and with COOPERATIVE, but returns CUDA_ERROR_INVALID_VALUE for all four synchronization policies, while cuStreamSetAttribute accepts the same values. Revert the feature so this branch matches main, and defer to maintainers on whether NVIDIA#2628 should be re-scoped to a stream-level API. Co-authored-by: Cursor <cursoragent@cursor.com>
This attribute is not valid for
|
| Attribute | Documented validity |
|---|---|
CU_LAUNCH_ATTRIBUTE_COOPERATIVE |
Valid for graph nodes, launches |
CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY |
Valid for streams |
CUlaunchAttributeValue.syncPolicy is likewise described as "CUsynchronizationPolicy for work queued up in this stream", and the driver docs list this attribute under cuStreamSetAttribute, not cuLaunchKernelEx.
Hardware verification
I ran a driver-level probe on an RTX A4000 (driver 550.144.03 / CUDA 12.4, cuda-bindings pinned to 12.9.7 so the CUDA-13-bindings skip could not fire). It uses cuda.bindings.driver directly, so no cuda.core code is involved — the same no-op kernel and same CUlaunchConfig in every case, varying only attrs:
A. no attributes (baseline) -> CUDA_SUCCESS
B. CU_LAUNCH_ATTRIBUTE_COOPERATIVE (documented) -> CUDA_SUCCESS
C. SYNCHRONIZATION_POLICY=CU_SYNC_POLICY_AUTO -> CUDA_ERROR_INVALID_VALUE
C. SYNCHRONIZATION_POLICY=CU_SYNC_POLICY_SPIN -> CUDA_ERROR_INVALID_VALUE
C. SYNCHRONIZATION_POLICY=CU_SYNC_POLICY_YIELD -> CUDA_ERROR_INVALID_VALUE
C. SYNCHRONIZATION_POLICY=CU_SYNC_POLICY_BLOCKING_SYNC -> CUDA_ERROR_INVALID_VALUE
D. cuStreamSetAttribute SYNC_POLICY=CU_SYNC_POLICY_SPIN -> CUDA_SUCCESS
D. cuStreamSetAttribute SYNC_POLICY=CU_SYNC_POLICY_BLOCKING_SYNC -> CUDA_SUCCESS
Baseline and COOPERATIVE both succeed on that exact kernel, so the launch path is fine; the driver rejects this specific attribute ID. cuStreamSetAttribute accepts the identical policy values. Combined with CI, this reproduces on driver 550 (CUDA 12.4) through CUDA 13.3, so it is not a driver-version regression.
Note on #2628
The C snippet in #2628 is annotated "agent-generated; reviewed but not executed", and I believe it is the source of the confusion — it passes syncPolicy through CUlaunchConfig.attrs, which the driver rejects. The issue's own "alternatives considered" item 2, cuStreamSetAttribute(..., CU_STREAM_ATTRIBUTE_SYNCHRONIZATION_POLICY, ...), is in fact the only working path. (In CUDA 11.8+ the enums are unified, so it is spelled CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY even when used as a stream attribute ID.)
So the two acceptance criteria in #2628 are not simultaneously satisfiable: mapping to the native launch attribute can be unit-tested, but any user who sets it gets CUDA_ERROR_INVALID_VALUE at launch. Shipping it would add a LaunchConfig option that always fails.
What I changed
71763c5fc6 reverts the feature. This branch is now byte-identical to main (0b5d816560) across all tracked files, so CI should be fully green. History is preserved — no force-push.
Over to you
I did not want to unilaterally redesign a maintainer-specified API, so I have not implemented a replacement. How would you like to proceed?
- Re-scope [FEA]: Support CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY in LaunchConfig #2628 to a stream-level API (e.g. a
Stream.synchronization_policyproperty backed bycuStreamSetAttribute/cuStreamGetAttribute) — I'm happy to implement that here or in a fresh PR. - Close [FEA]: Support CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY in LaunchConfig #2628 as not implementable as specified, and drop it from the RFC: Add support for
launch_attrinLaunchConfigctor #496 tracking list. - Close this PR if you'd rather handle the correction yourself.
Either way it's probably worth auditing the rest of #496 — any other CUlaunchAttributeID marked "Valid for streams" will hit the same wall. Happy to send that audit as a separate issue if useful.
One more /ok to test when you get a chance would confirm the branch is green.
…ribute Re-scope NVIDIA#2628 from the invalid per-launch attribute to the documented stream attribute path. CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY is rejected by cuLaunchKernelEx but accepted by cuStreamSetAttribute on real hardware (RunPod RTX A4000, driver 550 / CUDA 12.4). Expose SynchronizationPolicyType, Stream.synchronization_policy get/set, and an optional StreamOptions.synchronization_policy for creation-time configuration. Add GPU tests covering set/get, defaults, options, and launch+sync for all four policies. Co-authored-by: Cursor <cursoragent@cursor.com>
I do not read long reply. Could you summarize? |
…_init Cython rejects cdef declarations inside conditional blocks. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@lijinf2 Sorry for the long comment — here's the short version. TL;DR: What I did:
Ask: OK to update #2628 and this PR title to the stream-level API? Happy to open a fresh PR instead if you prefer. Please |
cuStreamGetAttribute can return -1 when synchronization_policy was never explicitly set on a new stream. Map that sentinel to CU_SYNC_POLICY_AUTO so the documented default is returned instead of raising ValueError. Co-authored-by: Cursor <cursoragent@cursor.com>
….pyi Fix pre-commit.ci failures on ruff-format and stubgen-pyx-cuda-core. Co-authored-by: Cursor <cursoragent@cursor.com>
|
RunPod validation (L40S, CUDA 13.3 mini-CTK, CI-matched setup):
pre-commit.ci is green after ruff format + Please |
|
@lijinf2 could you please trigger the CI build ? |
|
/ok to test a4fc6c1 |
|
@lijinf2 Thanks for the support and guidance on this PR — really appreciated. CI is all green now. Still on a learning curve with the cuda-python workflow, but getting there. Could you please review when you have a moment? |
|
The issue asked for (1), but this PR implements (2). (2) is already supported in To avoid introducing redundant APIs, I’m closing this PR. Feel free to push back if you disagree. (1) is still open; the intended direction is something like: |
|
@lijinf2 Short follow-up: (1) LaunchConfig — we tried this first. (2) Stream attribute — already on
There is no What's needed: guidance on #2628 — pursue (1) only if NVIDIA confirms a working launch path/driver fix; otherwise close or document that users should use bindings for (2), which already ships. |
Summary
LaunchConfig.synchronization_policyto exposeCU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICYfromcuda.core, closing [FEA]: Support CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICY in LaunchConfig #2628.SynchronizationPolicyTypeincuda.core.typing(AUTO,SPIN,YIELD,BLOCKING_SYNC) aligned withcuda.bindings.driver.CUsynchronizationPolicy.LaunchConfig._to_native_launch_config()and the standalone_to_native_launch_config()helper used in tests.tests/test_launcher.py, plus a GPU launch smoke test (skipped when CUDA 13 bindings run against a CUDA 12 driver).Motivation
Pool-backed and other
LaunchConfiglaunch attributes already route throughcuLaunchKernelEx. Users should be able to set per-launch CPU wait policy without dropping to rawcuda.bindings.driverAPIs. This follows the incrementalLaunchConfigattribute coverage tracked under #496 (same approach asprogrammatic_stream_serialization).Example
Test plan
pytest cuda_core/tests/test_launcher.py -k synchronization_policy -v$0.16/hr)RunPod GPU report (contributor-run)
feat/launch-config-sync-policy-2628cuda_core, CUDA 13 headers/bindingspytest tests/test_launcher.py -k synchronization_policy -vMapping tests verify
CU_LAUNCH_ATTRIBUTE_SYNCHRONIZATION_POLICYfor all four policies, invalid-input rejection, defaultNone, and combination withis_cooperative. The four GPU launch smoke tests were skipped on this host because the RunPod image exposes a CUDA 12 driver while the build used CUDA 13 bindings (cubin load is incompatible); upstream CI with matched driver/toolkit should cover the launch path.Closes #2628.
Made with Cursor