mirror of
https://github.com/slsdetectorgroup/aare.git
synced 2026-10-31 15:41:29 +01:00
CUDA: C++17 cleanup of ClusterFinderCUDA
- std::array for per-slot state; std::exchange in BatchView::steal - [[nodiscard]]/noexcept on the public API and release path - cuda_check moved to aare::cuda::detail (was reserved __cuda_check) - _v type traits; drop redundant std::move and `using namespace aare` - Add pytest for BatchView slot release
This commit is contained in:
1 parent
4d23b2b29c
commit
47d89446e2
6 files changed
+128
-48
No files matched your search
@@ -14,8 +14,6 @@
|
||||
namespace py = pybind11;
|
||||
using pd_type = double;
|
||||
|
||||
using namespace aare;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
@@ -170,7 +168,7 @@ sqrt(max(sum2/n - mean^2, 0)). Counterpart to `noise` for the device pedestal.)"
|
||||
.def(
|
||||
"steal_clusters",
|
||||
[](CF &self, bool realloc_same_capacity) {
|
||||
return std::move(self.steal_clusters(realloc_same_capacity));
|
||||
return self.steal_clusters(realloc_same_capacity);
|
||||
},
|
||||
py::arg("realloc_same_capacity") = true)
|
||||
|
||||
|
||||
@@ -13,8 +13,6 @@
|
||||
namespace py = pybind11;
|
||||
using pd_type = double;
|
||||
|
||||
using namespace aare;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
|
||||
@@ -65,7 +63,7 @@ void define_ClusterFinderCUDAGraph(py::module &m, const std::string &typestr) {
|
||||
.def(
|
||||
"steal_clusters",
|
||||
[](CF &self, bool realloc_same_capacity) {
|
||||
return std::move(self.steal_clusters(realloc_same_capacity));
|
||||
return self.steal_clusters(realloc_same_capacity);
|
||||
},
|
||||
py::arg("realloc_same_capacity") = true)
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from aare import ClusterFinderCUDA, _cuda_available, find_cluster_views_batched_iter
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
not _cuda_available(), reason="aare built without AARE_CUDA")
|
||||
|
||||
SHAPE = (32, 32)
|
||||
BATCH = 4
|
||||
# Pixel that gets a photon in every data frame, away from the border.
|
||||
HIT = (16, 16)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def cf():
|
||||
cf = ClusterFinderCUDA(SHAPE, n_streams=2, min_pedestal_samples=10)
|
||||
rng = np.random.default_rng(42)
|
||||
for _ in range(20):
|
||||
cf.push_pedestal_frame(
|
||||
rng.normal(1000, 5, SHAPE).astype(np.uint16))
|
||||
return cf
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def frames():
|
||||
rng = np.random.default_rng(7)
|
||||
f = rng.normal(1000, 5, (BATCH, *SHAPE)).astype(np.uint16)
|
||||
f[:, HIT[0], HIT[1]] = 3000
|
||||
return f
|
||||
|
||||
|
||||
def test_collect_view_exposes_batch(cf, frames):
|
||||
tok = cf.submit_batch(frames, first_frame=100)
|
||||
with cf.collect_view(tok) as v:
|
||||
assert v.valid
|
||||
assert v.n_frames == BATCH
|
||||
assert v.first_frame == 100
|
||||
assert all(v.count(i) >= 1 for i in range(BATCH))
|
||||
assert not v.valid
|
||||
|
||||
|
||||
def test_released_view_frees_its_slot(cf, frames):
|
||||
# Cycles both slots twice. pybind11 move-constructs every returned
|
||||
# BatchView, so a move that drops the slot index leaves the slot held
|
||||
# forever and the third submit_batch() throws.
|
||||
for i in range(2 * 2):
|
||||
tok = cf.submit_batch(frames, first_frame=i * BATCH)
|
||||
v = cf.collect_view(tok)
|
||||
v.release()
|
||||
assert not v.valid
|
||||
|
||||
|
||||
def test_dropped_view_frees_its_slot(cf, frames):
|
||||
# The destructor releases, so a view that is never bound is harmless.
|
||||
for i in range(2 * 2):
|
||||
tok = cf.submit_batch(frames, first_frame=i * BATCH)
|
||||
cf.collect_view(tok)
|
||||
|
||||
|
||||
def test_held_view_blocks_its_slot(cf, frames):
|
||||
held = cf.collect_view(cf.submit_batch(frames))
|
||||
# The other slot is still free.
|
||||
with cf.collect_view(cf.submit_batch(frames)):
|
||||
pass
|
||||
with pytest.raises(RuntimeError, match="held by a BatchView"):
|
||||
cf.submit_batch(frames)
|
||||
held.release()
|
||||
with cf.collect_view(cf.submit_batch(frames)):
|
||||
pass
|
||||
|
||||
|
||||
def test_views_batched_iter_pipelines_all_chunks(cf, frames):
|
||||
data = np.concatenate([frames] * 3)
|
||||
seen = []
|
||||
for v in find_cluster_views_batched_iter(cf, data, first_frame=10,
|
||||
chunk=BATCH):
|
||||
seen.append((v.first_frame, v.n_frames))
|
||||
assert seen == [(10, BATCH), (10 + BATCH, BATCH), (10 + 2 * BATCH, BATCH)]
|
||||
Reference in new issue
Block a user