Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-12-19 04:04:30

0001 #ifndef DataFormats_Portable_interface_PortableHostObject_h
0002 #define DataFormats_Portable_interface_PortableHostObject_h
0003 
0004 #include <cassert>
0005 #include <optional>
0006 #include <type_traits>
0007 
0008 #include <alpaka/alpaka.hpp>
0009 
0010 #include "DataFormats/Common/interface/Uninitialized.h"
0011 #include "HeterogeneousCore/AlpakaInterface/interface/config.h"
0012 #include "HeterogeneousCore/AlpakaInterface/interface/host.h"
0013 #include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
0014 
0015 // generic object in host memory
0016 template <typename T>
0017 class PortableHostObject {
0018 public:
0019   using Product = T;
0020   using Buffer = cms::alpakatools::host_buffer<Product>;
0021   using ConstBuffer = cms::alpakatools::const_host_buffer<Product>;
0022 
0023   static_assert(std::is_trivially_destructible_v<Product>);
0024 
0025   PortableHostObject() = delete;
0026 
0027   PortableHostObject(edm::Uninitialized) noexcept {}
0028 
0029   // Note that in contrast to the variadic template overload, this
0030   // constructor does not initialize the contained object
0031   PortableHostObject(alpaka_common::DevHost const& host)
0032       // allocate pageable host memory
0033       : buffer_{cms::alpakatools::make_host_buffer<Product>()}, product_{buffer_->data()} {
0034     assert(reinterpret_cast<uintptr_t>(product_) % alignof(Product) == 0);
0035   }
0036 
0037   template <typename... Args>
0038   PortableHostObject(alpaka_common::DevHost const& host, Args&&... args)
0039       // allocate pageable host memory
0040       : buffer_{cms::alpakatools::make_host_buffer<Product>()},
0041         product_{new(buffer_->data()) Product(std::forward<Args>(args)...)} {
0042     assert(reinterpret_cast<uintptr_t>(product_) % alignof(Product) == 0);
0043   }
0044 
0045   // Note that in contrast to the variadic template overload, this
0046   // constructor does not initialize the contained object
0047   template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0048   PortableHostObject(TQueue const& queue)
0049       // allocate pinned host memory associated to the given work queue, accessible by the queue's device
0050       : buffer_{cms::alpakatools::make_host_buffer<Product>(queue)}, product_{buffer_->data()} {
0051     assert(reinterpret_cast<uintptr_t>(product_) % alignof(Product) == 0);
0052   }
0053 
0054   template <typename TQueue, typename... Args, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0055   PortableHostObject(TQueue const& queue, Args&&... args)
0056       // allocate pinned host memory associated to the given work queue, accessible by the queue's device
0057       : buffer_{cms::alpakatools::make_host_buffer<Product>(queue)},
0058         product_{new(buffer_->data()) Product(std::forward<Args>(args)...)} {
0059     assert(reinterpret_cast<uintptr_t>(product_) % alignof(Product) == 0);
0060   }
0061 
0062   // non-copyable
0063   PortableHostObject(PortableHostObject const&) = delete;
0064   PortableHostObject& operator=(PortableHostObject const&) = delete;
0065 
0066   // movable
0067   PortableHostObject(PortableHostObject&&) = default;
0068   PortableHostObject& operator=(PortableHostObject&&) = default;
0069 
0070   // default destructor
0071   ~PortableHostObject() = default;
0072 
0073   // access the product
0074   Product& value() { return *product_; }
0075   Product const& value() const { return *product_; }
0076   Product const& const_value() const { return *product_; }
0077 
0078   Product* data() { return product_; }
0079   Product const* data() const { return product_; }
0080   Product const* const_data() const { return product_; }
0081 
0082   Product& operator*() { return *product_; }
0083   Product const& operator*() const { return *product_; }
0084 
0085   Product* operator->() { return product_; }
0086   Product const* operator->() const { return product_; }
0087 
0088   // access the buffer
0089   Buffer buffer() { return *buffer_; }
0090   ConstBuffer buffer() const { return *buffer_; }
0091   ConstBuffer const_buffer() const { return *buffer_; }
0092 
0093   // erases the data in the Buffer by writing zeros (bytes containing '\0') to it
0094   void zeroInitialise() {
0095     std::memset(std::data(*buffer_), 0x00, alpaka::getExtentProduct(*buffer_) * sizeof(std::byte));
0096   }
0097 
0098   template <typename TQueue, typename = std::enable_if_t<alpaka::isQueue<TQueue>>>
0099   void zeroInitialise(TQueue&& queue) {
0100     alpaka::memset(std::forward<TQueue>(queue), *buffer_, 0x00);
0101   }
0102 
0103   // part of the ROOT read streamer
0104   static void ROOTReadStreamer(PortableHostObject* newObj, Product& product) {
0105     // destroy the default-constructed object
0106     newObj->~PortableHostObject();
0107     // use the global "host" object returned by cms::alpakatools::host()
0108     new (newObj) PortableHostObject(cms::alpakatools::host());
0109     // copy the data from the on-file object to the new one
0110     std::memcpy(newObj->product_, &product, sizeof(Product));
0111   }
0112 
0113 private:
0114   std::optional<Buffer> buffer_;  //!
0115   Product* product_;
0116 };
0117 
0118 #endif  // DataFormats_Portable_interface_PortableHostObject_h