Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:54:12

0001 /*
0002  * SPDX-PackageName: "covfie, a part of the ACTS project"
0003  * SPDX-FileCopyrightText: 2022 CERN
0004  * SPDX-License-Identifier: MPL-2.0
0005  */
0006 
0007 #pragma once
0008 
0009 #include <memory>
0010 
0011 #include <covfie/core/backend/primitive/array.hpp>
0012 #include <covfie/core/concepts.hpp>
0013 #include <covfie/core/qualifiers.hpp>
0014 #include <covfie/core/vector.hpp>
0015 #include <covfie/sycl/utility/memory.hpp>
0016 #include <covfie/sycl/utility/unique_ptr.hpp>
0017 
0018 namespace covfie::backend {
0019 template <
0020     concepts::vector_descriptor _output_vector_t,
0021     typename _index_t = std::size_t>
0022 struct sycl_device_array {
0023     using this_t = sycl_device_array<_output_vector_t, _index_t>;
0024 
0025     static constexpr bool is_initial = true;
0026 
0027     using contravariant_input_t =
0028         covfie::vector::scalar_d<covfie::vector::vector_d<_index_t, 1>>;
0029     using covariant_output_t =
0030         covfie::vector::array_reference_vector_d<_output_vector_t>;
0031 
0032     using output_vector_t = _output_vector_t;
0033 
0034     using value_t = typename output_vector_t::type[output_vector_t::size];
0035     using vector_t = std::decay_t<typename covariant_output_t::vector_t>;
0036 
0037     using configuration_t = utility::nd_size<1>;
0038 
0039     static constexpr uint32_t IO_MAGIC_HEADER = 0xAB210000;
0040 
0041     struct owning_data_t {
0042         using parent_t = this_t;
0043 
0044         owning_data_t() = delete;
0045 
0046         owning_data_t(::sycl::queue & queue)
0047             : m_size(0)
0048             , m_queue(queue)
0049             , m_ptr({})
0050         {
0051         }
0052 
0053         owning_data_t(owning_data_t &&) = default;
0054         owning_data_t & operator=(owning_data_t &&) = default;
0055 
0056         owning_data_t & operator=(const owning_data_t & o)
0057         {
0058             m_size = o.m_size;
0059             m_ptr.reset();
0060             m_queue = o.m_queue;
0061             m_ptr =
0062                 utility::sycl::device_copy_d2d(o.m_ptr.get(), m_size, m_queue);
0063 
0064             return *this;
0065         }
0066 
0067         owning_data_t(const owning_data_t & o)
0068             : m_size(o.m_size)
0069             , m_queue(o.m_queue)
0070             , m_ptr(
0071                   utility::sycl::device_copy_d2d(o.m_ptr.get(), m_size, m_queue)
0072               )
0073         {
0074             assert(m_size == 0 || m_ptr);
0075 
0076             if (o.m_ptr && m_size > 0) {
0077                 std::memcpy(
0078                     m_ptr.get(), o.m_ptr.get(), m_size * sizeof(vector_t)
0079                 );
0080             }
0081         }
0082 
0083         explicit owning_data_t(parameter_pack<owning_data_t> && args)
0084             : owning_data_t(std::move(args.x))
0085         {
0086         }
0087 
0088         // TODO
0089         explicit owning_data_t(parameter_pack<configuration_t> && args)
0090             : m_size(args.x[0])
0091             , m_ptr(utility::sycl::device_allocate<vector_t[]>(m_size, m_queue))
0092         {
0093         }
0094 
0095         explicit owning_data_t(
0096             std::size_t size,
0097             std::unique_ptr<vector_t[]> && ptr,
0098             ::sycl::queue & queue
0099         )
0100             : m_size(size)
0101             , m_queue(queue)
0102             , m_ptr(utility::sycl::device_copy_h2d(ptr.get(), size, m_queue))
0103         {
0104         }
0105 
0106         template <typename B>
0107         requires(!std::same_as<B, owning_data_t> && concepts::array_1d_like_field_backend<typename B::parent_t>) explicit owning_data_t(
0108             const B & o, ::sycl::queue & queue
0109         )
0110             : owning_data_t(o.get_size(), o.get_host_array(), queue)
0111         {
0112         }
0113 
0114         configuration_t get_configuration() const
0115         {
0116             return {m_size};
0117         }
0118 
0119         static owning_data_t read_binary(std::istream & fs)
0120         {
0121             utility::read_io_header(fs, IO_MAGIC_HEADER);
0122 
0123             uint32_t float_width = utility::read_binary<uint32_t>(fs);
0124 
0125             if (float_width != 4 && float_width != 8) {
0126                 throw std::runtime_error(
0127                     "Float type is neither IEEE 754 single- nor "
0128                     "double-precision, binary input is not supported."
0129                 );
0130             }
0131 
0132             auto size =
0133                 utility::read_binary<std::decay_t<decltype(m_size)>>(fs);
0134             std::unique_ptr<vector_t[]> ptr =
0135                 std::make_unique<vector_t[]>(size);
0136 
0137             for (std::size_t i = 0; i < size; ++i) {
0138                 for (std::size_t j = 0; j < _output_vector_t::size; ++j) {
0139                     if (float_width == 4) {
0140                         ptr[i][j] = utility::read_binary<float>(fs);
0141                     } else if (float_width == 8) {
0142                         ptr[i][j] = utility::read_binary<double>(fs);
0143                     } else {
0144                         throw std::logic_error("Float width is unexpected.");
0145                     }
0146                 }
0147             }
0148 
0149             utility::read_io_footer(fs, IO_MAGIC_HEADER);
0150 
0151             return owning_data_t(size, std::move(ptr));
0152         }
0153 
0154         static void write_binary(std::ostream & fs, const owning_data_t & o)
0155         {
0156             utility::write_io_header(fs, IO_MAGIC_HEADER);
0157 
0158             uint32_t float_width;
0159 
0160             if constexpr (std::
0161                               is_same_v<typename _output_vector_t::type, float>)
0162             {
0163                 float_width = 4;
0164             } else if constexpr (std::is_same_v<
0165                                      typename _output_vector_t::type,
0166                                      double>)
0167             {
0168                 float_width = 8;
0169             } else {
0170                 throw std::logic_error(
0171                     "Float type is neither IEEE 754 single- nor "
0172                     "double-precision, binary output is not supported."
0173                 );
0174             }
0175 
0176             fs.write(
0177                 reinterpret_cast<const char *>(&float_width),
0178                 sizeof(std::decay_t<decltype(float_width)>)
0179             );
0180 
0181             fs.write(
0182                 reinterpret_cast<const char *>(&o.m_size),
0183                 sizeof(std::decay_t<decltype(o.m_size)>)
0184             );
0185 
0186             for (std::size_t i = 0; i < o.m_size; ++i) {
0187                 for (std::size_t j = 0; j < _output_vector_t::size; ++j) {
0188                     fs.write(
0189                         reinterpret_cast<const char *>(&o.m_ptr[i][j]),
0190                         sizeof(typename _output_vector_t::type)
0191                     );
0192                 }
0193             }
0194 
0195             utility::write_io_footer(fs, IO_MAGIC_HEADER);
0196         }
0197 
0198         std::size_t m_size;
0199         ::sycl::queue m_queue;
0200         utility::sycl::unique_device_ptr<vector_t[]> m_ptr;
0201     };
0202 
0203     struct non_owning_data_t {
0204         using parent_t = this_t;
0205 
0206         non_owning_data_t(const owning_data_t & o)
0207             : m_ptr(o.m_ptr.get())
0208         {
0209         }
0210 
0211         COVFIE_HOST_DEVICE typename covariant_output_t::vector_t
0212         at(typename contravariant_input_t::vector_t i) const
0213         {
0214             return m_ptr[i];
0215         }
0216 
0217         vector_t * m_ptr;
0218     };
0219 };
0220 }