File indexing completed on 2026-07-26 08:22:12
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include <vecmem/memory/device_atomic_ref.hpp>
0013 #include <vecmem/memory/memory_resource.hpp>
0014 #include <vecmem/memory/unique_ptr.hpp>
0015 #include <vecmem/utils/copy.hpp>
0016
0017
0018 #include <sycl/sycl.hpp>
0019
0020
0021 #include <concepts>
0022 #include <utility>
0023
0024 namespace traccc::sycl {
0025
0026 namespace kernels {
0027
0028
0029
0030
0031
0032
0033 template <typename CONTAINER, typename P, typename VIEW,
0034 std::equality_comparable S>
0035 struct is_contiguous_on_compress_adjacent {
0036
0037 is_contiguous_on_compress_adjacent(P projection, VIEW view,
0038 vecmem::data::vector_view<S> out_view)
0039 : m_projection(projection), m_view(view), m_out_view(out_view) {}
0040
0041
0042 void operator()(::sycl::nd_item<1> item) const {
0043 std::size_t tid = item.get_global_linear_id();
0044
0045 const CONTAINER in(m_view);
0046 vecmem::device_vector<S> out(m_out_view);
0047
0048 if (tid > 0 && tid < in.size()) {
0049 S v1 = m_projection(in.at(static_cast<CONTAINER::size_type>(tid - 1)));
0050 S v2 = m_projection(in.at(static_cast<CONTAINER::size_type>(tid)));
0051
0052 if (v1 != v2) {
0053 out.push_back(v2);
0054 }
0055 } else if (tid == 0) {
0056 out.push_back(
0057 m_projection(in.at(static_cast<CONTAINER::size_type>(tid))));
0058 }
0059 }
0060
0061
0062 P m_projection;
0063
0064 VIEW m_view;
0065
0066 vecmem::data::vector_view<S> m_out_view;
0067 };
0068
0069
0070 template <typename T>
0071 class is_contiguous_on_all_unique {};
0072
0073 }
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 template <typename CONTAINER, typename P, typename VIEW>
0096 requires std::regular_invocable<P,
0097 decltype(std::declval<CONTAINER>().at(0))> &&
0098 std::semiregular<P>
0099 bool is_contiguous_on(P&& projection, vecmem::memory_resource& mr,
0100 const vecmem::copy& copy, ::sycl::queue& queue,
0101 const VIEW& view) {
0102
0103
0104 constexpr int local_size = 512;
0105 constexpr int local_size_2d = 16;
0106
0107
0108 const typename VIEW::size_type n = copy.get_size(view);
0109
0110
0111 if (n == 0) {
0112 return true;
0113 }
0114
0115
0116 using projection_t =
0117 std::invoke_result_t<P, decltype(std::declval<CONTAINER>().at(0))>;
0118
0119
0120 vecmem::data::vector_buffer<projection_t> iout(
0121 n, mr, vecmem::data::buffer_type::resizable);
0122 copy.setup(iout)->wait();
0123 vecmem::unique_alloc_ptr<bool> out = vecmem::make_unique_alloc<bool>(mr);
0124
0125 bool initial_out = true;
0126
0127 ::sycl::event kernel2_memcpy_evt = queue.copy(&initial_out, out.get(), 1);
0128
0129 ::sycl::nd_range<1> compress_adjacent_range{
0130 ::sycl::range<1>(((n + local_size - 1) / local_size) * local_size),
0131 ::sycl::range<1>(local_size)};
0132
0133
0134
0135 queue
0136 .submit([&](::sycl::handler& h) {
0137 h.parallel_for<kernels::is_contiguous_on_compress_adjacent<
0138 CONTAINER, P, VIEW, projection_t>>(
0139 compress_adjacent_range,
0140 kernels::is_contiguous_on_compress_adjacent<CONTAINER, P, VIEW,
0141 projection_t>(
0142 projection, view, iout));
0143 })
0144 .wait_and_throw();
0145
0146 typename vecmem::data::vector_view<projection_t>::size_type host_iout_size =
0147 copy.get_size(iout);
0148 uint32_t grid_size_rd = (host_iout_size + local_size_2d - 1) / local_size_2d;
0149 ::sycl::nd_range<2> all_unique_range{
0150 ::sycl::range<2>(grid_size_rd * local_size_2d,
0151 grid_size_rd * local_size_2d),
0152 ::sycl::range<2>(local_size_2d, local_size_2d)};
0153
0154
0155 ::sycl::event kernel2_evt = queue.submit([&](::sycl::handler& h) {
0156 h.depends_on(kernel2_memcpy_evt);
0157 h.parallel_for<kernels::is_contiguous_on_all_unique<projection_t>>(
0158 all_unique_range, [in_view = vecmem::get_data(iout),
0159 out = out.get()](::sycl::nd_item<2> item) {
0160 std::size_t tid_x = item.get_global_id(0);
0161 std::size_t tid_y = item.get_global_id(1);
0162
0163 const vecmem::device_vector<projection_t> in(in_view);
0164
0165 if (tid_x < in.size() && tid_y < in.size() && tid_x != tid_y &&
0166 in.at(static_cast<CONTAINER::size_type>(tid_x)) ==
0167 in.at(static_cast<CONTAINER::size_type>(tid_y))) {
0168 *out = false;
0169 }
0170 });
0171 });
0172
0173
0174 bool host_out;
0175
0176 queue.memcpy(&host_out, out.get(), sizeof(bool), {kernel2_evt})
0177 .wait_and_throw();
0178
0179 return host_out;
0180 }
0181 }