Skip to content

Commit ce25646

Browse files
author
Vakho Tsulaia
committed
New example for demonstrating how to run reconstruction on GPU with time-varying misalignments
1 parent 8c39659 commit ce25646

File tree

2 files changed

+307
-0
lines changed

2 files changed

+307
-0
lines changed

examples/run/cuda/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ traccc_add_executable( truth_fitting_example_cuda "truth_fitting_example_cuda.cp
2626
LINK_LIBRARIES vecmem::core vecmem::cuda traccc::io traccc::performance
2727
traccc::core traccc::device_common traccc::cuda
2828
traccc::options )
29+
traccc_add_executable( misaligned_truth_fitting_example_cuda "misaligned_truth_fitting_example_cuda.cpp"
30+
LINK_LIBRARIES vecmem::core vecmem::cuda traccc::io traccc::performance
31+
traccc::core traccc::device_common traccc::cuda
32+
traccc::options )
2933
#
3034
# Set up the "throughput applications".
3135
#
Lines changed: 303 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,303 @@
1+
/** TRACCC library, part of the ACTS project (R&D line)
2+
*
3+
* (c) 2023-2025 CERN for the benefit of the ACTS project
4+
*
5+
* Mozilla Public License Version 2.0
6+
*/
7+
8+
// Project include(s).
9+
#include "traccc/cuda/fitting/fitting_algorithm.hpp"
10+
#include "traccc/cuda/utils/stream.hpp"
11+
#include "traccc/definitions/common.hpp"
12+
#include "traccc/definitions/primitives.hpp"
13+
#include "traccc/device/container_d2h_copy_alg.hpp"
14+
#include "traccc/device/container_h2d_copy_alg.hpp"
15+
#include "traccc/fitting/kalman_filter/kalman_fitter.hpp"
16+
#include "traccc/fitting/kalman_fitting_algorithm.hpp"
17+
#include "traccc/geometry/detector.hpp"
18+
#include "traccc/io/read_geometry.hpp"
19+
#include "traccc/io/read_measurements.hpp"
20+
#include "traccc/io/utils.hpp"
21+
#include "traccc/options/accelerator.hpp"
22+
#include "traccc/options/detector.hpp"
23+
#include "traccc/options/input_data.hpp"
24+
#include "traccc/options/performance.hpp"
25+
#include "traccc/options/program_options.hpp"
26+
#include "traccc/options/track_fitting.hpp"
27+
#include "traccc/options/track_propagation.hpp"
28+
#include "traccc/performance/collection_comparator.hpp"
29+
#include "traccc/performance/container_comparator.hpp"
30+
#include "traccc/performance/timer.hpp"
31+
#include "traccc/resolution/fitting_performance_writer.hpp"
32+
#include "traccc/utils/bfield.hpp"
33+
#include "traccc/utils/propagation.hpp"
34+
#include "traccc/utils/seed_generator.hpp"
35+
36+
// Detray include(s).
37+
#include <detray/core/detail/alignment.hpp>
38+
#include <detray/io/frontend/detector_reader.hpp>
39+
40+
// VecMem include(s).
41+
#include <vecmem/memory/cuda/device_memory_resource.hpp>
42+
#include <vecmem/memory/cuda/host_memory_resource.hpp>
43+
#include <vecmem/memory/cuda/managed_memory_resource.hpp>
44+
#include <vecmem/memory/host_memory_resource.hpp>
45+
#include <vecmem/utils/cuda/async_copy.hpp>
46+
#include <vecmem/utils/cuda/copy.hpp>
47+
48+
// System include(s).
49+
#include <cstdlib>
50+
#include <exception>
51+
#include <iomanip>
52+
#include <iostream>
53+
54+
using namespace traccc;
55+
56+
// The main routine
57+
//
58+
int main(int argc, char* argv[]) {
59+
std::unique_ptr<const traccc::Logger> ilogger =
60+
traccc::getDefaultLogger("TracccExampleMisalignedTruthFittingCuda",
61+
traccc::Logging::Level::INFO);
62+
TRACCC_LOCAL_LOGGER(std::move(ilogger));
63+
64+
// Program options.
65+
traccc::opts::detector detector_opts;
66+
traccc::opts::input_data input_opts;
67+
traccc::opts::track_propagation propagation_opts;
68+
traccc::opts::track_fitting fitting_opts;
69+
traccc::opts::performance performance_opts;
70+
traccc::opts::accelerator accelerator_opts;
71+
traccc::opts::program_options program_opts{
72+
"Misaligned Truth Track Fitting Using CUDA",
73+
{detector_opts, input_opts, propagation_opts, performance_opts,
74+
accelerator_opts},
75+
argc,
76+
argv,
77+
logger().cloneWithSuffix("Options")};
78+
79+
/// Type declarations
80+
using host_detector_type = traccc::default_detector::host;
81+
using device_detector_type = traccc::default_detector::device;
82+
83+
using scalar_type = device_detector_type::scalar_type;
84+
using b_field_t =
85+
covfie::field<traccc::const_bfield_backend_t<scalar_type>>;
86+
using rk_stepper_type =
87+
detray::rk_stepper<b_field_t::view_t, traccc::default_algebra,
88+
detray::constrained_step<scalar_type>>;
89+
using device_navigator_type = detray::navigator<const device_detector_type>;
90+
using device_fitter_type =
91+
traccc::kalman_fitter<rk_stepper_type, device_navigator_type>;
92+
93+
// Memory resources used by the application.
94+
vecmem::host_memory_resource host_mr;
95+
vecmem::cuda::host_memory_resource cuda_host_mr;
96+
vecmem::cuda::managed_memory_resource mng_mr;
97+
vecmem::cuda::device_memory_resource device_mr;
98+
vecmem::cuda::copy cuda_cpy;
99+
traccc::memory_resource mr{device_mr, &cuda_host_mr};
100+
101+
// Performance writer
102+
traccc::fitting_performance_writer fit_performance_writer(
103+
traccc::fitting_performance_writer::config{},
104+
logger().clone("FittingPerformanceWriter"));
105+
106+
// Output Stats
107+
std::size_t n_fitted_tracks = 0;
108+
std::size_t n_fitted_tracks_cuda = 0;
109+
110+
/*****************************
111+
* Build a geometry
112+
*****************************/
113+
114+
// B field value and its type
115+
// @TODO: Set B field as argument
116+
const traccc::vector3 B{0, 0, 2 * traccc::unit<traccc::scalar>::T};
117+
auto field = traccc::construct_const_bfield<traccc::scalar>(B);
118+
119+
// Read the detector
120+
detray::io::detector_reader_config reader_cfg{};
121+
reader_cfg.add_file(
122+
traccc::io::get_absolute_path(detector_opts.detector_file));
123+
if (!detector_opts.material_file.empty()) {
124+
reader_cfg.add_file(
125+
traccc::io::get_absolute_path(detector_opts.material_file));
126+
}
127+
if (!detector_opts.grid_file.empty()) {
128+
reader_cfg.add_file(
129+
traccc::io::get_absolute_path(detector_opts.grid_file));
130+
}
131+
auto [host_det, names] =
132+
detray::io::read_detector<host_detector_type>(host_mr, reader_cfg);
133+
134+
// Copy detector to the device
135+
auto det_buff_static = detray::get_buffer(host_det, device_mr, cuda_cpy);
136+
137+
// Detector view object
138+
auto det_view_static = detray::get_data(det_buff_static);
139+
140+
/// Create a "misaligned" context
141+
using xf_container = host_detector_type::transform_container;
142+
xf_container tf_store_aligned_host;
143+
tf_store_aligned_host.reserve(
144+
host_det.transform_store().size(),
145+
typename host_detector_type::transform_container::context_type{});
146+
for (const auto& tf : host_det.transform_store()) {
147+
tf_store_aligned_host.push_back(tf);
148+
}
149+
150+
// Copy the vector of "misaligned" transforms to the device
151+
auto tf_buff_aligned = detray::get_buffer(
152+
tf_store_aligned_host, device_mr, cuda_cpy, detray::copy::sync,
153+
vecmem::data::buffer_type::fixed_size);
154+
155+
// Get the view of the "misaligned" detector using the vector of
156+
// "misaligned" transforms and the static part of the detector copied to the
157+
// device earlier
158+
auto det_view_aligned =
159+
detray::detail::misaligned_detector_view<host_detector_type>(
160+
det_buff_static, tf_buff_aligned);
161+
162+
/*****************************
163+
* Do the reconstruction
164+
*****************************/
165+
166+
// Stream object
167+
traccc::cuda::stream stream;
168+
169+
// Copy object
170+
vecmem::copy host_copy;
171+
vecmem::cuda::async_copy async_copy{stream.cudaStream()};
172+
173+
traccc::device::container_d2h_copy_alg<traccc::track_state_container_types>
174+
track_state_d2h{mr, async_copy, logger().clone("TrackStateD2HCopyAlg")};
175+
176+
/// Standard deviations for seed track parameters
177+
static constexpr std::array<scalar, e_bound_size> stddevs = {
178+
0.03f * traccc::unit<scalar>::mm,
179+
0.03f * traccc::unit<scalar>::mm,
180+
0.017f,
181+
0.017f,
182+
0.001f / traccc::unit<scalar>::GeV,
183+
1.f * traccc::unit<scalar>::ns};
184+
185+
// Fitting algorithm object
186+
traccc::fitting_config fit_cfg(fitting_opts);
187+
fit_cfg.propagation = propagation_opts;
188+
189+
traccc::host::kalman_fitting_algorithm host_fitting(
190+
fit_cfg, host_mr, host_copy, logger().clone("HostFittingAlg"));
191+
traccc::cuda::fitting_algorithm<device_fitter_type> device_fitting(
192+
fit_cfg, mr, async_copy, stream, logger().clone("CudaFittingAlg"));
193+
194+
// Seed generator
195+
traccc::seed_generator<host_detector_type> sg(host_det, stddevs);
196+
197+
traccc::performance::timing_info elapsedTimes;
198+
199+
// Iterate over events
200+
for (std::size_t event = input_opts.skip;
201+
event < input_opts.events + input_opts.skip; ++event) {
202+
203+
// Truth Track Candidates
204+
traccc::event_data evt_data(input_opts.directory, event, host_mr,
205+
input_opts.use_acts_geom_source, &host_det,
206+
input_opts.format, false);
207+
208+
traccc::edm::track_candidate_container<traccc::default_algebra>::host
209+
truth_track_candidates{host_mr};
210+
evt_data.generate_truth_candidates(truth_track_candidates, sg, host_mr);
211+
212+
// track candidates buffer
213+
traccc::edm::track_candidate_container<traccc::default_algebra>::buffer
214+
truth_track_candidates_buffer{
215+
async_copy.to(vecmem::get_data(truth_track_candidates.tracks),
216+
mr.main, mr.host,
217+
vecmem::copy::type::host_to_device),
218+
async_copy.to(
219+
vecmem::get_data(truth_track_candidates.measurements),
220+
mr.main, vecmem::copy::type::host_to_device)};
221+
222+
// Instantiate cuda containers/collections
223+
traccc::track_state_container_types::buffer track_states_cuda_buffer{
224+
{{}, *(mr.host)}, {{}, *(mr.host), mr.host}};
225+
226+
// Run fitting
227+
{
228+
traccc::performance::timer t("Track fitting (cuda)", elapsedTimes);
229+
230+
// For the first half of events use the static detector view
231+
// For the second half of events switch to the "misaligned" detector
232+
// view
233+
bool firstHalf =
234+
((event - input_opts.skip) / (input_opts.events / 2) == 0);
235+
track_states_cuda_buffer = device_fitting(
236+
(firstHalf ? det_view_static : det_view_aligned), field,
237+
{truth_track_candidates_buffer.tracks,
238+
truth_track_candidates_buffer.measurements});
239+
}
240+
241+
traccc::track_state_container_types::host track_states_cuda =
242+
track_state_d2h(track_states_cuda_buffer);
243+
244+
// CPU container(s)
245+
traccc::host::kalman_fitting_algorithm::output_type track_states;
246+
247+
if (accelerator_opts.compare_with_cpu) {
248+
249+
{
250+
traccc::performance::timer t("Track fitting (cpu)",
251+
elapsedTimes);
252+
253+
// Run fitting
254+
track_states = host_fitting(
255+
host_det, field,
256+
{vecmem::get_data(truth_track_candidates.tracks),
257+
vecmem::get_data(truth_track_candidates.measurements)});
258+
}
259+
}
260+
261+
if (accelerator_opts.compare_with_cpu) {
262+
// Show which event we are currently presenting the results for.
263+
std::cout << "===>>> Event " << event << " <<<===" << std::endl;
264+
265+
// Compare the track parameters made on the host and on the device.
266+
traccc::collection_comparator<
267+
traccc::fitting_result<traccc::default_algebra>>
268+
compare_fitting_results{"fitted tracks"};
269+
compare_fitting_results(
270+
vecmem::get_data(track_states.get_headers()),
271+
vecmem::get_data(track_states_cuda.get_headers()));
272+
}
273+
274+
// Statistics
275+
n_fitted_tracks += track_states.size();
276+
n_fitted_tracks_cuda += track_states_cuda.size();
277+
278+
if (performance_opts.run) {
279+
for (unsigned int i = 0; i < track_states_cuda.size(); i++) {
280+
const auto& trk_states_per_track =
281+
track_states_cuda.at(i).items;
282+
283+
const auto& fit_res = track_states_cuda[i].header;
284+
285+
fit_performance_writer.write(trk_states_per_track, fit_res,
286+
host_det, evt_data);
287+
}
288+
}
289+
}
290+
291+
if (performance_opts.run) {
292+
fit_performance_writer.finalize();
293+
}
294+
295+
std::cout << "==> Statistics ... " << std::endl;
296+
std::cout << "- created (cuda) " << n_fitted_tracks_cuda << " fitted tracks"
297+
<< std::endl;
298+
std::cout << "- created (cpu) " << n_fitted_tracks << " fitted tracks"
299+
<< std::endl;
300+
std::cout << "==>Elapsed times...\n" << elapsedTimes << std::endl;
301+
302+
return EXIT_SUCCESS;
303+
}

0 commit comments

Comments
 (0)