Skip to content

Add an MPISenderPortable and MPIReceiverPortable modules to send/receive arbitrary device collections#50503

Open
ghyls wants to merge 4 commits into
cms-sw:masterfrom
ghyls:devel-mpi-generic
Open

Add an MPISenderPortable and MPIReceiverPortable modules to send/receive arbitrary device collections#50503
ghyls wants to merge 4 commits into
cms-sw:masterfrom
ghyls:devel-mpi-generic

Conversation

@ghyls

@ghyls ghyls commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

PR description:

These PR includes two separate developments, one of which requires the other.

Enable the registration at runtime of DtoH and HtoD product transformations:

  • Implements the ability of registering DtoH and HtoD transformations of products whose type is not known at compile-time.
  • These changes are motivated in the context of the need for an MPI module that:
    • Is an alpaka module, and can receive products directly on device memory.
    • These products might be needed on host by downstream modules, in which case they should be converted automatically
    • The concrete type of these modules is not known at compile-time.

Add an MPISenderPortable and MPIReceiverPortable modules to send/receive device collections

  • Introduce MPISenderPortable.cc and MPIReceiverPortable.cc, which can send/receive device runtime-typed device collections for which a device TrivialSerialiser plugin exists, directly to/from device memory.

PR validation:

  • A GenericClonerPortable test module is introduced to demonstrate the D to H and H to D transformation registrations at runtime. The module clones a host or a device product and registers the H to D (or D to H) transformation for it. The test is configured via testGenericClonerDevice.py

  • A small test is added to FWCore/Framework/test/stream_producer_catch2.cc to test the non-templated registerTransformAsync overload added to Framework/interface/stream/implementors.h.

  • The Portable MPI modules (MPISenderPortable.cc and MPIReceiverPortable.cc) are tested via the two new configurations added to HeterogeneousCore/MPICore/test.

Backport

  • We plan to backport this PR to 16_0_X and 16_1_X for it to be used in the NGT demonstrator during data taking this year.

@cmsbuild

cmsbuild commented Mar 24, 2026

Copy link
Copy Markdown
Contributor

cms-bot internal usage

@cmsbuild

Copy link
Copy Markdown
Contributor

+code-checks

Logs: https://cmssdt.cern.ch/SDT/code-checks/cms-sw-PR-50503/48670

@cmsbuild

cmsbuild commented Apr 4, 2026

Copy link
Copy Markdown
Contributor

Milestone for this pull request has been moved to CMSSW_17_0_X. Please open a backport if it should also go in to CMSSW_16_1_X.

@fwyzard

fwyzard commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

please test

Comment on lines +164 to +165
"On the synchronous CPU backend, only types whose CopyToHost<T>::copyAsync returns T itself are "
"supported.");

@makortel makortel Jun 18, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really the condition though at this level of abstraction, right? I think we even have the CopyToHost<T> not being specialized for PortableHostCollection, so strictly speaking there is no copyAsync() that would return itself. How about

Suggested change
"On the synchronous CPU backend, only types whose CopyToHost<T>::copyAsync returns T itself are "
"supported.");
"On the synchronous CPU backend, the host and device product types must be the same.");

or more generic

Suggested change
"On the synchronous CPU backend, only types whose CopyToHost<T>::copyAsync returns T itself are "
"supported.");
"On a backend where host data products are used directly on the device, the host and device product types must be the same.");

?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Thanks for the suggestions. Just changed it.

@cmsbuild

Copy link
Copy Markdown
Contributor

+1

Size: This PR adds an extra 16KB to repository
Summary: https://cmssdt.cern.ch/SDT/jenkins-artifacts/pull-request-integration/PR-73c3b9/54084/summary.html
COMMIT: f68a893
CMSSW: CMSSW_20_1_X_2026-06-18-1100/el9_amd64_gcc13
User test area: For local testing, you can use /cvmfs/cms-ci.cern.ch/week0/cms-sw/cmssw/50503/54084/install.sh to create a dev area with all the needed externals and cmssw changes.

