You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
cuda.core: introduce copy options for Buffer.copy_{to/from} (#2636)
cuda.core: introduce copy options for Buffer.copy_to/copy_from
Add an optional `options: CopyOptions` keyword argument to
`Buffer.copy_to` and `Buffer.copy_from`, exposing the same dataclass
introduced by `copy_batch` on the per-buffer path. When set, the copy
is submitted via `cuMemcpyWithAttributesAsync` if both cuda.bindings
and the driver are CUDA 13.2+, the stream isn't `LEGACY_DEFAULT_STREAM`,
and it isn't currently capturing; `PER_THREAD_DEFAULT_STREAM` is
accepted like any other stream. `options=None` is unaffected and
always uses the existing `cuMemcpyAsync` path.
Passing `options` together with `LEGACY_DEFAULT_STREAM` or a capturing
stream raises `TypeError`, matching `copy_batch`; a graph cannot
represent these attributes, so `GraphNode.memcpy` (a plain,
non-attributed copy) is the only way to get a copy into a graph today.
On an older cuda.bindings/driver, `src_access_order` values of
`STREAM` and `ANY` fall back to `cuMemcpyAsync` silently, since
stream-ordered access already satisfies both. `DURING_API_CALL`
promises all source reads complete before the call returns; a
stream-ordered fallback can't honor that, so it raises `RuntimeError`
instead of silently downgrading the guarantee, which could otherwise
let a caller overwrite a source buffer before the real read happens.
While aligning the two APIs, this also fixes two bugs in the existing
`copy_batch`: it previously rejected `PER_THREAD_DEFAULT_STREAM`
outright even though the driver accepts it, and its pre-CUDA-13
fallback loop silently ignored `DURING_API_CALL` despite a stale
comment claiming that case was already rejected. Both now match the
per-buffer behavior via a shared `_reject_unsupported_during_api_call`
helper in `_copy_enums.py`.
`cuMemcpyWithAttributesAsync` is absent from cuda.bindings older than
13.2, so it's routed through a small C++ function-pointer shim
(`_cpp/resource_handles.{cpp,hpp}`) resolved at runtime, avoiding a
hard Cython cimport that would break older-bindings builds.
Tests: new `tests/memory/test_copy_single_options.py` covers data
correctness across all `CopyOptions` fields, the `TypeError`/
`RuntimeError` rejection paths, default-stream-token and graph-capture
behavior (including that `options=None` is unaffected by either), and
`dst=None` auto-allocation. `test_copy_batch.py`/
`test_copy_batch_options.py` gain matching coverage for the
`copy_batch` fixes, plus direct unit tests of the shared
`DURING_API_CALL` guard. `test_memory.py` adds previously-missing
size-mismatch rejection tests for `copy_to`/`copy_from`.
Closes#2365.
0 commit comments