Skip to content

Commit 1816ae7

Browse files
author
Vakho Tsulaia
committed
New function for creating misaligned detector views
Introduced a new function `misaligned_detector_view()` that makes a misaligned detector view by combining "static" buffers of the detector (volumes, surfaces, etc.) with a buffer of potentially misaligned transforms. The new mechanism is tested by a new unit test `detector_align_cuda`. A demonstration of the usage of this mechanism added to the `cuda/detector_construction` tutorial code
1 parent 7816acc commit 1816ae7

File tree

6 files changed

+217
-4
lines changed

6 files changed

+217
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/** Detray library, part of the ACTS project (R&D line)
2+
*
3+
* (c) 2023-2024 CERN for the benefit of the ACTS project
4+
*
5+
* Mozilla Public License Version 2.0
6+
*/
7+
8+
#pragma once
9+
10+
namespace detray::detail {
11+
12+
/// Creates detector view using "static" detector components and
13+
/// a "misaligned" transform store
14+
template <typename host_detector_type>
15+
typename host_detector_type::view_type misaligned_detector_view(
16+
typename host_detector_type::buffer_type& det_buffer,
17+
typename host_detector_type::transform_container::buffer_type& trf_buffer) {
18+
typename host_detector_type::view_type detview{
19+
detray::get_data(
20+
detray::detail::get<0>(det_buffer.m_buffer)), // volumes
21+
detray::get_data(
22+
detray::detail::get<1>(det_buffer.m_buffer)), // surfaces
23+
detray::get_data(trf_buffer), // transforms
24+
detray::get_data(detray::detail::get<3>(det_buffer.m_buffer)), // masks
25+
detray::get_data(
26+
detray::detail::get<4>(det_buffer.m_buffer)), // materials
27+
detray::get_data(
28+
detray::detail::get<5>(det_buffer.m_buffer)), // accelerators
29+
detray::get_data(detray::detail::get<6>(
30+
det_buffer.m_buffer))}; // volume search grid
31+
return detview;
32+
}
33+
34+
} // namespace detray::detail

tests/unit_tests/device/cuda/detector_cuda.cpp

+84
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,11 @@
77

88
// Detray test include(s)
99
#include "detector_cuda_kernel.hpp"
10+
#include "detray/core/detail/alignment.hpp"
11+
#include "detray/definitions/detail/algebra.hpp"
12+
#include "detray/test/common/assert.hpp"
1013
#include "detray/test/utils/detectors/build_toy_detector.hpp"
14+
#include "detray/test/utils/types.hpp"
1115

1216
// Vecmem include(s)
1317
#include <vecmem/memory/cuda/device_memory_resource.hpp>
@@ -96,3 +100,83 @@ TEST(detector_cuda, detector) {
96100
EXPECT_EQ(cylinders_host[i] == cylinders_device[i], true);
97101
}
98102
}
103+
104+
TEST(detector_cuda, detector_alignment) {
105+
// a few typedefs
106+
using test_algebra = test::algebra;
107+
using scalar = dscalar<test_algebra>;
108+
using point3 = dpoint3D<test_algebra>;
109+
110+
// memory resources
111+
vecmem::host_memory_resource host_mr;
112+
vecmem::cuda::device_memory_resource dev_mr;
113+
vecmem::cuda::managed_memory_resource mng_mr;
114+
115+
// helper object for performing memory copies to CUDA devices
116+
vecmem::cuda::copy cuda_cpy;
117+
118+
// create toy geometry in host memory
119+
auto [det_host, names_host] = build_toy_detector<test_algebra>(host_mr);
120+
121+
// copy static detector data (including the initial set of transforms) to
122+
// the device
123+
// use synchronous copy and fixed size buffers
124+
auto det_buff_static = detray::get_buffer(det_host, dev_mr, cuda_cpy);
125+
126+
// ---------- construct an "aligned" transform store ---------
127+
128+
// build a vector of aligned transforms on the host
129+
// for populating this vector take all transforms of the detector
130+
// and shift them by the same translation
131+
typename detector_host_t::transform_container tf_store_aligned_host;
132+
133+
point3 shift{.1f * unit<scalar>::mm, .2f * unit<scalar>::mm,
134+
.3f * unit<scalar>::mm};
135+
136+
tf_store_aligned_host.reserve(
137+
det_host.transform_store().size(),
138+
typename decltype(det_host)::transform_container::context_type{});
139+
140+
for (const auto& tf : det_host.transform_store()) {
141+
point3 shifted = tf.translation() + shift;
142+
tf_store_aligned_host.push_back(
143+
transform_t{shifted, tf.x(), tf.y(), tf.z()});
144+
}
145+
146+
// copy the vector of aligned transforms to the device
147+
// again, use synchronous copy and fixed size buffers
148+
auto tf_buff_aligned =
149+
get_buffer(tf_store_aligned_host, dev_mr, cuda_cpy, copy::sync,
150+
vecmem::data::buffer_type::fixed_size);
151+
152+
// Get the view of the aligned detector using the vector of aligned
153+
// transforms and the static part of the detector copied to the device
154+
// earlier
155+
auto detector_view_aligned =
156+
detail::misaligned_detector_view<detector_host_t>(det_buff_static,
157+
tf_buff_aligned);
158+
// Get the view of the static detector
159+
auto detector_view_static = detray::get_data(det_buff_static);
160+
161+
// make two vectors for surface transforms copied from device side
162+
vecmem::vector<transform_t> surfacexf_device_static(
163+
det_host.surfaces().size(), &mng_mr);
164+
vecmem::vector<transform_t> surfacexf_device_aligned(
165+
det_host.surfaces().size(), &mng_mr);
166+
// views of the above vectors
167+
auto surfacexf_data_static = vecmem::get_data(surfacexf_device_static);
168+
auto surfacexf_data_aligned = vecmem::get_data(surfacexf_device_aligned);
169+
170+
// run the test code to extract the surface transforms for the static
171+
// and misaligned detector views and to store them into the vectors
172+
detector_alignment_test(detector_view_static, detector_view_aligned,
173+
surfacexf_data_static, surfacexf_data_aligned);
174+
175+
// check that the relevant transforms have been properly shifted
176+
for (unsigned int i = 0u; i < surfacexf_device_static.size(); i++) {
177+
auto translation_static = surfacexf_device_static[i].translation();
178+
auto translation_aligned = surfacexf_device_aligned[i].translation();
179+
auto translation_diff = translation_aligned - translation_static;
180+
EXPECT_POINT3_NEAR(translation_diff, shift, 1e-4);
181+
}
182+
}