Comparison Summary

Summary:

  • No significant changes to the logs found
  • Reco comparison results: 4 differences found in the comparisons
  • DQMHistoTests: Total files compared: 47
  • DQMHistoTests: Total histograms compared: 3648276
  • DQMHistoTests: Total failures: 23
  • DQMHistoTests: Total nulls: 0
  • DQMHistoTests: Total successes: 3648235
  • DQMHistoTests: Total skipped: 18
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 46 files compared)
  • Checked 203 log files, 173 edm output root files, 47 DQM output files

Comment on lines +142 to +147
} else {
return nullptr;
}
} else {
return nullptr;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be simplified as

Suggested change
} else {
return nullptr;
}
} else {
return nullptr;
}
}
}
return nullptr;

?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On second thought, rather than using if constexpr to make the function return nullptr if the conditions are not met, can it be replaced by requires so that the method is simply not available ?

Comment on lines +24 to +35
// The plugin is registered under two keys:
//
// 1. mangled typeid name of TYPE_HOST: used to look up the device serialiser
// for a host type.
// 2. EDM_STRINGIZE(TYPE_DEVICE): used to look up the device serialiser
#define DEFINE_TRIVIAL_SERIALISER_PORTABLE_PLUGIN(TYPE_HOST, TYPE_DEVICE) \
DEFINE_EDM_PLUGIN(ALPAKA_ACCELERATOR_NAMESPACE::ngt::SerialiserFactoryDevice, \
ALPAKA_ACCELERATOR_NAMESPACE::ngt::Serialiser<ALPAKA_ACCELERATOR_NAMESPACE::TYPE_DEVICE>, \
typeid(TYPE_HOST).name()); \
DEFINE_EDM_PLUGIN2(ALPAKA_ACCELERATOR_NAMESPACE::ngt::SerialiserFactoryDevice, \
ALPAKA_ACCELERATOR_NAMESPACE::ngt::Serialiser<ALPAKA_ACCELERATOR_NAMESPACE::TYPE_DEVICE>, \
EDM_STRINGIZE(TYPE_DEVICE))

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand why we need two names, and specifically these two names.
Can we not use simply the mangled names for both ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was using EDM_STRINGIZE(TYPE_DEVICE) because just changing that to typeid(ALPAKA_ACCELERATOR_NAMESPACE::TYPE_DEVICE).name() would lead to the "host" version of the type being registered twice when the device is the CPU: Once by DEFINE_EDM_PLUGIN, and another by DEFINE_EDM_PLUGIN2.

Making the TYPE_DEVICE version registered only on the GPU backend solved this issue.

@@ -3,9 +3,9 @@
#include <catch2/catch_all.hpp>

#include <Eigen/Dense>
#include <string>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you move the std headers at the top ?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ping on this request.

@cmsbuild

Copy link
Copy Markdown
Contributor

@cmsbuild

Copy link
Copy Markdown
Contributor

+code-checks

Logs: https://cmssdt.cern.ch/SDT/code-checks/cms-sw-PR-50503/49990

@cmsbuild

Copy link
Copy Markdown
Contributor

Pull request #50503 was updated. @Dr15Jones, @Moanwar, @civanch, @cmsbuild, @fwyzard, @jfernan2, @kpedro88, @makortel, @mandrenguyen, @mdhildreth, @smuzaffar, @srimanob can you please check and sign again.

@fwyzard

fwyzard commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

please test

@cmsbuild

Copy link
Copy Markdown
Contributor

-1

Failed Tests: UnitTests
Size: This PR adds an extra 28KB to repository
Summary: https://cmssdt.cern.ch/SDT/jenkins-artifacts/pull-request-integration/PR-73c3b9/54351/summary.html
COMMIT: d04af20
CMSSW: CMSSW_20_1_X_2026-06-28-0000/el9_amd64_gcc13
User test area: For local testing, you can use /cvmfs/cms-ci.cern.ch/week0/cms-sw/cmssw/50503/54351/install.sh to create a dev area with all the needed externals and cmssw changes.

