Skip to content

Commit 9ee3668

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 813b640 commit 9ee3668

File tree

6 files changed

+213
-4
lines changed

6 files changed

+213
-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

+81
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
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"
1012
#include "detray/test/utils/detectors/build_toy_detector.hpp"
13+
#include "detray/test/utils/types.hpp"
1114

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

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
@@ -41,4 +41,11 @@ void detector_test(typename detector_host_t::view_type det_data,
4141
vecmem::data::vector_view<disc_t> discs_data,
4242
vecmem::data::vector_view<cylinder_t> cylinders_data);
4343

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

tutorials/src/device/cuda/detector_construction.cpp

+33-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)
@@ -77,10 +78,9 @@ int main() {
7778
auto sf_buff = detray::get_buffer(det_host.surfaces(), dev_mr, cuda_cpy,
7879
detray::copy::sync,
7980
vecmem::data::buffer_type::fixed_size);
80-
// Use resizable buffer and asynchronous copy for alignment
8181
auto trf_buff = detray::get_buffer(det_host.transform_store(), dev_mr,
82-
cuda_cpy, detray::copy::async,
83-
vecmem::data::buffer_type::resizable);
82+
cuda_cpy, detray::copy::sync,
83+
vecmem::data::buffer_type::fixed_size);
8484
auto msk_buff = detray::get_buffer(det_host.mask_store(), dev_mr, cuda_cpy,
8585
detray::copy::sync,
8686
vecmem::data::buffer_type::fixed_size);
@@ -95,11 +95,40 @@ int main() {
9595
vecmem::data::buffer_type::fixed_size);
9696

9797
// Assemble the detector buffer
98-
auto det_custom_buff = typename decltype(det_host)::buffer_type(
98+
using host_detector_type = decltype(det_host);
99+
auto det_custom_buff = typename host_detector_type::buffer_type(
99100
std::move(vol_buff), std::move(sf_buff), std::move(trf_buff),
100101
std::move(msk_buff), std::move(mat_buff), std::move(acc_buff),
101102
std::move(vgrid_buff));
102103

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

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)