Skip to content

[BUG] cuvsDatasetMakePadded rejects an already-aligned device tensor #2482

Description

@imotov

Describe the bug

cuvsDatasetMakePadded fails when handed a device tensor whose rows already sit at CAGRA's required stride. The refusal makes sense since it avoids a redundant copy. However, it is not documented in the API, and the C API exposes no way to predict it.

Steps/Code to reproduce bug

  1. Allocate a contiguous float32 device matrix whose dimension is a multiple of 4 — e.g. 64 rows × 128 dims. (Contiguous means rowStride == columns, which for 4-byte elements is already the 16-byte-aligned width CAGRA requires.)
  2. Wrap it in a DLManagedTensor with device type kDLCUDA.
  3. Call cuvsDatasetMakePadded(res, tensor, CUVS_DATASET_MEM_TYPE_DEVICE, &out).
  4. Repeat with 127 dims instead of 128 — it succeeds. The boundary is dim % 4 == 0 for float32.

Expected behavior

The dataset contents are copied into newly allocated padded storage, as documented at

* The source tensor may reside in host- or device-accessible memory. Its contents are copied into
* newly allocated padded storage in `target_mem_type`.

Actual behavior

CUVS_ERROR, with cuvsGetLastErrorText() returning:

RAFT failure at cpp/include/cuvs/neighbors/common.hpp:1162:
source is device and stride is already correct.
Use make_device_padded_dataset_view() to get a view instead.

Environment details

Not environment specific. Present on main and release/26.08:

if (device_src && src_stride == target_stride) {
RAFT_EXPECTS(false,
"source is device and stride is already correct. "
"Use %s() to get a view instead.",
view_factory_name);
}

Additional context

The Python workaround is probably the clearest signal that the API is missing something:

cdef cuvsError_t status = cuvsDatasetMakePadded(
res,
dataset_dlpack,
CUVS_DATASET_MEM_TYPE_DEVICE,
&padded.dataset
)
if status == cuvsError_t.CUVS_SUCCESS:
return padded
err = get_last_error_text() or ""
if "stride is already correct" not in err:
check_cuvs(status)
check_cuvs(cuvsDatasetMakePaddedView(
res,
dataset_dlpack,
&padded.dataset
))
return padded

It matches on the error text, so any rewording of that message turns the workaround into a crash. Rust, Go, and Java have no equivalent workaround and propagate the failure.

Might be related: #2402 (Dataset API C++, C, and language wrapper follow-up), #2394 (Remove dataset views from language wrappers).

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions