Files
project_6/cccl_upstream/python/cuda_cccl/tests/compute/conftest.py
EngineX CI 56fd68e7dd [INFRA] Import NVIDIA/CCCL upstream as optimization reference library
CCCL (CUDA C++ Core Libraries) provides:
- CUB: device/block/warp-level GPU primitives (reduce, scan, sort, topk)
- Thrust: high-level parallel algorithms (transform_reduce, sort, scan)
- libcudacxx: CUDA C++ standard library (atomics, barriers, memory)
- cudax: experimental features (memory resources, allocators)
- Tuning policies: per-SM hardware-specific algorithm parameters

Competition optimization vectors mapped to CCCL:
- Output TPS (83% weight): warp_reduce, block_reduce, device_topk
- Input TPS (14% weight): device_scan, block_load, prefetch
- Cache TPS (3% weight): prefix caching strategy patterns
- Memory (0.9 util): pooled/cached/buddy allocators

Source: https://github.com/NVIDIA/cccl (shallow clone, HEAD only)
License: Apache-2.0
2026-07-30 09:35:51 +00:00

170 lines
5.9 KiB
Python

import builtins
from collections.abc import Generator
import numpy as np
import pytest
from cuda.core import Device, Stream
try:
from cuda.compute._build_info import USING_V2
except ImportError:
USING_V2 = False
check_ldl_stl_in_sass = False
# Define a pytest fixture that returns random arrays with different dtypes
@pytest.fixture(
params=[
np.int8,
np.int16,
np.int32,
np.int64,
np.uint8,
np.uint16,
np.uint32,
np.uint64,
np.float16,
np.float32,
np.float64,
np.complex64,
np.complex128,
]
)
def input_array(request):
dtype = np.dtype(request.param)
sample_size = 1000
# Generate random values based on the dtype
if np.issubdtype(dtype, np.integer):
is_unsigned = dtype.kind == "u"
# For integer types, use np.random.randint for random integers
if is_unsigned:
low_inclusive, high_exclusive = 0, 8
else:
low_inclusive, high_exclusive = -5, 6
array = np.random.randint(
low=low_inclusive, high=high_exclusive, size=sample_size, dtype=dtype
)
elif np.issubdtype(dtype, np.floating):
# For floating-point types, use np.random.random and cast to the required dtype
array = np.random.random(sample_size).astype(dtype)
elif np.issubdtype(dtype, np.complexfloating):
# For complex types, generate random real and imaginary parts
packed = np.random.random(2 * sample_size)
real_part = packed[:sample_size]
imag_part = packed[sample_size:]
array = (real_part + 1j * imag_part).astype(dtype)
return array
# Define a pytest fixture that returns random floating-point arrays only
@pytest.fixture(
params=[
np.float32,
np.float64,
]
)
def floating_array(request):
dtype = np.dtype(request.param)
sample_size = 1000
# Generate random floating-point values
array = np.random.random(sample_size).astype(dtype)
return array
@pytest.fixture(scope="function")
def cuda_stream() -> Generator[Stream, None, None]:
device = Device()
device.set_current()
stream = device.create_stream()
try:
yield stream
finally:
stream.close()
@pytest.fixture(scope="function", autouse=True)
def verify_sass(request):
if request.node.get_closest_marker("no_verify_sass"):
return
if not check_ldl_stl_in_sass:
return
# Pull monkeypatch dynamically rather than as a fixture parameter so this
# autouse fixture does not add monkeypatch to every test's static fixture
# closure. pytest-run-parallel treats monkeypatch as thread-unsafe based on
# that closure, so a parameter here would serialize the entire free-threaded
# parallel sweep -- even though this fixture only patches on the opt-in
# SASS-check path (check_ldl_stl_in_sass, off by default and in CI).
monkeypatch = request.getfixturevalue("monkeypatch")
import cuda.compute._cccl_interop
monkeypatch.setattr(
cuda.compute._cccl_interop,
"_check_sass",
True,
)
@pytest.fixture
def raise_on_numba_import(monkeypatch):
"""This fixture will raise if a test attempts to import numba"""
real_import = builtins.__import__
def guarded_import(name, *args, **kwargs):
if name == "numba" or name.startswith("numba."):
raise ModuleNotFoundError(
"This test is marked 'no_numba' but attempted to import it"
)
return real_import(name, *args, **kwargs)
monkeypatch.setattr(builtins, "__import__", guarded_import)
def pytest_collection_modifyitems(config, items):
"""Runs after pytest collects the tests. Makes a test marked no_numba fail
if it imports numba, and skips a test marked serialization when running on
the v2 (HostJIT) backend."""
serialization_skip = pytest.mark.skip(
reason="serialization not supported on v2 (HostJIT) backend"
)
# Tests marked no_numba must not import numba. We enforce that by attaching
# the raise_on_numba_import fixture defined above to each one; it raises if
# numba is imported.
#
# We skip attaching it during a real pytest-run-parallel sweep of more than
# one thread: the fixture uses monkeypatch, which pytest-run-parallel
# serializes as thread-unsafe, so attaching it to every no_numba test would
# make the whole sweep run serially and defeat its purpose. A single-threaded
# run has no sweep to protect, so we attach it and keep the check.
#
# config.getoption gives the --parallel-threads value as an int for the
# default but a str when passed on the command line; normalize to str and
# count the run as parallel only for an explicit number > 1:
#
# pytest ... -> 1 single-threaded, attach
# pytest --parallel-threads=1 ... -> "1" single-threaded, attach
# pytest --parallel-threads=8 ... -> "8" parallel, skip (CI sweep)
# pytest --parallel-threads=auto ... -> "auto" single-threaded, attach
#
# "auto" counts as single-threaded on purpose: it can resolve to one CPU, so
# keeping the check is safer than dropping it on a non-parallel run. isdigit
# also stops int() from raising on the non-numeric "auto".
parallel_threads = str(config.getoption("parallel_threads", 1))
running_parallel = parallel_threads.isdigit() and int(parallel_threads) > 1
for item in items:
# no_numba: add raise_on_numba_import unless we skip it for the sweep
if item.get_closest_marker("no_numba") and not running_parallel:
if "raise_on_numba_import" not in item.fixturenames:
item.fixturenames.append("raise_on_numba_import")
# serialization is unsupported on v2 (HostJIT); skip those tests there
if USING_V2 and item.get_closest_marker("serialization"):
item.add_marker(serialization_skip)