Skip to content

Commit 7fb5f59

Browse files
authored
DPL: add allocator to forward a fair::mq::Message payload by shallow copy (#15577)
1 parent 7e06656 commit 7fb5f59

16 files changed

Lines changed: 92 additions & 6 deletions

Framework/Core/include/Framework/DataAllocator.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,11 @@ class DataAllocator
455455
void snapshot(const Output& spec, const char* payload, size_t payloadSize,
456456
o2::header::SerializationMethod serializationMethod = o2::header::gSerializationMethodNone);
457457

458+
/// create a shallow copy of the @a inputPayload and forward it to the output route of @a spec
459+
/// if the transport types of the input and output routes are different, a real copy is created as fallback
460+
void forwardPayload(const Output& spec, fair::mq::Message& inputPayload,
461+
o2::header::SerializationMethod serializationMethod = o2::header::gSerializationMethodNone);
462+
458463
/// make an object of type T and route to output specified by OutputRef
459464
/// The object is owned by the framework, returned reference can be used to fill the object.
460465
///

Framework/Core/include/Framework/InputRecord.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,9 @@ class InputRecord
213213
/// O(1) access to the part described by @a indices in slot @a pos.
214214
[[nodiscard]] DataRef getAtIndices(int pos, DataRefIndices indices) const;
215215

216+
/// Return the payload as fair::mq::Message* for the part described by @a indices in slot @a slotIdx
217+
fair::mq::Message* getPayloadAtIndices(size_t slotIdx, DataRefIndices indices) const;
218+
216219
/// O(1) advance from @a current to the next part's indices in slot @a pos.
217220
[[nodiscard]] DataRefIndices nextIndices(int pos, DataRefIndices current) const
218221
{
@@ -745,6 +748,7 @@ class InputRecord
745748
[[nodiscard]] DataRefIndices initialIndices() const { return {0, 1}; }
746749
[[nodiscard]] DataRefIndices endIndices() const { return {size_t(-1), size_t(-1)}; }
747750
[[nodiscard]] DataRef getAtIndices(DataRefIndices idx) const { return record->getAtIndices((int)slot, idx); }
751+
[[nodiscard]] fair::mq::Message* getPayloadAtIndices(DataRefIndices idx) const { return record->getPayloadAtIndices((int)slot, idx); }
748752
[[nodiscard]] DataRefIndices nextIndices(DataRefIndices idx) const { return record->nextIndices((int)slot, idx); }
749753
[[nodiscard]] size_t size() const { return record->getNofParts((int)slot); }
750754

Framework/Core/include/Framework/InputRecordWalker.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,11 @@ class InputRecordWalker
115115
return not operator==(rh);
116116
}
117117

118+
fair::mq::Message* getPayload() const
119+
{
120+
return mCurrentRange.getPayloadAtIndices(mCurrent.indices());
121+
}
122+
118123
private:
119124
bool next(bool isInitialPart = false)
120125
{

Framework/Core/include/Framework/InputSpan.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@
1313

1414
#include "Framework/DataRef.h"
1515
#include <functional>
16+
#include <fairmq/FwdDecls.h>
1617

1718
extern template class std::function<o2::framework::DataRef(size_t, o2::framework::DataRefIndices)>;
1819
extern template class std::function<o2::framework::DataRefIndices(size_t, o2::framework::DataRefIndices)>;
20+
extern template class std::function<fair::mq::Message*(size_t, o2::framework::DataRefIndices)>;
1921

2022
namespace o2::framework
2123
{
@@ -38,6 +40,7 @@ class InputSpan
3840
std::function<int(size_t)> refCountGetter,
3941
std::function<DataRef(size_t, DataRefIndices)> indicesGetter,
4042
std::function<DataRefIndices(size_t, DataRefIndices)> nextIndicesGetter,
43+
std::function<fair::mq::Message*(size_t, DataRefIndices)> payloadGetter,
4144
size_t size);
4245

4346
/// @a i-th element of the InputSpan (O(partidx) sequential scan via indices protocol)
@@ -56,6 +59,12 @@ class InputSpan
5659
return mIndicesGetter(slotIdx, indices);
5760
}
5861

62+
/// Return the payload as fair::mq::Message* for the part described by @a indices in slot @a slotIdx
63+
[[nodiscard]] fair::mq::Message* getPayloadAtIndices(size_t slotIdx, DataRefIndices indices) const
64+
{
65+
return mPayloadGetter(slotIdx, indices);
66+
}
67+
5968
/// Advance from @a current to the indices of the next part in slot @a slotIdx in O(1).
6069
[[nodiscard]] DataRefIndices nextIndices(size_t slotIdx, DataRefIndices current) const
6170
{
@@ -179,6 +188,12 @@ class InputSpan
179188
return mCurrentIndices.headerIdx;
180189
}
181190

191+
// return current indices
192+
[[nodiscard]] DataRefIndices indices() const
193+
{
194+
return mCurrentIndices;
195+
}
196+
182197
// return an iterable range over all parts in the current slot
183198
// only available for slot-level iterators whose parent has parts(size_t)
184199
[[nodiscard]] auto parts() const
@@ -201,6 +216,7 @@ class InputSpan
201216
[[nodiscard]] DataRefIndices initialIndices() const { return {0, 1}; }
202217
[[nodiscard]] DataRefIndices endIndices() const { return {size_t(-1), size_t(-1)}; }
203218
[[nodiscard]] DataRef getAtIndices(DataRefIndices idx) const { return span->getAtIndices(slot, idx); }
219+
[[nodiscard]] fair::mq::Message* getPayloadAtIndices(DataRefIndices idx) const { return span->getPayloadAtIndices(slot, idx); }
204220
[[nodiscard]] DataRefIndices nextIndices(DataRefIndices idx) const { return span->nextIndices(slot, idx); }
205221
[[nodiscard]] size_t size() const { return span->getNofParts(slot); }
206222

@@ -230,6 +246,7 @@ class InputSpan
230246
std::function<int(size_t)> mRefCountGetter;
231247
std::function<DataRef(size_t, DataRefIndices)> mIndicesGetter;
232248
std::function<DataRefIndices(size_t, DataRefIndices)> mNextIndicesGetter;
249+
std::function<fair::mq::Message*(size_t, DataRefIndices)> mPayloadGetter;
233250
size_t mSize;
234251
};
235252