tests/unit_tests/device/cuda/detector_cuda_kernel.cu

+54
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
#include "detray/definitions/detail/cuda_definitions.hpp"
9+
#include "detray/geometry/tracking_surface.hpp"
910

1011
// Detray test include(s)
1112
#include "detector_cuda_kernel.hpp"
@@ -107,4 +108,57 @@ void detector_test(typename detector_host_t::view_type det_data,
107108
DETRAY_CUDA_ERROR_CHECK(cudaDeviceSynchronize());
108109
}
109110

111+
// cuda kernel to extract surface transforms from two detector views - static
112+
// and misaligned - and to copy them into vectors
113+
__global__ void detector_alignment_test_kernel(
114+
typename detector_host_t::view_type det_data_static,
115+
typename detector_host_t::view_type det_data_aligned,
116+
vecmem::data::vector_view<transform_t> surfacexf_data_static,
117+
vecmem::data::vector_view<transform_t> surfacexf_data_aligned) {
118+
119+
auto ctx = typename detector_host_t::geometry_context{};
120+
121+
// two instances of device detectors
122+
detector_device_t det_device_static(det_data_static);
123+
detector_device_t det_device_aligned(det_data_aligned);
124+
125+
// device vectors of surface transforms
126+
vecmem::device_vector<transform_t> surfacexf_device_static(
127+
surfacexf_data_static);
128+
vecmem::device_vector<transform_t> surfacexf_device_aligned(
129+
surfacexf_data_aligned);
130+
131+
// copy surface transforms into relevant vectors
132+
for (unsigned int i = 0u; i < det_device_static.surfaces().size(); i++) {
133+
const auto sf = tracking_surface{det_device_static,
134+
det_device_static.surfaces()[i]};
135+
surfacexf_device_static[i] = sf.transform(ctx);
136+
}
137+
138+
for (unsigned int i = 0u; i < det_device_aligned.surfaces().size(); i++) {
139+
const auto sf = tracking_surface{det_device_aligned,
140+
det_device_aligned.surfaces()[i]};
141+
surfacexf_device_aligned[i] = sf.transform(ctx);
142+
}
143+
}
144+
145+
/// implementation of the alignment test function for detector
146+
void detector_alignment_test(
147+
typename detector_host_t::view_type det_data_static,
148+
typename detector_host_t::view_type det_data_aligned,
149+
vecmem::data::vector_view<transform_t> surfacexf_data_static,
150+
vecmem::data::vector_view<transform_t> surfacexf_data_aligned) {
151+
constexpr int block_dim = 1u;
152+
constexpr int thread_dim = 1u;
153+
154+
// run the test kernel
155+
detector_alignment_test_kernel<<<block_dim, thread_dim>>>(
156+
det_data_static, det_data_aligned, surfacexf_data_static,
157+
surfacexf_data_aligned);
158+
159+
// cuda error check
160+
DETRAY_CUDA_ERROR_CHECK(cudaGetLastError());
161+
DETRAY_CUDA_ERROR_CHECK(cudaDeviceSynchronize());
162+
}
163+
110164
} // namespace detray

