From 6c9a2840a10514b10caa5b51fe35f0ea2def4231 Mon Sep 17 00:00:00 2001 From: Andrea Bocci Date: Wed, 13 Mar 2024 03:03:05 +0100 Subject: [PATCH] Implement AlpakaBackendProducer and AlpakaBackendFilter Implement AlpakaBackendProducer, an empty alpaka-based EDProducer whose only purpose is to save in the event what alpaka backend has been used. Implement AlpakaBackendFilter, an EDFilter that selects events based on the alpaka backend used to run a previous producer. Implement a unit test for both modules. --- .../AlpakaCore/plugins/AlpakaBackendFilter.cc | 48 +++++++++++++++++++ .../AlpakaCore/plugins/BuildFile.xml | 12 +++++ .../plugins/alpaka/AlpakaBackendProducer.cc | 31 ++++++++++++ .../AlpakaCore/test/BuildFile.xml | 3 ++ .../test/testAlpakaBackendFilter.py | 46 ++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 HeterogeneousCore/AlpakaCore/plugins/AlpakaBackendFilter.cc create mode 100644 HeterogeneousCore/AlpakaCore/plugins/alpaka/AlpakaBackendProducer.cc create mode 100644 HeterogeneousCore/AlpakaCore/test/BuildFile.xml create mode 100644 HeterogeneousCore/AlpakaCore/test/testAlpakaBackendFilter.py diff --git a/HeterogeneousCore/AlpakaCore/plugins/AlpakaBackendFilter.cc b/HeterogeneousCore/AlpakaCore/plugins/AlpakaBackendFilter.cc new file mode 100644 index 0000000000000..5d6a037e8e74e --- /dev/null +++ b/HeterogeneousCore/AlpakaCore/plugins/AlpakaBackendFilter.cc @@ -0,0 +1,48 @@ +#include +#include +#include + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/global/EDFilter.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "HeterogeneousCore/AlpakaInterface/interface/Backend.h" + +class AlpakaBackendFilter : public edm::global::EDFilter<> { +public: + explicit AlpakaBackendFilter(edm::ParameterSet const& config) + : producer_(consumes(config.getParameter("producer"))), backends_{} { + for (auto const& backend : config.getParameter>("backends")) { + backends_[static_cast(cms::alpakatools::toBackend(backend))] = true; + } + } + + bool filter(edm::StreamID sid, edm::Event& event, edm::EventSetup const& setup) const final { + return backends_[event.get(producer_)]; + } + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + const edm::EDGetTokenT producer_; + std::array(cms::alpakatools::Backend::size)> backends_; +}; + +void AlpakaBackendFilter::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("producer", edm::InputTag("alpakaBackendProducer", "backend")) + ->setComment( + "Use the 'backend' instance label to read the backend indicator that is implicitly produced by every alpaka " + "EDProducer."); + desc.add>("backends", {"SerialSync"}) + ->setComment("Valid backends are 'SerialSync', 'CudaAsync', 'ROCmAsync', and 'TbbAsync'."); + descriptions.addWithDefaultLabel(desc); + descriptions.setComment( + "This EDFilter accepts events if the alpaka EDProducer 'producer' was run on a backend among those listed by the " + "'backends' parameter."); +} + +#include "FWCore/Framework/interface/MakerMacros.h" +DEFINE_FWK_MODULE(AlpakaBackendFilter); diff --git a/HeterogeneousCore/AlpakaCore/plugins/BuildFile.xml b/HeterogeneousCore/AlpakaCore/plugins/BuildFile.xml index 80f1acb621283..006fa4ca8679c 100644 --- a/HeterogeneousCore/AlpakaCore/plugins/BuildFile.xml +++ b/HeterogeneousCore/AlpakaCore/plugins/BuildFile.xml @@ -3,5 +3,17 @@ + + + + + + + + + + + + diff --git a/HeterogeneousCore/AlpakaCore/plugins/alpaka/AlpakaBackendProducer.cc b/HeterogeneousCore/AlpakaCore/plugins/alpaka/AlpakaBackendProducer.cc new file mode 100644 index 0000000000000..a09fa075fe245 --- /dev/null +++ b/HeterogeneousCore/AlpakaCore/plugins/alpaka/AlpakaBackendProducer.cc @@ -0,0 +1,31 @@ +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ParameterSet/interface/ParameterSetDescription.h" +#include "FWCore/Utilities/interface/StreamID.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/Event.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EventSetup.h" +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/global/EDProducer.h" +#include "HeterogeneousCore/AlpakaInterface/interface/config.h" + +namespace ALPAKA_ACCELERATOR_NAMESPACE { + + class AlpakaBackendProducer : public global::EDProducer<> { + public: + AlpakaBackendProducer(edm::ParameterSet const& config){}; + + void produce(edm::StreamID sid, device::Event& event, device::EventSetup const&) const override {} + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + descriptions.addWithDefaultLabel(desc); + descriptions.setComment( + "The alpaka EDProducer does not have any explicit products. " + "Its only purpose is to produce a 'backend' value."); + } + }; + +} // namespace ALPAKA_ACCELERATOR_NAMESPACE + +#include "HeterogeneousCore/AlpakaCore/interface/alpaka/MakerMacros.h" +DEFINE_FWK_ALPAKA_MODULE(AlpakaBackendProducer); diff --git a/HeterogeneousCore/AlpakaCore/test/BuildFile.xml b/HeterogeneousCore/AlpakaCore/test/BuildFile.xml new file mode 100644 index 0000000000000..558acc941298c --- /dev/null +++ b/HeterogeneousCore/AlpakaCore/test/BuildFile.xml @@ -0,0 +1,3 @@ + + + diff --git a/HeterogeneousCore/AlpakaCore/test/testAlpakaBackendFilter.py b/HeterogeneousCore/AlpakaCore/test/testAlpakaBackendFilter.py new file mode 100644 index 0000000000000..0ff16f161be9c --- /dev/null +++ b/HeterogeneousCore/AlpakaCore/test/testAlpakaBackendFilter.py @@ -0,0 +1,46 @@ +import os +import sys + +# choose a different alpaka backend depending on the SCRAM test being run +try: + backend = os.environ['SCRAM_ALPAKA_BACKEND'] +except: + backend = 'SerialSync' + +# map the alpaka backends to the process accelerators +accelerators = { + 'SerialSync': 'cpu', + 'CudaAsync': 'gpu-nvidia', + 'ROCmAsync': 'gpu-amd' +} + +print(f"Testing the alpaka backend {backend} using the process accelerator {accelerators[backend]}") + +import FWCore.ParameterSet.Config as cms +from HeterogeneousCore.AlpakaCore.functions import * + +process = cms.Process('Test') + +process.options.accelerators = [ accelerators[backend] ] + +process.maxEvents.input = 10 + +process.source = cms.Source('EmptySource') + +process.load('Configuration.StandardSequences.Accelerators_cff') +process.load('HeterogeneousCore.AlpakaCore.ProcessAcceleratorAlpaka_cfi') + +process.alpakaBackendProducer = cms.EDProducer('AlpakaBackendProducer@alpaka') + +process.alpakaBackendFilter = cms.EDFilter('AlpakaBackendFilter', + producer = cms.InputTag('alpakaBackendProducer', 'backend'), + backends = cms.vstring(backend) +) + +process.mustRun = cms.EDProducer("edmtest::MustRunIntProducer", ivalue=cms.int32(1)) +process.mustNotRun = cms.EDProducer("FailingProducer") + +process.SelectedBackend = cms.Path(process.alpakaBackendProducer + process.alpakaBackendFilter + process.mustRun) +process.AnyOtherBackend = cms.Path(process.alpakaBackendProducer + ~process.alpakaBackendFilter + process.mustNotRun) + +process.options.wantSummary = True