Framework/Core/src/DataAllocator.cxx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,26 @@ void DataAllocator::snapshot(const Output& spec, const char* payload, size_t pay
342342
addPartToContext(routeIndex, std::move(payloadMessage), spec, serializationMethod);
343343
}
344344

345+
void DataAllocator::forwardPayload(const Output& spec, fair::mq::Message& inputPayload,
346+
o2::header::SerializationMethod serializationMethod)
347+
{
348+
auto& proxy = mRegistry.get<FairMQDeviceProxy>();
349+
auto& timingInfo = mRegistry.get<TimingInfo>();
350+
351+
RouteIndex routeIndex = matchDataHeader(spec, timingInfo.timeslice);
352+
auto* transport = proxy.getOutputTransport(routeIndex);
353+
354+
if (inputPayload.GetTransport() == transport) {
355+
auto payloadMessage = transport->CreateMessage();
356+
payloadMessage->Copy(inputPayload);
357+
addPartToContext(routeIndex, std::move(payloadMessage), spec, serializationMethod);
358+
} else {
359+
auto payloadMessage = transport->CreateMessage(inputPayload.GetSize(), fair::mq::Alignment{64});
360+
memcpy(payloadMessage->GetData(), inputPayload.GetData(), inputPayload.GetSize());
361+
addPartToContext(routeIndex, std::move(payloadMessage), spec, serializationMethod);
362+
}
363+
}
364+
345365
Output DataAllocator::getOutputByBind(OutputRef&& ref)
346366
{
347367
if (ref.label.empty()) {

Framework/Core/src/DataProcessingDevice.cxx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2203,7 +2203,14 @@ bool DataProcessingDevice::tryDispatchComputation(ServiceRegistryRef ref, std::v
22032203
auto next = currentSetOfInputs[i] | get_next_pair{current};
22042204
return next.headerIdx < currentSetOfInputs[i].size() ? next : DataRefIndices{size_t(-1), size_t(-1)};
22052205
};
2206-
return InputSpan{nofPartsGetter, refCountGetter, indicesGetter, nextIndicesGetter, currentSetOfInputs.size()};
2206+
auto payloadGetter = [&currentSetOfInputs](size_t i, DataRefIndices current) -> fair::mq::Message* {
2207+
auto const& msgs = currentSetOfInputs[i];
2208+
if (msgs.size() <= current.payloadIdx || !msgs[current.payloadIdx]) {
2209+
return nullptr;
2210+
}
2211+
return msgs[current.payloadIdx].get();
2212+
};
2213+
return InputSpan{nofPartsGetter, refCountGetter, indicesGetter, nextIndicesGetter, payloadGetter, currentSetOfInputs.size()};
22072214
};
22082215

22092216
auto markInputsAsDone = [ref](TimesliceSlot slot) -> void {

Framework/Core/src/DataRelayer.cxx

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,14 @@ DataRelayer::ActivityStats DataRelayer::processDanglingInputs(std::vector<Expira
236236
auto next = partial[idx] | get_next_pair{current};
237237
return next.headerIdx < partial[idx].size() ? next : DataRefIndices{size_t(-1), size_t(-1)};
238238
};
239-
InputSpan span{nPartsGetter, refCountGetter, indicesGetter, nextIndicesGetter, static_cast<size_t>(partial.size())};
239+
auto payloadGetter = [&partial](size_t idx, DataRefIndices current) -> fair::mq::Message* {
240+
auto const& msgs = partial[idx];
241+
if (msgs.size() <= current.payloadIdx || !msgs[current.payloadIdx]) {
242+
return nullptr;
243+
}
244+
return msgs[current.payloadIdx].get();
245+
};
246+
InputSpan span{nPartsGetter, refCountGetter, indicesGetter, nextIndicesGetter, payloadGetter, static_cast<size_t>(partial.size())};
240247
// Setup the input span
241248

242249
if (expirator.checker(services, timestamp.value, span) == false) {
@@ -818,7 +825,14 @@ void DataRelayer::getReadyToProcess(std::vector<DataRelayer::RecordAction>& comp
818825
auto next = partial[idx] | get_next_pair{current};
819826
return next.headerIdx < partial[idx].size() ? next : DataRefIndices{size_t(-1), size_t(-1)};
820827
};
821-
InputSpan span{nPartsGetter, refCountGetter, indicesGetter, nextIndicesGetter, static_cast<size_t>(partial.size())};
828+
auto payloadGetter = [&partial](size_t idx, DataRefIndices current) -> fair::mq::Message* {
829+
auto const& msgs = partial[idx];
830+
if (msgs.size() <= current.payloadIdx || !msgs[current.payloadIdx]) {
831+
return nullptr;
832+
}
833+
return msgs[current.payloadIdx].get();
834+
};
835+
InputSpan span{nPartsGetter, refCountGetter, indicesGetter, nextIndicesGetter, payloadGetter, static_cast<size_t>(partial.size())};
822836
CompletionPolicy::CompletionOp action = mCompletionPolicy.callbackFull(span, mInputs, mContext);
823837

824838
auto& variables = mTimesliceIndex.getVariablesForSlot(slot);

Framework/Core/src/InputRecord.cxx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,11 @@ DataRef InputRecord::getAtIndices(int pos, DataRefIndices indices) const
149149
return ref;
150150
}
151151

152+
fair::mq::Message* InputRecord::getPayloadAtIndices(size_t slotIdx, DataRefIndices indices) const
153+
{
154+
return mSpan.getPayloadAtIndices(slotIdx, indices);
155+
}
156+
152157
size_t InputRecord::size() const
153158
{
154159
return mSpan.size();

Framework/Core/src/InputSpan.cxx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@
1313

1414
template class std::function<o2::framework::DataRef(size_t, o2::framework::DataRefIndices)>;
1515
template class std::function<o2::framework::DataRefIndices(size_t, o2::framework::DataRefIndices)>;
16+
template class std::function<fair::mq::Message*(size_t, o2::framework::DataRefIndices)>;
1617

1718
namespace o2::framework
1819
{
1920
InputSpan::InputSpan(std::function<size_t(size_t)> nofPartsGetter,
2021
std::function<int(size_t)> refCountGetter,
2122
std::function<DataRef(size_t, DataRefIndices)> indicesGetter,
2223
std::function<DataRefIndices(size_t, DataRefIndices)> nextIndicesGetter,
24+
std::function<fair::mq::Message*(size_t, DataRefIndices)> payloadGetter,
2325
size_t size)
24-
: mNofPartsGetter{nofPartsGetter}, mRefCountGetter(refCountGetter), mIndicesGetter{std::move(indicesGetter)}, mNextIndicesGetter{std::move(nextIndicesGetter)}, mSize{size}
26+
: mNofPartsGetter{nofPartsGetter}, mRefCountGetter(refCountGetter), mIndicesGetter{std::move(indicesGetter)}, mNextIndicesGetter{std::move(nextIndicesGetter)}, mPayloadGetter{std::move(payloadGetter)}, mSize{size}
2527
{
2628
}
2729

Framework/Core/test/benchmark_InputRecord.cxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ static void BM_InputRecordGenericGetters(benchmark::State& state)
5252
nullptr,
5353
[](size_t, DataRefIndices) { return DataRef{nullptr, nullptr, nullptr}; },
5454
[](size_t, DataRefIndices) -> DataRefIndices { return {size_t(-1), size_t(-1)}; },
55+
nullptr,
5556
0};
5657
ServiceRegistry registry;
5758
InputRecord emptyRecord(schema, span, registry);
@@ -92,6 +93,7 @@ static void BM_InputRecordGenericGetters(benchmark::State& state)
9293
nullptr,
9394
[&inputs](size_t i, DataRefIndices idx) { return DataRef{nullptr, static_cast<char const*>(inputs[2 * i + idx.headerIdx]), static_cast<char const*>(inputs[2 * i + idx.payloadIdx])}; },
9495
[](size_t, DataRefIndices) -> DataRefIndices { return {size_t(-1), size_t(-1)}; },
96+
nullptr,
9597
inputs.size() / 2};
9698
InputRecord record{schema, span2, registry};
9799

0 commit comments

Comments
 (0)