Implement cuda.bench.State.set_stream(provider) - #443
Conversation
The stream provide type is expected to implement __cuda_stream__ protocol, and not be an instance of cuda.bench.CudaStream. The reason is that cuda.bench.CudaStream type is not user-constructible. It is returns by cuda.bench.State.get_stream method. It stores reference to stream stored in nvbench::state referenced from cuda.bench.State. Disallowing cuda.bench.CudaStream as argument to set_stream avoid footguns.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (3)
📝 WalkthroughSummary by CodeRabbit
WalkthroughThe PR adds the ChangesExternal CUDA stream support
Assessment against linked issues
Comment |
Replace pybind11 keep_alive with an explicit per-state provider cache so repeated State.set_stream calls release previously installed providers instead of retaining every historical stream provider.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Add test for repeated set_stream of the same external owning stream Python object, with expectation that it does not double-free.
Docstring should not require that external stream provider must own stream, only that it keeps it alive. Added notes that both run_all_benchmarks and State.exec evaluate with GIL held. Add note about intended way of using State.set_stream
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
This comment was marked as outdated.
|
@PointKernel This PR fixes the limitation mentioned in NVIDIA/cuvs#2371 (comment) that prompted filing for #440 |
|
Use of Example code# SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
import sys
import cuda.bench as bench
import cupy
@bench.register()
@bench.axis.int64_power_of_two("Elements", [22,24,26])
def elementwise_square(state: bench.State):
# Provide cuda.bench stream to use for launching
state.set_stream(cupy.cuda.get_current_stream())
size = state.get_int64("Elements")
x = cupy.random.randint(low=-16000, high=16000, size=size)
y = cupy.empty_like(x)
state.add_element_count(size)
state.add_global_memory_reads(x.nbytes)
state.add_global_memory_writes(y.nbytes)
def launcher(launch: bench.Launch):
cupy.square(x, out=y)
state.exec(launcher, batched=False)
if __name__ == "__main__":
bench.run_all_benchmarks(sys.argv)compare to example that sets stream provided by # SPDX-FileCopyrightText: Copyright (c) 2026, NVIDIA CORPORATION.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
import sys
import cuda.bench as bench
import cupy
@bench.register()
@bench.axis.int64_power_of_two("Elements", [22,24,26])
def elementwise_square(state: bench.State):
size = state.get_int64("Elements")
x = cupy.random.randint(low=-16000, high=16000, size=size)
y = cupy.empty_like(x)
state.add_element_count(size)
state.add_global_memory_reads(x.nbytes)
state.add_global_memory_writes(y.nbytes)
def launcher(launch: bench.Launch):
with cupy.cuda.Stream.from_external(launch.get_stream()):
cupy.square(x, out=y)
state.exec(launcher, batched=False)
if __name__ == "__main__":
bench.run_all_benchmarks(sys.argv) |
The stream provide type is expected to implement
__cuda_stream__protocol, and not be an instance of typecuda.bench.CudaStream.The reason is that
cuda.bench.CudaStreamtype is not user-constructible. It is returned bycuda.bench.State.get_streammethod. It stores reference to the stream stored innvbench::statereferenced fromcuda.bench.State.Disallowing instances of
cuda.bench.CudaStreamas argument toset_streamavoids footguns.Closes #440