File indexing completed on 2025-02-05 03:15:03
0001 #ifndef HeterogeneousCore_AlpakaCore_interface_ProducerBase_h
0002 #define HeterogeneousCore_AlpakaCore_interface_ProducerBase_h
0003
0004 #include "DataFormats/Common/interface/DeviceProduct.h"
0005 #include "FWCore/Framework/interface/FrameworkfwdMostUsed.h"
0006 #include "FWCore/Framework/interface/moduleAbilities.h"
0007 #include "FWCore/Framework/interface/Event.h"
0008 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0009 #include "FWCore/Utilities/interface/EDPutToken.h"
0010 #include "FWCore/Utilities/interface/Transition.h"
0011 #include "HeterogeneousCore/AlpakaCore/interface/alpaka/DeviceProductType.h"
0012 #include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDMetadataAcquireSentry.h"
0013 #include "HeterogeneousCore/AlpakaCore/interface/modulePrevalidate.h"
0014 #include "HeterogeneousCore/AlpakaInterface/interface/Backend.h"
0015 #include "HeterogeneousCore/AlpakaInterface/interface/CopyToDevice.h"
0016 #include "HeterogeneousCore/AlpakaInterface/interface/CopyToHost.h"
0017
0018 #include <memory>
0019 #include <tuple>
0020
0021 namespace ALPAKA_ACCELERATOR_NAMESPACE {
0022 template <typename Producer, edm::Transition Tr>
0023 class ProducerBaseAdaptor;
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 template <template <typename...> class BaseT, typename... Args>
0042 class ProducerBase : public BaseT<Args..., edm::Transformer> {
0043 static_assert(not edm::CheckAbility<edm::module::Abilities::kTransformer>::kHasIt,
0044 "ALPAKA_ACCELERATOR_NAMESPACE::ProducerBase can not be used with Transformer ability (as it is "
0045 "used internally)");
0046 using Base = BaseT<Args..., edm::Transformer>;
0047
0048 public:
0049 ProducerBase(edm::ParameterSet const& iConfig)
0050 : backendToken_(Base::produces("backend")),
0051
0052
0053
0054 synchronize_(iConfig.getUntrackedParameter<edm::ParameterSet>("alpaka").getUntrackedParameter<bool>(
0055 "synchronize", false)) {}
0056
0057 template <edm::Transition Tr = edm::Transition::Event>
0058 [[nodiscard]] auto produces() noexcept {
0059 return ProducerBaseAdaptor<ProducerBase, Tr>(*this);
0060 }
0061
0062 template <edm::Transition Tr = edm::Transition::Event>
0063 [[nodiscard]] auto produces(std::string instanceName) noexcept {
0064 return ProducerBaseAdaptor<ProducerBase, Tr>(*this, std::move(instanceName));
0065 }
0066
0067 static void prevalidate(edm::ConfigurationDescriptions& descriptions) {
0068 Base::prevalidate(descriptions);
0069 cms::alpakatools::modulePrevalidate(descriptions);
0070 }
0071
0072 protected:
0073 void putBackend(edm::Event& iEvent) const {
0074 iEvent.emplace(this->backendToken_, static_cast<unsigned short>(kBackend));
0075 }
0076
0077 bool synchronize() const { return synchronize_; }
0078
0079 private:
0080 edm::EDPutTokenT<unsigned short> const backendToken_;
0081 bool const synchronize_ = false;
0082
0083 template <typename TProducer, edm::Transition Tr>
0084 friend class ProducerBaseAdaptor;
0085
0086
0087
0088
0089
0090 template <typename TProduct, edm::Transition Tr>
0091 edm::EDPutTokenT<TProduct> produces(std::string instanceName) {
0092 constexpr bool hasCopy = requires(Queue& queue, TProduct const& prod) {
0093 cms::alpakatools::CopyToDevice<TProduct>::copyAsync(queue, prod);
0094 };
0095
0096 if constexpr (detail::useProductDirectly or not hasCopy) {
0097 return Base::template produces<TProduct, Tr>(std::move(instanceName));
0098 } else {
0099 edm::EDPutTokenT<TProduct> hostToken = Base::template produces<TProduct, Tr>(instanceName);
0100 this->registerTransformAsync(
0101 hostToken,
0102 [synchronize = this->synchronize()](
0103 edm::StreamID streamID, TProduct const& hostProduct, edm::WaitingTaskWithArenaHolder holder) {
0104 detail::EDMetadataAcquireSentry sentry(streamID, std::move(holder), synchronize);
0105 using CopyT = cms::alpakatools::CopyToDevice<TProduct>;
0106 auto productOnDevice = CopyT::copyAsync(sentry.metadata()->queue(), hostProduct);
0107
0108
0109 using TplType = std::tuple<std::shared_ptr<EDMetadata>, decltype(productOnDevice)>;
0110
0111 return std::make_shared<TplType>(sentry.finish(), std::move(productOnDevice));
0112 },
0113 [](edm::StreamID, auto tplPtr) {
0114 using DeviceObject = std::tuple_element_t<1, std::remove_cvref_t<decltype(*tplPtr)>>;
0115 using DeviceProductType = detail::DeviceProductType<DeviceObject>;
0116 return DeviceProductType(std::move(std::get<0>(*tplPtr)), std::move(std::get<1>(*tplPtr)));
0117 },
0118 std::move(instanceName));
0119 return hostToken;
0120 }
0121 }
0122
0123
0124
0125
0126
0127 template <typename TProduct, typename TToken, edm::Transition Tr>
0128 edm::EDPutTokenT<TToken> deviceProduces(std::string instanceName) {
0129 if constexpr (detail::useProductDirectly) {
0130 return Base::template produces<TToken, Tr>(std::move(instanceName));
0131 } else {
0132 edm::EDPutTokenT<TToken> token = Base::template produces<TToken, Tr>(instanceName);
0133 using CopyT = cms::alpakatools::CopyToHost<TProduct>;
0134 this->registerTransformAsync(
0135 token,
0136 [](edm::StreamID, TToken const& deviceProduct, edm::WaitingTaskWithArenaHolder holder) {
0137 auto const& device = alpaka::getDev(deviceProduct.template metadata<EDMetadata>().queue());
0138 detail::EDMetadataAcquireSentry sentry(device, std::move(holder));
0139 auto metadataPtr = sentry.metadata();
0140 constexpr bool tryReuseQueue = true;
0141 TProduct const& productOnDevice =
0142 deviceProduct.template getSynchronized<EDMetadata>(*metadataPtr, tryReuseQueue);
0143
0144 auto productOnHost = CopyT::copyAsync(metadataPtr->queue(), productOnDevice);
0145
0146
0147
0148 using TplType = std::tuple<decltype(productOnHost), std::shared_ptr<EDMetadata>>;
0149
0150 return std::make_shared<TplType>(std::move(productOnHost), sentry.finish());
0151 },
0152 [](edm::StreamID, auto tplPtr) {
0153 auto& productOnHost = std::get<0>(*tplPtr);
0154 if constexpr (requires { CopyT::postCopy(productOnHost); }) {
0155 CopyT::postCopy(productOnHost);
0156 }
0157 return std::move(productOnHost);
0158 },
0159 std::move(instanceName));
0160 return token;
0161 }
0162 }
0163 };
0164
0165
0166 template <typename TProducer, edm::Transition Tr>
0167 class ProducerBaseAdaptor {
0168 public:
0169
0170 template <typename Type>
0171 edm::EDPutTokenT<Type> produces() {
0172 return producer_.template produces<Type, Tr>(label_);
0173 }
0174
0175
0176 template <typename TProduct, typename TToken>
0177 edm::EDPutTokenT<TToken> deviceProduces() {
0178 return producer_.template deviceProduces<TProduct, TToken, Tr>(label_);
0179 }
0180
0181 private:
0182
0183 friend TProducer;
0184
0185 ProducerBaseAdaptor(TProducer& producer, std::string label) : producer_(producer), label_(std::move(label)) {}
0186 explicit ProducerBaseAdaptor(TProducer& producer) : producer_(producer) {}
0187
0188 TProducer& producer_;
0189 std::string const label_;
0190 };
0191 }
0192
0193 #endif