Failed Unit Tests

I found 2 errors in the following unit tests:

---> test TestHeterogeneousCoreTrivialSerialisationGenericClonerPortable had ERRORS
---> test testMPISoADeviceTransfer had ERRORS

Comparison Summary

Summary:

  • No significant changes to the logs found
  • Reco comparison results: 0 differences found in the comparisons
  • DQMHistoTests: Total files compared: 47
  • DQMHistoTests: Total histograms compared: 3648276
  • DQMHistoTests: Total failures: 61
  • DQMHistoTests: Total nulls: 0
  • DQMHistoTests: Total successes: 3648197
  • DQMHistoTests: Total skipped: 18
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 46 files compared)
  • Checked 203 log files, 173 edm output root files, 47 DQM output files
  • TriggerResults: no differences found

@fwyzard

fwyzard commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

please test

To refresh the tests and get a test area with the latest UCX library.

@cmsbuild

cmsbuild commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

-1

Failed Tests: UnitTests
Size: This PR adds an extra 16KB to repository
Summary: https://cmssdt.cern.ch/SDT/jenkins-artifacts/pull-request-integration/PR-73c3b9/54452/summary.html
COMMIT: d04af20
CMSSW: CMSSW_20_1_X_2026-07-01-1100/el9_amd64_gcc13
User test area: For local testing, you can use /cvmfs/cms-ci.cern.ch/week0/cms-sw/cmssw/50503/54452/install.sh to create a dev area with all the needed externals and cmssw changes.

Failed Unit Tests

I found 2 errors in the following unit tests:

---> test TestHeterogeneousCoreTrivialSerialisationGenericClonerPortable had ERRORS
---> test testMPISoADeviceTransfer had ERRORS

Comparison Summary

Summary:

  • You potentially added 4 lines to the logs
  • Reco comparison results: 4 differences found in the comparisons
  • DQMHistoTests: Total files compared: 47
  • DQMHistoTests: Total histograms compared: 3648276
  • DQMHistoTests: Total failures: 22
  • DQMHistoTests: Total nulls: 0
  • DQMHistoTests: Total successes: 3648236
  • DQMHistoTests: Total skipped: 18
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 46 files compared)
  • Checked 203 log files, 173 edm output root files, 47 DQM output files
  • TriggerResults: no differences found

@cmsbuild

cmsbuild commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

-code-checks

Logs: https://cmssdt.cern.ch/SDT/code-checks/cms-sw-PR-50503/50126

Code check has found code style and quality issues which could be resolved by applying following patch(s)

@cmsbuild

Copy link
Copy Markdown
Contributor

+code-checks

Logs: https://cmssdt.cern.ch/SDT/code-checks/cms-sw-PR-50503/50182

@cmsbuild

Copy link
Copy Markdown
Contributor

Pull request #50503 was updated. @Dr15Jones, @Moanwar, @civanch, @cmsbuild, @fwyzard, @jfernan2, @kpedro88, @makortel, @mandrenguyen, @mdhildreth, @smuzaffar, @srimanob can you please check and sign again.

@fwyzard

fwyzard commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

please test

@cmsbuild

Copy link
Copy Markdown
Contributor

+1

Size: This PR adds an extra 128KB to repository
Summary: https://cmssdt.cern.ch/SDT/jenkins-artifacts/pull-request-integration/PR-73c3b9/54730/summary.html
COMMIT: 416cf97
CMSSW: CMSSW_20_1_X_2026-07-13-1100/el9_amd64_gcc13
User test area: For local testing, you can use /cvmfs/cms-ci.cern.ch/week0/cms-sw/cmssw/50503/54730/install.sh to create a dev area with all the needed externals and cmssw changes.

