From bf2c8052f4060f47f55eea33fe6ceded6dbe0826 Mon Sep 17 00:00:00 2001 From: Tapish Date: Fri, 7 Feb 2025 16:44:21 +0100 Subject: [PATCH 1/2] Use custom tuple on host side, fix forwarding of custom tuple and add enumerated apply --- include/picongpu/plugins/binning/Binner.hpp | 10 +-- .../plugins/binning/BinningCreator.hpp | 11 ++-- .../picongpu/plugins/binning/BinningData.hpp | 18 +++--- .../plugins/binning/BinningFunctors.hpp | 11 ++-- .../plugins/binning/FilteredSpecies.hpp | 4 +- .../picongpu/plugins/binning/WriteHist.hpp | 10 +-- .../plugins/binning/axis/LinearAxis.hpp | 2 +- .../picongpu/plugins/binning/axis/LogAxis.hpp | 2 +- include/picongpu/plugins/binning/utility.hpp | 64 ++++++++++++------- 9 files changed, 77 insertions(+), 55 deletions(-) diff --git a/include/picongpu/plugins/binning/Binner.hpp b/include/picongpu/plugins/binning/Binner.hpp index 2e43a1e675..72456a4886 100644 --- a/include/picongpu/plugins/binning/Binner.hpp +++ b/include/picongpu/plugins/binning/Binner.hpp @@ -115,7 +115,7 @@ namespace picongpu { pmacc::DataSpace const nDIdx = pmacc::math::mapToND(extentsDataspace, linearTid); float_X factor = 1.; - apply( + binning::apply( [&](auto const&... binWidthsKernel) { // uses bin width for axes without dimensions as well should those be ignored? @@ -159,7 +159,7 @@ namespace picongpu std::optional<::openPMD::Series> m_series; public: - Binner(TBinningData bd, MappingDesc* cellDesc) : binningData{bd}, cellDescription{cellDesc} + Binner(TBinningData const& bd, MappingDesc* cellDesc) : binningData{bd}, cellDescription{cellDesc} { this->pluginName = "binner_" + binningData.binnerOutputName; /** @@ -186,7 +186,7 @@ namespace picongpu // Do binning for species. Writes to histBuffer if(binningData.isRegionEnabled(ParticleRegion::Bounded)) { - std::apply( + binning::apply( [&](auto const&... tupleArgs) { ((doBinningForSpecies(tupleArgs, currentStep)), ...); }, binningData.speciesTuple); } @@ -246,7 +246,7 @@ namespace picongpu this->histBuffer->getDeviceBuffer().getDataBox()); // change output dimensions - apply( + binning::apply( [&](auto const&... tupleArgs) { ((dimensionSubtraction(outputUnits, tupleArgs.units)), ...); }, binningData.axisTuple); @@ -304,7 +304,7 @@ namespace picongpu if(binningData.isRegionEnabled(ParticleRegion::Leaving)) { - std::apply( + binning::apply( [&](auto const&... tupleArgs) { (misc::ExecuteIf{}( diff --git a/include/picongpu/plugins/binning/BinningCreator.hpp b/include/picongpu/plugins/binning/BinningCreator.hpp index f94e310a5c..44cad440a3 100644 --- a/include/picongpu/plugins/binning/BinningCreator.hpp +++ b/include/picongpu/plugins/binning/BinningCreator.hpp @@ -62,11 +62,12 @@ namespace picongpu */ template auto addBinner( - std::string binnerOutputName, - TAxisTuple axisTupleObject, - TSpeciesTuple speciesTupleObject, - TDepositionData depositionData, - std::function + std::string const& binnerOutputName, + TAxisTuple const& axisTupleObject, + TSpeciesTuple const& speciesTupleObject, + TDepositionData const& depositionData, + std::function< + void(::openPMD::Series& series, ::openPMD::Iteration& iteration, ::openPMD::Mesh& mesh)> const& writeOpenPMDFunctor = [](::openPMD::Series& series, ::openPMD::Iteration& iteration, ::openPMD::Mesh& mesh) {}) -> BinningData& diff --git a/include/picongpu/plugins/binning/BinningData.hpp b/include/picongpu/plugins/binning/BinningData.hpp index 631bdb56e4..01da28cd4c 100644 --- a/include/picongpu/plugins/binning/BinningData.hpp +++ b/include/picongpu/plugins/binning/BinningData.hpp @@ -22,6 +22,7 @@ #if(ENABLE_OPENPMD == 1) # include "picongpu/plugins/binning/Axis.hpp" +# include "picongpu/plugins/binning/utility.hpp" # include "picongpu/plugins/common/openPMDDefaultExtension.hpp" # include @@ -64,7 +65,7 @@ namespace picongpu T_DepositionData depositionData; std::function writeOpenPMDFunctor; - DataSpace> axisExtentsND; + DataSpace> axisExtentsND; /* Optional parameters not initialized by constructor. * Use the return value of addBinner() to modify them if needed. */ @@ -80,10 +81,10 @@ namespace picongpu std::string jsonCfg = "{}"; BinningData( - const std::string binnerName, - const T_AxisTuple axes, - const T_SpeciesTuple species, - const T_DepositionData depositData, + std::string const& binnerName, + T_AxisTuple const& axes, + T_SpeciesTuple const& species, + T_DepositionData const& depositData, std::function writeOpenPMD) : binnerOutputName{binnerName} @@ -92,19 +93,18 @@ namespace picongpu , depositionData{depositData} , writeOpenPMDFunctor{writeOpenPMD} { - std::apply( + binning::applyEnumerate( [&](auto const&... tupleArgs) { - uint32_t i = 0; // This assumes getNBins() exists - ((axisExtentsND[i++] = tupleArgs.getNBins()), ...); + ((axisExtentsND[tupleArgs.first] = tupleArgs.second.getNBins()), ...); }, axisTuple); } static constexpr uint32_t getNAxes() { - return std::tuple_size_v; + return pmacc::memory::tuple::tuple_size_v; } /** @brief Time average the accumulated data when doing the dump. Defaults to true. */ diff --git a/include/picongpu/plugins/binning/BinningFunctors.hpp b/include/picongpu/plugins/binning/BinningFunctors.hpp index ebb057b0af..5808e913e2 100644 --- a/include/picongpu/plugins/binning/BinningFunctors.hpp +++ b/include/picongpu/plugins/binning/BinningFunctors.hpp @@ -53,19 +53,18 @@ namespace picongpu auto binsDataspace = pmacc::DataSpace{}; bool validIdx = true; - apply( + binning::applyEnumerate( [&](auto const&... tupleArgs) { - uint32_t i = 0; // This assumes n_bins and getBinIdx exist validIdx - = (( + = ( [&] { - auto [isValid, binIdx] = tupleArgs.getBinIdx(domainInfo, worker, particle); - binsDataspace[i++] = binIdx; + auto [isValid, binIdx] = tupleArgs.second.getBinIdx(domainInfo, worker, particle); + binsDataspace[tupleArgs.first] = binIdx; return isValid; - }()) + }() && ...); }, axes); diff --git a/include/picongpu/plugins/binning/FilteredSpecies.hpp b/include/picongpu/plugins/binning/FilteredSpecies.hpp index 3f3931c72a..0787f1871f 100644 --- a/include/picongpu/plugins/binning/FilteredSpecies.hpp +++ b/include/picongpu/plugins/binning/FilteredSpecies.hpp @@ -19,6 +19,8 @@ #pragma once +#include "picongpu/plugins/binning/utility.hpp" + #include namespace picongpu @@ -66,7 +68,7 @@ namespace picongpu template HDINLINE auto createSpeciesTuple(Args&&... args) { - return std::make_tuple( + return createTuple( (IsFilteredSpecies ? std::forward(args) : FilteredSpecies{std::forward(args)})...); } diff --git a/include/picongpu/plugins/binning/WriteHist.hpp b/include/picongpu/plugins/binning/WriteHist.hpp index a05d249b06..42bd54b8d0 100644 --- a/include/picongpu/plugins/binning/WriteHist.hpp +++ b/include/picongpu/plugins/binning/WriteHist.hpp @@ -56,8 +56,8 @@ namespace picongpu std::optional<::openPMD::Series>& maybe_series, OpenPMDWriteParams params, std::unique_ptr> hReducedBuffer, - T_BinningData binningData, - const std::array& outputUnits, + T_BinningData const& binningData, + std::array const& outputUnits, const uint32_t currentStep, const bool isCheckpoint = false, const uint32_t accumulateCounter = 0) @@ -138,8 +138,8 @@ namespace picongpu mesh.setGeometry(::openPMD::Mesh::Geometry::cartesian); mesh.setDataOrder(::openPMD::Mesh::DataOrder::C); - std::apply( - [&](auto&... tupleArgs) + binning::apply( + [&](auto const&... tupleArgs) { ((mesh.setAttribute(tupleArgs.label + "_bin_edges", tupleArgs.getBinEdgesSI())), ...); ((mesh.setAttribute(tupleArgs.label + "_units", tupleArgs.units)), ...); @@ -148,7 +148,7 @@ namespace picongpu std::reverse(labelVector.begin(), labelVector.end()); mesh.setAxisLabels(labelVector); }, - binningData.axisTuple); // careful no const tupleArgs + binningData.axisTuple); std::vector gridSpacingVector; std::vector gridOffsetVector; diff --git a/include/picongpu/plugins/binning/axis/LinearAxis.hpp b/include/picongpu/plugins/binning/axis/LinearAxis.hpp index 230295c1d4..9f20595d52 100644 --- a/include/picongpu/plugins/binning/axis/LinearAxis.hpp +++ b/include/picongpu/plugins/binning/axis/LinearAxis.hpp @@ -188,7 +188,7 @@ namespace picongpu /** * @return bin edges in SI units */ - std::vector getBinEdgesSI() + std::vector getBinEdgesSI() const { /** * @TODO store edges? Compute once at the beginning and store for later to print at every diff --git a/include/picongpu/plugins/binning/axis/LogAxis.hpp b/include/picongpu/plugins/binning/axis/LogAxis.hpp index 6807612502..135116da55 100644 --- a/include/picongpu/plugins/binning/axis/LogAxis.hpp +++ b/include/picongpu/plugins/binning/axis/LogAxis.hpp @@ -249,7 +249,7 @@ namespace picongpu /** * @return bin edges in SI units */ - std::vector getBinEdgesSI() + std::vector getBinEdgesSI() const { std::vector binEdges; binEdges.reserve(axisSplit.nBins + 1); diff --git a/include/picongpu/plugins/binning/utility.hpp b/include/picongpu/plugins/binning/utility.hpp index a6ae9ae2ac..1cf3e098b1 100644 --- a/include/picongpu/plugins/binning/utility.hpp +++ b/include/picongpu/plugins/binning/utility.hpp @@ -31,51 +31,71 @@ namespace picongpu { namespace detail { - template - HDINLINE constexpr auto apply_impl( + template + HDINLINE constexpr decltype(auto) applyImpl(TFunc&& f, TPmaccTuple&& t, std::index_sequence) + { + return std::forward(f)(pmacc::memory::tuple::get(std::forward(t))...); + } + + template + HDINLINE constexpr decltype(auto) applyEnumerateImpl( TFunc&& f, - pmacc::memory::tuple::Tuple&& t, + TPmaccTuple&& t, std::index_sequence) { - // @todo give Is as a param to f, so compiler has knowledge - return f(pmacc::memory::tuple::get(std::forward&&>(t))...); + return std::forward(f)(std::make_pair( + std::integral_constant{}, + pmacc::memory::tuple::get(std::forward(t)))...); } + } // namespace detail - template - HDINLINE constexpr auto apply(TFunc&& f, pmacc::memory::tuple::Tuple t) + // takes pmacc::memory::tuple::Tuple + template + HDINLINE constexpr decltype(auto) apply(TFunc&& f, TPmaccTuple&& t) + { + return detail::applyImpl( + std::forward(f), + std::forward(t), + std::make_index_sequence>{}); + } + + // takes pmacc::memory::tuple::Tuple + template + HDINLINE constexpr decltype(auto) applyEnumerate(TFunc&& f, TPmaccTuple&& t) { - return detail::apply_impl( + return detail::applyEnumerateImpl( std::forward(f), - std::forward&&>(t), - std::make_index_sequence{}); + std::forward(t), + std::make_index_sequence>{}); } namespace detail { - template - constexpr auto tupleMapHelper( - std::index_sequence, - const std::tuple& tuple, - const Functor& functor) + template + constexpr auto tupleMapHelper(std::index_sequence, TPmaccTuple&& tuple, Functor&& functor) noexcept { - return pmacc::memory::tuple::make_tuple(functor(std::get(tuple))...); + return pmacc::memory::tuple::make_tuple(std::forward(functor)( + pmacc::memory::tuple::get(std::forward(tuple)))...); } } // namespace detail /** - * @brief create an alpaka tuple from a standard tuple by applying a functor + * @brief create a new tuple from the return value of a functor applied on all arguments of a tuple */ - template - constexpr auto tupleMap(const std::tuple& tuple, const Functor& functor) + template + constexpr auto tupleMap(TPmaccTuple&& tuple, Functor&& functor) noexcept { - return detail::tupleMapHelper(std::make_index_sequence{}, tuple, functor); + return detail::tupleMapHelper( + std::make_index_sequence>{}, + std::forward(tuple), + std::forward(functor)); } template - HDINLINE auto createTuple(Args const&... args) + constexpr auto createTuple(Args&&... args) noexcept { - return std::make_tuple(args...); + return pmacc::memory::tuple::make_tuple(std::forward(args)...); } } // namespace plugins::binning From c56c5207d8d82fba6dc873255f3dad5ef42ecc8a Mon Sep 17 00:00:00 2001 From: Tapish Date: Mon, 10 Feb 2025 17:25:16 +0100 Subject: [PATCH 2/2] Switch back to host side std tuple --- include/picongpu/plugins/binning/Binner.hpp | 6 +++--- .../picongpu/plugins/binning/BinningData.hpp | 10 +++++----- .../plugins/binning/FilteredSpecies.hpp | 2 +- .../picongpu/plugins/binning/WriteHist.hpp | 2 +- include/picongpu/plugins/binning/utility.hpp | 20 ++++++++++--------- 5 files changed, 21 insertions(+), 19 deletions(-) diff --git a/include/picongpu/plugins/binning/Binner.hpp b/include/picongpu/plugins/binning/Binner.hpp index 72456a4886..d3b7a2b950 100644 --- a/include/picongpu/plugins/binning/Binner.hpp +++ b/include/picongpu/plugins/binning/Binner.hpp @@ -186,7 +186,7 @@ namespace picongpu // Do binning for species. Writes to histBuffer if(binningData.isRegionEnabled(ParticleRegion::Bounded)) { - binning::apply( + std::apply( [&](auto const&... tupleArgs) { ((doBinningForSpecies(tupleArgs, currentStep)), ...); }, binningData.speciesTuple); } @@ -246,7 +246,7 @@ namespace picongpu this->histBuffer->getDeviceBuffer().getDataBox()); // change output dimensions - binning::apply( + std::apply( [&](auto const&... tupleArgs) { ((dimensionSubtraction(outputUnits, tupleArgs.units)), ...); }, binningData.axisTuple); @@ -304,7 +304,7 @@ namespace picongpu if(binningData.isRegionEnabled(ParticleRegion::Leaving)) { - binning::apply( + std::apply( [&](auto const&... tupleArgs) { (misc::ExecuteIf{}( diff --git a/include/picongpu/plugins/binning/BinningData.hpp b/include/picongpu/plugins/binning/BinningData.hpp index 01da28cd4c..9cad6f214a 100644 --- a/include/picongpu/plugins/binning/BinningData.hpp +++ b/include/picongpu/plugins/binning/BinningData.hpp @@ -22,7 +22,6 @@ #if(ENABLE_OPENPMD == 1) # include "picongpu/plugins/binning/Axis.hpp" -# include "picongpu/plugins/binning/utility.hpp" # include "picongpu/plugins/common/openPMDDefaultExtension.hpp" # include @@ -65,7 +64,7 @@ namespace picongpu T_DepositionData depositionData; std::function writeOpenPMDFunctor; - DataSpace> axisExtentsND; + DataSpace> axisExtentsND; /* Optional parameters not initialized by constructor. * Use the return value of addBinner() to modify them if needed. */ @@ -93,18 +92,19 @@ namespace picongpu , depositionData{depositData} , writeOpenPMDFunctor{writeOpenPMD} { - binning::applyEnumerate( + std::apply( [&](auto const&... tupleArgs) { + uint32_t i = 0; // This assumes getNBins() exists - ((axisExtentsND[tupleArgs.first] = tupleArgs.second.getNBins()), ...); + ((axisExtentsND[i++] = tupleArgs.getNBins()), ...); }, axisTuple); } static constexpr uint32_t getNAxes() { - return pmacc::memory::tuple::tuple_size_v; + return std::tuple_size_v; } /** @brief Time average the accumulated data when doing the dump. Defaults to true. */ diff --git a/include/picongpu/plugins/binning/FilteredSpecies.hpp b/include/picongpu/plugins/binning/FilteredSpecies.hpp index 0787f1871f..4830fea585 100644 --- a/include/picongpu/plugins/binning/FilteredSpecies.hpp +++ b/include/picongpu/plugins/binning/FilteredSpecies.hpp @@ -66,7 +66,7 @@ namespace picongpu * a trivial AllParticle filter is used with it, which allows all particles through without filtering */ template - HDINLINE auto createSpeciesTuple(Args&&... args) + constexpr auto createSpeciesTuple(Args&&... args) { return createTuple( (IsFilteredSpecies ? std::forward(args) : FilteredSpecies{std::forward(args)})...); diff --git a/include/picongpu/plugins/binning/WriteHist.hpp b/include/picongpu/plugins/binning/WriteHist.hpp index 42bd54b8d0..c59c2d48a9 100644 --- a/include/picongpu/plugins/binning/WriteHist.hpp +++ b/include/picongpu/plugins/binning/WriteHist.hpp @@ -138,7 +138,7 @@ namespace picongpu mesh.setGeometry(::openPMD::Mesh::Geometry::cartesian); mesh.setDataOrder(::openPMD::Mesh::DataOrder::C); - binning::apply( + std::apply( [&](auto const&... tupleArgs) { ((mesh.setAttribute(tupleArgs.label + "_bin_edges", tupleArgs.getBinEdgesSI())), ...); diff --git a/include/picongpu/plugins/binning/utility.hpp b/include/picongpu/plugins/binning/utility.hpp index 1cf3e098b1..7b46630f66 100644 --- a/include/picongpu/plugins/binning/utility.hpp +++ b/include/picongpu/plugins/binning/utility.hpp @@ -72,30 +72,32 @@ namespace picongpu namespace detail { - template - constexpr auto tupleMapHelper(std::index_sequence, TPmaccTuple&& tuple, Functor&& functor) noexcept + template + constexpr auto tupleMapHelper( + std::index_sequence, + std::tuple const& tuple, + Functor&& functor) noexcept { - return pmacc::memory::tuple::make_tuple(std::forward(functor)( - pmacc::memory::tuple::get(std::forward(tuple)))...); + return pmacc::memory::tuple::make_tuple(std::forward(functor)(std::get(tuple))...); } } // namespace detail /** * @brief create a new tuple from the return value of a functor applied on all arguments of a tuple */ - template - constexpr auto tupleMap(TPmaccTuple&& tuple, Functor&& functor) noexcept + template + constexpr auto tupleMap(std::tuple const& tuple, Functor&& functor) noexcept { return detail::tupleMapHelper( - std::make_index_sequence>{}, - std::forward(tuple), + std::make_index_sequence{}, + tuple, std::forward(functor)); } template constexpr auto createTuple(Args&&... args) noexcept { - return pmacc::memory::tuple::make_tuple(std::forward(args)...); + return std::make_tuple(std::forward(args)...); } } // namespace plugins::binning