Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:24

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // Detray include(s)
0010 #include "container_cuda_kernel.hpp"
0011 
0012 // Vecmem include(s)
0013 #include <vecmem/memory/cuda/device_memory_resource.hpp>
0014 #include <vecmem/memory/cuda/managed_memory_resource.hpp>
0015 #include <vecmem/memory/host_memory_resource.hpp>
0016 #include <vecmem/utils/cuda/copy.hpp>
0017 
0018 // GTest include(s)
0019 #include <gtest/gtest.h>
0020 
0021 // System include(s)
0022 #include <algorithm>
0023 #include <iterator>
0024 #include <numeric>
0025 
0026 using namespace detray;
0027 
0028 constexpr double tol{1e-6};
0029 
0030 /// Test the access to the single store by summing the contained values
0031 TEST(container_cuda, single_store) {
0032   // Vecmem memory resources
0033   vecmem::host_memory_resource host_mr;
0034   vecmem::cuda::managed_memory_resource mng_mr;
0035   vecmem::cuda::device_memory_resource dev_mr;
0036   vecmem::cuda::copy cpy;
0037 
0038   // Create single store(s)
0039   single_store_t store(host_mr);
0040   single_store_t mng_store(mng_mr);
0041 
0042   // Base store function check
0043   EXPECT_TRUE(store.empty());
0044   EXPECT_EQ(store.size(), 0u);
0045   EXPECT_TRUE(mng_store.empty());
0046   EXPECT_EQ(mng_store.size(), 0u);
0047 
0048   // Test the managed memory allocation
0049   geometry_context ctx{};
0050   mng_store.reserve(4, ctx);
0051   mng_store.emplace_back(ctx, 1.);
0052   mng_store.push_back(2., ctx);
0053   mng_store.insert(vecmem::vector<double>{10.5, 7.6}, ctx);
0054   store.append(mng_store, ctx);
0055 
0056   EXPECT_FALSE(store.empty());
0057   EXPECT_EQ(store.size(), 4u);
0058   EXPECT_FALSE(mng_store.empty());
0059   EXPECT_EQ(mng_store.size(), 4u);
0060 
0061   // Check the host-side access to the data
0062   EXPECT_NEAR(mng_store.at(0, ctx), 1., tol);
0063   EXPECT_NEAR(mng_store.at(2, ctx), 10.5, tol);
0064   EXPECT_NEAR(mng_store.at(1, ctx), 2., tol);
0065   EXPECT_NEAR(mng_store.at(3, ctx), 7.6, tol);
0066 
0067   // CPU sum check
0068   double cpu_sum{std::accumulate(mng_store.begin(), mng_store.end(), 0.)};
0069   EXPECT_NEAR(cpu_sum, 21.1, tol);
0070   EXPECT_NEAR(cpu_sum, std::accumulate(store.begin(), store.end(), 0.), tol);
0071 
0072   // Get the view to the managed memory and run the test
0073   single_store_t::view_type mng_store_view = detray::get_data(mng_store);
0074 
0075   vecmem::vector<double> cuda_sum(&mng_mr);
0076   cuda_sum.push_back(0.);
0077   vecmem::data::vector_view<double> sum_data = vecmem::get_data(cuda_sum);
0078 
0079   test_single_store(mng_store_view, sum_data);
0080 
0081   EXPECT_NEAR(cpu_sum, cuda_sum[0], tol);
0082 
0083   // Check that the store can be cleared
0084   mng_store.clear(ctx);
0085 
0086   EXPECT_TRUE(mng_store.empty());
0087   EXPECT_EQ(mng_store.size(), 0u);
0088 
0089   // Reset for next test
0090   cuda_sum[0] = 0.;
0091 
0092   // Copy the host store to device, get the view to it and run the test again
0093   single_store_t::buffer_type store_buffer =
0094       detray::get_buffer(store, dev_mr, cpy);
0095   single_store_t::view_type buffer_view = detray::get_data(store_buffer);
0096 
0097   EXPECT_NEAR(cuda_sum[0], 0.f, tol);
0098 
0099   test_single_store(buffer_view, sum_data);
0100 
0101   EXPECT_NEAR(cuda_sum[0], cpu_sum, tol);
0102 }
0103 
0104 /// Test the access to the tuple container by summing the contained values
0105 TEST(container_cuda, tuple_container) {
0106   // Vecmem memory resources
0107   vecmem::host_memory_resource host_mr;
0108   vecmem::cuda::managed_memory_resource mng_mr;
0109   vecmem::cuda::device_memory_resource dev_mr;
0110   vecmem::cuda::copy cpy;
0111 
0112   // Create single store(s)
0113   tuple_cont_t tcont(host_mr);
0114   tuple_cont_t mng_tcont(mng_mr);
0115 
0116   // Base store function check
0117   EXPECT_EQ(tcont.size(), 2u);
0118   EXPECT_EQ(mng_tcont.size(), 2u);
0119 
0120   // Test the managed memory allocation
0121   mng_tcont.get<0>().push_back(3);
0122   mng_tcont.get<1>().push_back(4.);
0123   mng_tcont.get<1>().push_back(5.8);
0124 
0125   vecmem::vector<double> new_data{10.5, 7.6, 14.5};
0126   auto& data_coll = detail::get<1>(mng_tcont);
0127   std::ranges::copy(new_data, std::back_inserter(data_coll));
0128   std::ranges::copy(mng_tcont.get<0>(), std::back_inserter(tcont.get<0>()));
0129   std::ranges::copy(mng_tcont.get<1>(), std::back_inserter(tcont.get<1>()));
0130 
0131   EXPECT_EQ(mng_tcont.get<0>().size(), 1u);
0132   EXPECT_EQ(mng_tcont.get<1>().size(), 5u);
0133   EXPECT_EQ(tcont.get<0>().size(), 1u);
0134   EXPECT_EQ(tcont.get<1>().size(), 5u);
0135 
0136   // CPU sum check
0137   double cpu_sum{static_cast<double>(mng_tcont.get<0>().at(0))};
0138   cpu_sum = std::accumulate(data_coll.begin(), data_coll.end(), cpu_sum);
0139   EXPECT_NEAR(cpu_sum, 45.4, tol);
0140 
0141   // Get the view to the managed memory and run the test
0142   tuple_cont_t::view_type mng_store_view = detray::get_data(mng_tcont);
0143 
0144   vecmem::vector<double> cuda_sum(&mng_mr);
0145   cuda_sum.push_back(0.);
0146   vecmem::data::vector_view<double> sum_data = vecmem::get_data(cuda_sum);
0147 
0148   test_tuple_container(mng_store_view, sum_data);
0149 
0150   EXPECT_NEAR(cpu_sum, cuda_sum[0], tol);
0151 
0152   // Reset for next test
0153   cuda_sum[0] = 0.;
0154 
0155   // Copy the host store to device, get the view to it and run the test again
0156   tuple_cont_t::buffer_type store_buffer =
0157       detray::get_buffer(tcont, dev_mr, cpy);
0158   tuple_cont_t::view_type buffer_view = detray::get_data(store_buffer);
0159 
0160   EXPECT_NEAR(cuda_sum[0], 0.f, tol);
0161 
0162   test_tuple_container(buffer_view, sum_data);
0163 
0164   EXPECT_NEAR(cuda_sum[0], cpu_sum, tol);
0165 }
0166 
0167 /// Test the regular multi store functionality
0168 TEST(container_cuda, regular_multi_store) {
0169   using enum reg_type_ids;
0170 
0171   // Vecmem memory resources
0172   vecmem::host_memory_resource host_mr;
0173   vecmem::cuda::managed_memory_resource mng_mr;
0174   vecmem::cuda::device_memory_resource dev_mr;
0175   vecmem::cuda::copy cpy;
0176 
0177   // Create tuple vector store
0178   reg_multi_store_t mng_store(mng_mr);
0179   reg_multi_store_t store(host_mr);
0180 
0181   // Base store function check
0182   EXPECT_EQ(mng_store.n_collections(), 3u);
0183   EXPECT_EQ(mng_store.empty<e_size>(), true);
0184   EXPECT_EQ(mng_store.empty<e_float>(), true);
0185   EXPECT_EQ(mng_store.empty<e_double>(), true);
0186 
0187   // Add elements to the store
0188   empty_context ctx{};
0189   mng_store.emplace_back<e_size>(ctx, 1u);
0190   mng_store.push_back<e_size>(2u, ctx);
0191   mng_store.emplace_back<e_float>(ctx, 3.1f);
0192   mng_store.push_back<e_float>(4.5f, ctx);
0193   mng_store.emplace_back<e_double>(ctx, 5.5);
0194   mng_store.push_back<e_double>(6.0, ctx);
0195 
0196   vecmem::vector<std::size_t> int_vec{3u, 4u, 5u};
0197   mng_store.insert(int_vec);
0198 
0199   vecmem::vector<float> float_vec{12.1f, 5.6f};
0200   mng_store.insert(float_vec);
0201 
0202   mng_store.insert(vecmem::vector<double>{10.5, 7.6});
0203 
0204   store.append(mng_store, ctx);
0205 
0206   EXPECT_EQ(mng_store.size<e_size>(), 5u);
0207   EXPECT_EQ(mng_store.size<e_float>(), 4u);
0208   EXPECT_EQ(mng_store.size<e_double>(), 4u);
0209   EXPECT_EQ(store.size<e_size>(), 5u);
0210   EXPECT_EQ(store.size<e_float>(), 4u);
0211   EXPECT_EQ(store.size<e_double>(), 4u);
0212 
0213   // CPU sum check
0214   double cpu_sum{std::accumulate(mng_store.get<e_size>().begin(),
0215                                  mng_store.get<e_size>().end(), 0.)};
0216   cpu_sum = std::accumulate(mng_store.get<e_float>().begin(),
0217                             mng_store.get<e_float>().end(), cpu_sum);
0218   cpu_sum = std::accumulate(mng_store.get<e_double>().begin(),
0219                             mng_store.get<e_double>().end(), cpu_sum);
0220   EXPECT_NEAR(cpu_sum, 69.9, tol);
0221 
0222   // CUDA sum check
0223   typename reg_multi_store_t::view_type store_view = get_data(mng_store);
0224 
0225   vecmem::vector<double> cuda_sum(&mng_mr);
0226   cuda_sum.push_back(0.);
0227   auto sum_data = vecmem::get_data(cuda_sum);
0228 
0229   test_reg_multi_store(store_view, sum_data);
0230 
0231   EXPECT_NEAR(cpu_sum, cuda_sum[0], tol);
0232 
0233   // Reset for next test
0234   cuda_sum[0] = 0.;
0235 
0236   // Copy the host store to device, get the view to it and run the test again
0237   reg_multi_store_t::buffer_type store_buffer =
0238       detray::get_buffer(store, dev_mr, cpy);
0239   reg_multi_store_t::view_type buffer_view = detray::get_data(store_buffer);
0240 
0241   EXPECT_NEAR(cuda_sum[0], 0.f, tol);
0242 
0243   test_reg_multi_store(buffer_view, sum_data);
0244 
0245   EXPECT_NEAR(cuda_sum[0], cpu_sum, tol);
0246 }
0247 
0248 /// Tets the multi store with a hierarchical memory type ( @c test<> )
0249 TEST(container_cuda, multi_store) {
0250   using enum type_ids;
0251 
0252   // Vecmem memory resources
0253   vecmem::host_memory_resource host_mr;
0254   vecmem::cuda::managed_memory_resource mng_mr;
0255   vecmem::cuda::device_memory_resource dev_mr;
0256   vecmem::cuda::copy cpy;
0257 
0258   // Create tuple vector store
0259   multi_store_t mng_store(mng_mr);
0260   multi_store_t store(host_mr);
0261 
0262   // Base store function check
0263   EXPECT_EQ(mng_store.n_collections(), 2u);
0264   EXPECT_EQ(mng_store.empty<e_float>(), true);
0265 
0266   // Add elements to the store
0267   vecmem::vector<float> float_vec{12.1f, 5.6f};
0268   mng_store.insert(float_vec);
0269 
0270   mng_store.get<e_test_class>().first = vecmem::vector<int>{2, 3};
0271   mng_store.get<e_test_class>().second = vecmem::vector<double>{18., 42.6};
0272 
0273   std::ranges::copy(mng_store.get<e_float>(),
0274                     std::back_inserter(store.get<e_float>()));
0275   store.get<e_test_class>() = mng_store.get<e_test_class>();
0276 
0277   EXPECT_EQ(mng_store.size<e_float>(), 2u);
0278   EXPECT_EQ(mng_store.get<e_test_class>().first.size(), 2u);
0279   EXPECT_EQ(mng_store.get<e_test_class>().second.size(), 2u);
0280   EXPECT_EQ(store.size<e_float>(), 2u);
0281   EXPECT_EQ(store.get<e_test_class>().first.size(), 2u);
0282   EXPECT_EQ(store.get<e_test_class>().second.size(), 2u);
0283 
0284   // CPU sum check
0285   double cpu_sum{std::accumulate(mng_store.get<e_float>().begin(),
0286                                  mng_store.get<e_float>().end(), 0.)};
0287   cpu_sum = std::accumulate(mng_store.get<e_test_class>().first.begin(),
0288                             mng_store.get<e_test_class>().first.end(), cpu_sum);
0289   cpu_sum =
0290       std::accumulate(mng_store.get<e_test_class>().second.begin(),
0291                       mng_store.get<e_test_class>().second.end(), cpu_sum);
0292   EXPECT_NEAR(cpu_sum, 83.3, tol);
0293 
0294   // CUDA sum check
0295   typename multi_store_t::view_type store_view = get_data(mng_store);
0296 
0297   vecmem::vector<double> cuda_sum(&mng_mr);
0298   cuda_sum.push_back(0.);
0299   auto sum_data = vecmem::get_data(cuda_sum);
0300 
0301   test_multi_store(store_view, sum_data);
0302 
0303   EXPECT_NEAR(cpu_sum, cuda_sum[0], tol);
0304 
0305   // Reset for next test
0306   cuda_sum[0] = 0.;
0307 
0308   // Copy the host store to device, get the view to it and run the test again
0309   multi_store_t::buffer_type store_buffer =
0310       detray::get_buffer(store, dev_mr, cpy);
0311   multi_store_t::view_type buffer_view = detray::get_data(store_buffer);
0312 
0313   EXPECT_NEAR(cuda_sum[0], 0.f, tol);
0314 
0315   test_multi_store(buffer_view, sum_data);
0316 
0317   EXPECT_NEAR(cuda_sum[0], cpu_sum, tol);
0318 }