Skip to content

Commit 2f2cacb

Browse files
authored
Merge pull request #47028 from makortel/alpakaSynchronize
Add central `synchronize` configuration parameter to Alpaka modules
2 parents 9aa0a45 + 5469807 commit 2f2cacb

27 files changed

+205
-92
lines changed

HeterogeneousCore/AlpakaCore/README.md

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,9 @@ The `...` can in principle be any of the module abilities listed in the linked T
146146

147147
New base classes (or other functionality) can be added based on new use cases that come up.
148148

149-
The Alpaka-based ESProducers should use the `ESProducer` base class (`#include "HeterogeneousCore/AlpakaCore/interface/alpaka/ESProducer.h"`). Note that the Alpaka-based ESProducer constructor must pass the argument `edm::ParameterSet` object to the constructor of the `ESProducer` base class.
149+
The Alpaka-based ESProducers should use the `ESProducer` base class (`#include "HeterogeneousCore/AlpakaCore/interface/alpaka/ESProducer.h"`).
150+
151+
Note that both the Alpaka-based EDProducer and ESProducer constructors must pass the argument `edm::ParameterSet` object to the constructor of their base class.
150152

151153
Note that currently Alpaka-based ESSources are not supported. If you need to produce EventSetup data products into a Record for which there is no ESSource yet, use [`EmptyESSource`](https://twiki.cern.ch/twiki/bin/view/CMSPublic/SWGuideEDMParametersForModules#EmptyESSource).
152154

@@ -237,8 +239,10 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
237239
class ExampleAlpakaProducer : public global::EDProducer<> {
238240
public:
239241
ExampleAlpakaProducer(edm::ParameterSet const& iConfig)
240-
// produces() must not specify the product type, it is deduced from deviceToken_
241-
: deviceToken_{produces()}, size_{iConfig.getParameter<int32_t>("size")} {}
242+
: EDProducer<>(iConfig),
243+
// produces() must not specify the product type, it is deduced from deviceToken_
244+
deviceToken_{produces()},
245+
size_{iConfig.getParameter<int32_t>("size")} {}
242246

243247
// device::Event and device::EventSetup are defined in ALPAKA_ACCELERATOR_NAMESPACE as well
244248
void produce(edm::StreamID sid, device::Event& iEvent, device::EventSetup const& iSetup) const override {
@@ -479,6 +483,24 @@ process.ProcessAcceleratorAlpaka.setBackend("serial_sync") # or "cuda_async" or
479483
process.options.accelerators = ["cpu"] # or "gpu-nvidia" or "gpu-amd"
480484
```
481485

486+
### Blocking synchronization (for testing)
487+
488+
While the general approach is to favor asynchronous operations with non-blocking synchronization, for testing purposes it can be useful to synchronize the EDModule's `acquire()` / `produce()` or ESProducer's production functions in a blocking way. Such a blocking synchronization can be specified for individual modules via the `alpaka` `PSet` along
489+
```python
490+
process.producer = cms.EDProducer("ExampleAlpakaProducer@alpaka",
491+
...
492+
alpaka = cms.untracked.PSet(
493+
synchronize = cms.untracked.bool(True)
494+
)
495+
)
496+
```
497+
498+
The blocking synchronization can be specified for all Alpaka modules via the `ProcessAcceleratorAlpaka` along
499+
```python
500+
process.ProcessAcceleratorAlpaka.setSynchronize(True)
501+
```
502+
Note that the possible per-module parameter overrides this global setting.
503+
482504

483505
## Unit tests
484506

HeterogeneousCore/AlpakaCore/interface/alpaka/EDMetadataAcquireSentry.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
1616
public:
1717
// TODO: WaitingTaskWithArenaHolder not really needed for host synchronous case
1818
// Constructor overload to be called from acquire()
19-
EDMetadataAcquireSentry(edm::StreamID stream, edm::WaitingTaskWithArenaHolder holder);
19+
EDMetadataAcquireSentry(edm::StreamID stream, edm::WaitingTaskWithArenaHolder holder, bool synchronize);
2020

2121
// Constructor overload to be called from registerTransformAsync()
22-
EDMetadataAcquireSentry(Device const& device, edm::WaitingTaskWithArenaHolder holder);
22+
EDMetadataAcquireSentry(Device const& device, edm::WaitingTaskWithArenaHolder holder, bool synchronize = false);
2323

2424
EDMetadataAcquireSentry(EDMetadataAcquireSentry const&) = delete;
2525
EDMetadataAcquireSentry& operator=(EDMetadataAcquireSentry const&) = delete;
@@ -40,6 +40,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
4040
std::shared_ptr<EDMetadata> metadata_;
4141

4242
edm::WaitingTaskWithArenaHolder waitingTaskHolder_;
43+
bool const synchronize_;
4344
};
4445
} // namespace detail
4546
} // namespace ALPAKA_ACCELERATOR_NAMESPACE

HeterogeneousCore/AlpakaCore/interface/alpaka/EDMetadataSentry.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
1414
class EDMetadataSentry {
1515
public:
1616
// For normal module
17-
EDMetadataSentry(edm::StreamID stream);
17+
EDMetadataSentry(edm::StreamID stream, bool synchronize);
1818

1919
// For ExternalWork-module's produce()
20-
EDMetadataSentry(std::shared_ptr<EDMetadata> metadata) : metadata_(std::move(metadata)) {}
20+
EDMetadataSentry(std::shared_ptr<EDMetadata> metadata, bool synchronize)
21+
: metadata_(std::move(metadata)), synchronize_(synchronize) {}
2122

2223
EDMetadataSentry(EDMetadataSentry const&) = delete;
2324
EDMetadataSentry& operator=(EDMetadataSentry const&) = delete;
@@ -31,6 +32,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
3132

3233
private:
3334
std::shared_ptr<EDMetadata> metadata_;
35+
bool const synchronize_;
3436
};
3537
} // namespace detail
3638
} // namespace ALPAKA_ACCELERATOR_NAMESPACE

HeterogeneousCore/AlpakaCore/interface/alpaka/ESProducer.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
#include "FWCore/Framework/interface/ESProducer.h"
55
#include "FWCore/Framework/interface/MakeDataException.h"
66
#include "FWCore/Framework/interface/produce_helpers.h"
7-
#include "HeterogeneousCore/AlpakaCore/interface/module_backend_config.h"
7+
#include "HeterogeneousCore/AlpakaCore/interface/modulePrevalidate.h"
88
#include "HeterogeneousCore/AlpakaCore/interface/alpaka/ESDeviceProduct.h"
99
#include "HeterogeneousCore/AlpakaCore/interface/alpaka/ESDeviceProductType.h"
1010
#include "HeterogeneousCore/AlpakaCore/interface/alpaka/Record.h"
@@ -30,7 +30,7 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
3030
public:
3131
static void prevalidate(edm::ConfigurationDescriptions& descriptions) {
3232
Base::prevalidate(descriptions);
33-
cms::alpakatools::module_backend_config(descriptions);
33+
cms::alpakatools::modulePrevalidate(descriptions);
3434
}
3535

3636
protected:

HeterogeneousCore/AlpakaCore/interface/alpaka/ProducerBase.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
#include "FWCore/Framework/interface/FrameworkfwdMostUsed.h"
66
#include "FWCore/Framework/interface/moduleAbilities.h"
77
#include "FWCore/Framework/interface/Event.h"
8+
#include "FWCore/ParameterSet/interface/ParameterSet.h"
89
#include "FWCore/Utilities/interface/EDPutToken.h"
910
#include "FWCore/Utilities/interface/Transition.h"
1011
#include "HeterogeneousCore/AlpakaCore/interface/alpaka/DeviceProductType.h"
1112
#include "HeterogeneousCore/AlpakaCore/interface/alpaka/EDMetadataAcquireSentry.h"
1213
#include "HeterogeneousCore/AlpakaCore/interface/EventCache.h"
1314
#include "HeterogeneousCore/AlpakaCore/interface/QueueCache.h"
14-
#include "HeterogeneousCore/AlpakaCore/interface/module_backend_config.h"
15+
#include "HeterogeneousCore/AlpakaCore/interface/modulePrevalidate.h"
1516
#include "HeterogeneousCore/AlpakaInterface/interface/Backend.h"
1617
#include "HeterogeneousCore/AlpakaInterface/interface/CopyToHost.h"
1718

@@ -46,7 +47,15 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
4647
using Base = BaseT<Args..., edm::Transformer>;
4748

4849
public:
50+
// TODO: default constructor to be removed after all derived classes have been migrated
4951
ProducerBase() : backendToken_(Base::produces("backend")) {}
52+
ProducerBase(edm::ParameterSet const& iConfig)
53+
: backendToken_(Base::produces("backend")),
54+
// The 'synchronize' parameter can be unset in Alpaka
55+
// modules specified with the namespace prefix instead if
56+
// '@alpaka' suffix
57+
synchronize_(iConfig.getUntrackedParameter<edm::ParameterSet>("alpaka").getUntrackedParameter<bool>(
58+
"synchronize", false)) {}
5059

5160
template <edm::Transition Tr = edm::Transition::Event>
5261
[[nodiscard]] auto produces() noexcept {
@@ -60,16 +69,19 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
6069

6170
static void prevalidate(edm::ConfigurationDescriptions& descriptions) {
6271
Base::prevalidate(descriptions);
63-
cms::alpakatools::module_backend_config(descriptions);
72+
cms::alpakatools::modulePrevalidate(descriptions);
6473
}
6574

6675
protected:
6776
void putBackend(edm::Event& iEvent) const {
6877
iEvent.emplace(this->backendToken_, static_cast<unsigned short>(kBackend));
6978
}
7079

80+
bool synchronize() const { return synchronize_; }
81+
7182
private:
7283
edm::EDPutTokenT<unsigned short> const backendToken_;
84+
bool const synchronize_ = false;
7385

7486
template <typename TProducer, edm::Transition Tr>
7587
friend class ProducerBaseAdaptor;

HeterogeneousCore/AlpakaCore/interface/alpaka/global/EDProducer.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
1515
static_assert(not edm::CheckAbility<edm::module::Abilities::kExternalWork, Args...>::kHasIt,
1616
"ALPAKA_ACCELERATOR_NAMESPACE::global::EDProducer may not be used with ExternalWork ability. "
1717
"Please use ALPAKA_ACCELERATOR_NAMESPACE::stream::SynchronizingEDProducer instead.");
18+
using Base = ProducerBase<edm::global::EDProducer, Args...>;
19+
20+
protected:
21+
EDProducer() = default; // to be removed in the near future
22+
EDProducer(edm::ParameterSet const iConfig) : Base(iConfig) {}
1823

1924
public:
2025
void produce(edm::StreamID sid, edm::Event& iEvent, edm::EventSetup const& iSetup) const final {
21-
detail::EDMetadataSentry sentry(sid);
26+
detail::EDMetadataSentry sentry(sid, this->synchronize());
2227
device::Event ev(iEvent, sentry.metadata());
2328
device::EventSetup const es(iSetup, ev.device());
2429
produce(sid, ev, es);

HeterogeneousCore/AlpakaCore/interface/alpaka/stream/EDProducer.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
1515
static_assert(not edm::CheckAbility<edm::module::Abilities::kExternalWork, Args...>::kHasIt,
1616
"ALPAKA_ACCELERATOR_NAMESPACE::stream::EDProducer may not be used with ExternalWork ability. "
1717
"Please use ALPAKA_ACCELERATOR_NAMESPACE::stream::SynchronizingEDProducer instead.");
18+
using Base = ProducerBase<edm::stream::EDProducer, Args...>;
19+
20+
protected:
21+
EDProducer() = default; // to be removed in the near future
22+
EDProducer(edm::ParameterSet const iConfig) : Base(iConfig) {}
1823

1924
public:
2025
void produce(edm::Event& iEvent, edm::EventSetup const& iSetup) final {
21-
detail::EDMetadataSentry sentry(iEvent.streamID());
26+
detail::EDMetadataSentry sentry(iEvent.streamID(), this->synchronize());
2227
device::Event ev(iEvent, sentry.metadata());
2328
device::EventSetup const es(iSetup, ev.device());
2429
produce(ev, es);

HeterogeneousCore/AlpakaCore/interface/alpaka/stream/SynchronizingEDProducer.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,25 @@ namespace ALPAKA_ACCELERATOR_NAMESPACE {
1818
not edm::CheckAbility<edm::module::Abilities::kExternalWork, Args...>::kHasIt,
1919
"ExternalWork ability is redundant with ALPAKA_ACCELERATOR_NAMESPACE::stream::SynchronizingEDProducer."
2020
"Please remove it.");
21+
using Base = ProducerBase<edm::stream::EDProducer, edm::ExternalWork, Args...>;
22+
23+
protected:
24+
SynchronizingEDProducer() = default; // to be removed in the near future
25+
SynchronizingEDProducer(edm::ParameterSet const iConfig) : Base(iConfig) {}
2126

2227
public:
2328
void acquire(edm::Event const& iEvent,
2429
edm::EventSetup const& iSetup,
2530
edm::WaitingTaskWithArenaHolder holder) final {
26-
detail::EDMetadataAcquireSentry sentry(iEvent.streamID(), std::move(holder));
31+
detail::EDMetadataAcquireSentry sentry(iEvent.streamID(), std::move(holder), this->synchronize());
2732
device::Event const ev(iEvent, sentry.metadata());
2833
device::EventSetup const es(iSetup, ev.device());
2934
acquire(ev, es);
3035
metadata_ = sentry.finish();
3136
}
3237

3338
void produce(edm::Event& iEvent, edm::EventSetup const& iSetup) final {
34-
detail::EDMetadataSentry sentry(std::move(metadata_));
39+
detail::EDMetadataSentry sentry(std::move(metadata_), this->synchronize());
3540
device::Event ev(iEvent, sentry.metadata());
3641
device::EventSetup const es(iSetup, ev.device());
3742
produce(ev, es);
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef HeterogeneousCore_AlpakaCore_interface_modulePrevalidate_h
2+
#define HeterogeneousCore_AlpakaCore_interface_modulePrevalidate_h
3+
4+
#include "FWCore/Framework/interface/FrameworkfwdMostUsed.h"
5+
6+
namespace cms::alpakatools {
7+
void modulePrevalidate(edm::ConfigurationDescriptions& iDesc);
8+
} // namespace cms::alpakatools
9+
10+
#endif

HeterogeneousCore/AlpakaCore/interface/module_backend_config.h

Lines changed: 0 additions & 10 deletions
This file was deleted.

0 commit comments

Comments
 (0)