tests/unit_tests/device/cuda/detector_cuda_kernel.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,11 @@ void detector_test(typename detector_host_t::view_type det_data,
4444
vecmem::data::vector_view<disc_t> discs_data,
4545
vecmem::data::vector_view<cylinder_t> cylinders_data);
4646

47+
/// declaration of an alignment test function for detector
48+
void detector_alignment_test(
49+
typename detector_host_t::view_type det_data_static,
50+
typename detector_host_t::view_type det_data_aligned,
51+
vecmem::data::vector_view<transform_t> surfacexf_data_static,
52+
vecmem::data::vector_view<transform_t> surfacexf_data_aligned);
53+
4754
} // namespace detray

tutorials/src/device/cuda/detector_construction.cpp

+34-4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
// Project include(s)
99
#include "detector_construction.hpp"
1010

11+
#include "detray/core/detail/alignment.hpp"
1112
#include "detray/test/utils/detectors/build_toy_detector.hpp"
1213

1314
// Vecmem include(s)
@@ -24,6 +25,7 @@
2425
int main() {
2526

2627
using algebra_t = detray::tutorial::algebra_t;
28+
using scalar = detray::tutorial::scalar;
2729

2830
// memory resource(s)
2931
vecmem::host_memory_resource host_mr;
@@ -81,10 +83,9 @@ int main() {
8183
auto sf_buff = detray::get_buffer(det_host.surfaces(), dev_mr, cuda_cpy,
8284
detray::copy::sync,
8385
vecmem::data::buffer_type::fixed_size);
84-
// Use resizable buffer and asynchronous copy for alignment
8586
auto trf_buff = detray::get_buffer(det_host.transform_store(), dev_mr,
86-
cuda_cpy, detray::copy::async,
87-
vecmem::data::buffer_type::resizable);
87+
cuda_cpy, detray::copy::sync,
88+
vecmem::data::buffer_type::fixed_size);
8889
auto msk_buff = detray::get_buffer(det_host.mask_store(), dev_mr, cuda_cpy,
8990
detray::copy::sync,
9091
vecmem::data::buffer_type::fixed_size);
@@ -99,11 +100,40 @@ int main() {
99100
vecmem::data::buffer_type::fixed_size);
100101

101102
// Assemble the detector buffer
102-
auto det_custom_buff = typename decltype(det_host)::buffer_type(
103+
using host_detector_type = decltype(det_host);
104+
auto det_custom_buff = typename host_detector_type::buffer_type(
103105
std::move(vol_buff), std::move(sf_buff), std::move(trf_buff),
104106
std::move(msk_buff), std::move(mat_buff), std::move(acc_buff),
105107
std::move(vgrid_buff));
106108

107109
std::cout << "\nCustom buffer setup:" << std::endl;
108110
detray::tutorial::print(detray::get_data(det_custom_buff));
111+
112+
// Construct an "aligned" transform store
113+
using host_transform_type =
114+
host_detector_type::transform_container::value_type;
115+
116+
typename host_detector_type::transform_container host_aligned_transforms;
117+
detray::tutorial::point3 shift{.1f * detray::unit<scalar>::mm,
118+
.2f * detray::unit<scalar>::mm,
119+
.3f * detray::unit<scalar>::mm};
120+
121+
for (const auto& tf : det_host.transform_store()) {
122+
detray::tutorial::point3 shifted{tf.translation()[0] + shift[0],
123+
tf.translation()[1] + shift[1],
124+
tf.translation()[2] + shift[2]};
125+
host_aligned_transforms.push_back(
126+
host_transform_type{shifted, tf.x(), tf.y(), tf.z()});
127+
}
128+
129+
auto trf_buff_shifted = detray::get_buffer(
130+
host_aligned_transforms, dev_mr, cuda_cpy, detray::copy::sync,
131+
vecmem::data::buffer_type::fixed_size);
132+
133+
auto detector_view =
134+
detray::detail::misaligned_detector_view<host_detector_type>(
135+
det_custom_buff, trf_buff_shifted);
136+
137+
std::cout << "\nCustom buffer setup (shifted):" << std::endl;
138+
detray::tutorial::print(detector_view);
109139
}

tutorials/src/device/cuda/detector_construction.cu

+4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ __global__ void print_kernel(
2525

2626
printf("Number of volumes: %d\n", det.volumes().size());
2727
printf("Number of transforms: %d\n", det.transform_store().size());
28+
printf("First translation: {%f,%f,%f}\n",
29+
det.transform_store().at(0).translation()[0],
30+
det.transform_store().at(0).translation()[1],
31+
det.transform_store().at(0).translation()[2]);
2832
printf("Number of rectangles: %d\n",
2933
det.mask_store().get<mask_id::e_rectangle2>().size());
3034
printf("Number of trapezoids: %d\n",

0 commit comments

Comments
 (0)