Comparison Summary

Summary:

  • No significant changes to the logs found
  • Reco comparison results: 0 differences found in the comparisons
  • DQMHistoTests: Total files compared: 47
  • DQMHistoTests: Total histograms compared: 3792433
  • DQMHistoTests: Total failures: 66
  • DQMHistoTests: Total nulls: 0
  • DQMHistoTests: Total successes: 3792349
  • DQMHistoTests: Total skipped: 18
  • DQMHistoTests: Total Missing objects: 0
  • DQMHistoSizes: Histogram memory added: 0.0 KiB( 46 files compared)
  • Checked 203 log files, 173 edm output root files, 47 DQM output files
  • TriggerResults: no differences found

@fwyzard

fwyzard commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

enable gpu

@fwyzard

fwyzard commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

please test


<test name="TestHeterogeneousCoreTrivialSerialisationGenericCloner" command="cmsRun ${LOCALTOP}/src/HeterogeneousCore/TrivialSerialisation/test/testGenericCloner_cfg.py"/>
<test name="TestHeterogeneousCoreTrivialSerialisationGenericClonerHost" command="cmsRun ${LOCALTOP}/src/HeterogeneousCore/TrivialSerialisation/test/testGenericClonerHost_cfg.py"/>
<test name="TestHeterogeneousCoreTrivialSerialisationGenericClonerPortable" command="cmsRun ${LOCALTOP}/src/HeterogeneousCore/TrivialSerialisation/test/testGenericClonerPortable_cfg.py"/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test runs only for the default back-end, it does not for any alpaka backends.

I think to run on all backends you need

Suggested change
<test name="TestHeterogeneousCoreTrivialSerialisationGenericClonerPortable" command="cmsRun ${LOCALTOP}/src/HeterogeneousCore/TrivialSerialisation/test/testGenericClonerPortable_cfg.py"/>
<test name="TestHeterogeneousCoreTrivialSerialisationGenericClonerPortable" command="cmsRun ${LOCALTOP}/src/HeterogeneousCore/TrivialSerialisation/test/testGenericClonerPortable_cfg.py">
<!-- dependence and flag only to trigger the unit test for each Alpaka backend -->
<use name="alpaka"/>
<flags ALPAKA_BACKENDS="1"/>
</test>

"copyAsync must take (Queue&, edm::WrapperBase const&) and return std::any");
static_assert(std::is_same_v<std::invoke_result_t<TTransform, std::any&, std::shared_ptr<EDMetadata>>,
std::unique_ptr<edm::WrapperBase>>,
"transform must take (std::any& and std::shared_ptr<EDMetadata>) and return "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"transform must take (std::any& and std::shared_ptr<EDMetadata>) and return "
"transform must take (std::any&, std::shared_ptr<EDMetadata>) and return "

for consistency with the previous message.

// product is a device product. Types without this suffix are resolved
// as host or ROOT types.
static std::string const kAlpakaNamespacePlaceholder = "ALPAKA_ACCELERATOR_NAMESPACE::";
bool const isDeviceType = type.compare(0, kAlpakaNamespacePlaceholder.size(), kAlpakaNamespacePlaceholder) == 0;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ALPAKA_ACCELERATOR_NAMESPACE is not necessarily at the beginning, and can be present more than once.
The code should search for that string anywhere in the type, and replace all instances with the actual backend namespace.

continue;
}

// Check 2: Lookup a host serialiser registered in the host

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a portable serialiser for a host product?

edm::TypeWithDict wrappedTwd = edm::TypeWithDict::byName("edm::Wrapper<" + bareType + ">");
LogDebug("MPISenderPortable") << "looking for ROOT serialisation of type \"" << type << "\"";
if (!twd || !wrappedTwd.getClass()) {
throw cms::Exception("MPISenderPortable")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You also need to check if the type that the type is not transient.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants