File indexing completed on 2024-05-29 23:12:53
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/Utilities/interface/EDPutToken.h"
0009 #include "FWCore/Utilities/interface/Transition.h"
0010 #include "HeterogeneousCore/AlpakaCore/interface/alpaka/DeviceProductType.h"
0011 #include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDMetadataAcquireSentry.h"
0012 #include "HeterogeneousCore/AlpakaCore/interface/EventCache.h"
0013 #include "HeterogeneousCore/AlpakaCore/interface/QueueCache.h"
0014 #include "HeterogeneousCore/AlpakaCore/interface/module_backend_config.h"
0015 #include "HeterogeneousCore/AlpakaInterface/interface/Backend.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() : backendToken_(Base::produces("backend")) {}
0050
0051 template <edm::Transition Tr = edm::Transition::Event>
0052 [[nodiscard]] auto produces() noexcept {
0053 return ProducerBaseAdaptor<ProducerBase, Tr>(*this);
0054 }
0055
0056 template <edm::Transition Tr = edm::Transition::Event>
0057 [[nodiscard]] auto produces(std::string instanceName) noexcept {
0058 return ProducerBaseAdaptor<ProducerBase, Tr>(*this, std::move(instanceName));
0059 }
0060
0061 static void prevalidate(edm::ConfigurationDescriptions& descriptions) {
0062 Base::prevalidate(descriptions);
0063 cms::alpakatools::module_backend_config(descriptions);
0064 }
0065
0066 protected:
0067 void putBackend(edm::Event& iEvent) const {
0068 iEvent.emplace(this->backendToken_, static_cast<unsigned short>(kBackend));
0069 }
0070
0071 private:
0072 edm::EDPutTokenT<unsigned short> const backendToken_;
0073
0074 template <typename TProducer, edm::Transition Tr>
0075 friend class ProducerBaseAdaptor;
0076
0077
0078
0079
0080
0081 template <typename TProduct, edm::Transition Tr>
0082 edm::EDPutTokenT<TProduct> produces(std::string instanceName) {
0083 return Base::template produces<TProduct, Tr>(std::move(instanceName));
0084 }
0085
0086
0087
0088
0089
0090 template <typename TProduct, typename TToken, edm::Transition Tr>
0091 edm::EDPutTokenT<TToken> deviceProduces(std::string instanceName) {
0092 if constexpr (detail::useProductDirectly<TProduct>) {
0093 return Base::template produces<TToken, Tr>(std::move(instanceName));
0094 } else {
0095 edm::EDPutTokenT<TToken> token = Base::template produces<TToken, Tr>(instanceName);
0096 this->registerTransformAsync(
0097 token,
0098 [](TToken const& deviceProduct, edm::WaitingTaskWithArenaHolder holder) {
0099 auto const& device = alpaka::getDev(deviceProduct.template metadata<EDMetadata>().queue());
0100 detail::EDMetadataAcquireSentry sentry(device, std::move(holder));
0101 auto metadataPtr = sentry.metadata();
0102 constexpr bool tryReuseQueue = true;
0103 TProduct const& productOnDevice =
0104 deviceProduct.template getSynchronized<EDMetadata>(*metadataPtr, tryReuseQueue);
0105
0106 using CopyT = cms::alpakatools::CopyToHost<TProduct>;
0107 auto productOnHost = CopyT::copyAsync(metadataPtr->queue(), productOnDevice);
0108
0109
0110
0111 using TplType = std::tuple<decltype(productOnHost), std::shared_ptr<EDMetadata>>;
0112
0113 return std::make_shared<TplType>(std::move(productOnHost), sentry.finish());
0114 },
0115 [](auto tplPtr) { return std::move(std::get<0>(*tplPtr)); },
0116 std::move(instanceName));
0117 return token;
0118 }
0119 }
0120 };
0121
0122
0123 template <typename TProducer, edm::Transition Tr>
0124 class ProducerBaseAdaptor {
0125 public:
0126
0127 template <typename Type>
0128 edm::EDPutTokenT<Type> produces() {
0129 return producer_.template produces<Type, Tr>(label_);
0130 }
0131
0132
0133 template <typename TProduct, typename TToken>
0134 edm::EDPutTokenT<TToken> deviceProduces() {
0135 return producer_.template deviceProduces<TProduct, TToken, Tr>(label_);
0136 }
0137
0138 private:
0139
0140 friend TProducer;
0141
0142 ProducerBaseAdaptor(TProducer& producer, std::string label) : producer_(producer), label_(std::move(label)) {}
0143 explicit ProducerBaseAdaptor(TProducer& producer) : producer_(producer) {}
0144
0145 TProducer& producer_;
0146 std::string const label_;
0147 };
0148 }
0149
0150 #endif