From b637e7079d332a4d5b0ec33f39589a1edfe0ce1a Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Thu, 25 Sep 2025 09:19:40 +0200 Subject: [PATCH 1/2] [ntuple] Improve documentation of RNTupleParallelWriter --- tree/ntuple/inc/ROOT/RNTupleFillContext.hxx | 2 +- tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx | 6 ++-- .../ntuple/inc/ROOT/RNTupleParallelWriter.hxx | 31 +++++++++++-------- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx b/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx index a81c8af1e5293..1f151f9405ffd 100644 --- a/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx @@ -172,7 +172,7 @@ public: void EnableMetrics() { fMetrics.Enable(); } const Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; } -}; // class RNTupleFillContext +}; } // namespace Experimental } // namespace ROOT diff --git a/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx b/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx index b22a2d097b434..dc334e44f49df 100644 --- a/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx @@ -30,8 +30,8 @@ class RNTupleFillContext; \ingroup NTuple \brief A status object after filling an entry -After passing an instance to RNTupleWriter::FillNoFlush or RNTupleFillContext::FillNoFlush, the caller must check -ShouldFlushCluster and call RNTupleWriter::FlushCluster or RNTupleFillContext::FlushCluster if necessary. +After passing an instance to RNTupleWriter::FillNoFlush() or RNTupleFillContext::FillNoFlush(), the caller must check +ShouldFlushCluster() and call RNTupleWriter::FlushCluster() or RNTupleFillContext::FlushCluster() if necessary. */ // clang-format on class RNTupleFillStatus { @@ -55,7 +55,7 @@ public: std::size_t GetLastEntrySize() const { return fLastEntrySize; } /// Return true if the caller should call FlushCluster. bool ShouldFlushCluster() const { return fShouldFlushCluster; } -}; // class RNTupleFillContext +}; } // namespace ROOT diff --git a/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx b/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx index e590563bcaf02..333065562df5e 100644 --- a/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx @@ -44,20 +44,19 @@ class RNTupleFillContext; \brief A writer to fill an RNTuple from multiple contexts Compared to the sequential RNTupleWriter, a parallel writer enables the creation of multiple RNTupleFillContext (see -RNTupleParallelWriter::CreateFillContext). Each fill context prepares independent clusters that are appended to the -common ntuple with internal synchronization. Before destruction, all fill contexts must have flushed their data and -been destroyed (or data could be lost!). +CreateFillContext()). Each fill context prepares independent clusters that are appended to the common RNTuple with +internal synchronization. Before destruction, all fill contexts must have flushed their data and been destroyed (or +data could be lost!). -For user convenience, RNTupleParallelWriter::CreateFillContext is thread-safe and may be called from multiple threads -in parallel at any time, also after some data has already been written. Internally, the original model is cloned and -ownership is passed to a newly created RNTupleFillContext. For that reason, it is recommended to use -RNTupleModel::CreateBare when creating the model for parallel writing and avoid the allocation of a useless default -REntry per context. +For user convenience, CreateFillContext() is thread-safe and may be called from multiple threads in parallel at any +time, also after some data has already been written. Internally, the original model is cloned and ownership is passed +to a newly created RNTupleFillContext. For that reason, it is recommended to use RNTupleModel::CreateBare when creating +the model for parallel writing and avoid the allocation of a useless default REntry per context. Note that the sequence of independently prepared clusters is indeterminate and therefore entries are only partially ordered: Entries from one context are totally ordered as they were filled. However, there is no orderering with other -contexts and the entries may be appended to the ntuple either before or after other entries written in parallel into -other contexts. In addition, two consecutive entries in one fill context can end up separated in the final ntuple, if +contexts and the entries may be appended to the RNTuple either before or after other entries written in parallel into +other contexts. In addition, two consecutive entries in one fill context can end up separated in the final RNTuple, if they happen to fall onto a cluster boundary and other contexts append more entries before the next cluster is full. At the moment, the parallel writer does not (yet) support incremental updates of the underlying model. Please refer to @@ -82,11 +81,17 @@ private: RNTupleParallelWriter &operator=(const RNTupleParallelWriter &) = delete; public: - /// Recreate a new file and return a writer to write an ntuple. + /// Recreate a new file and return a writer to write an RNTuple. static std::unique_ptr Recreate(std::unique_ptr model, std::string_view ntupleName, std::string_view storage, const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions()); - /// Append an ntuple to the existing file, which must not be accessed while data is filled into any created context. + /// Append an RNTuple to the existing file. + /// + /// While the writer synchronizes between multiple fill contexts created from the same writer, there is no + /// synchronization with other writers or other clients that write into the same file. The caller must ensure that + /// the underlying file is not be accessed while data is filled into any created context. To improve performance, it + /// is allowed to use special methods that are guaranteed to not interact with the underlying file, such as + /// RNTupleFillContext::FillNoFlush(). static std::unique_ptr Append(std::unique_ptr model, std::string_view ntupleName, TDirectory &fileOrDirectory, const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions()); @@ -97,7 +102,7 @@ public: /// thread-safe and may be called from multiple threads in parallel at any time, also after some data has already /// been written. /// - /// Note that all fill contexts must be destroyed before RNTupleParallelWriter::CommitDataset() is called. + /// Note that all fill contexts must be destroyed before CommitDataset() is called. std::shared_ptr CreateFillContext(); /// Automatically called by the destructor From f966c868ce9937d025a18d44344beb0f97a07ac0 Mon Sep 17 00:00:00 2001 From: Jonas Hahnfeld Date: Thu, 25 Sep 2025 09:34:53 +0200 Subject: [PATCH 2/2] [ntuple] Move RNTupleParallelWriter out of Experimental --- README/ReleaseNotes/v638/index.md | 4 +++ .../inc/ROOT/RDF/SnapshotHelpers.hxx | 10 +++---- tree/dataframe/src/RDFSnapshotHelpers.cxx | 2 +- tree/ntuple/inc/ROOT/REntry.hxx | 4 +-- tree/ntuple/inc/ROOT/RNTupleFillContext.hxx | 16 +++++------- tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx | 4 +-- .../ntuple/inc/ROOT/RNTupleParallelWriter.hxx | 11 +++----- tree/ntuple/inc/ROOT/RNTupleWriter.hxx | 2 +- tree/ntuple/inc/ROOT/RRawPtrWriteEntry.hxx | 5 ++-- tree/ntuple/src/RNTupleFillContext.cxx | 14 +++++----- tree/ntuple/src/RNTupleParallelWriter.cxx | 26 ++++++++----------- tree/ntuple/test/ntuple_test.hxx | 2 +- tutorials/io/ntuple/ntpl009_parallelWriter.C | 10 ++----- tutorials/io/ntuple/ntpl013_staged.C | 14 +++------- tutorials/io/ntuple/ntpl014_framework.C | 11 ++++---- 15 files changed, 53 insertions(+), 82 deletions(-) diff --git a/README/ReleaseNotes/v638/index.md b/README/ReleaseNotes/v638/index.md index d5e749d14507b..d391c89d78102 100644 --- a/README/ReleaseNotes/v638/index.md +++ b/README/ReleaseNotes/v638/index.md @@ -56,6 +56,10 @@ The following people have contributed to this new version: * Behaviour change: the behaviour of `TChain::SetBranchStatus` has been aligned to the one of `TTree::SetBranchStatus`. In particular, when `SetBranchStatus` is called to deactivate all branches, a subsequent call to `TChain::SetBranchAddress` would override the previous instruction and activate that single branch. Instead `TTree::SetBranchAddress` respects the rule imposed by `SetBranchStatus`. If a user needs to activate only one or more branches, they should call `SetBranchStatus("brName", true)` on each branch that needs to be active in the TChain, like it was already necessary for a TTree. See https://github.com/root-project/root/pull/19221 for more details. +### RNTuple + +* The parallel writer is now part of the public, stable API. The `RNTupleParallelWriter` and the closely related `RNTupleFillContext` moved from the `ROOT::Experimental` to the `ROOT` namespace. + ## Math ### Minuit2 diff --git a/tree/dataframe/inc/ROOT/RDF/SnapshotHelpers.hxx b/tree/dataframe/inc/ROOT/RDF/SnapshotHelpers.hxx index f542d33ad3aef..92eae3b36be96 100644 --- a/tree/dataframe/inc/ROOT/RDF/SnapshotHelpers.hxx +++ b/tree/dataframe/inc/ROOT/RDF/SnapshotHelpers.hxx @@ -30,12 +30,10 @@ class TBranch; class TFile; namespace ROOT { -namespace Experimental { -class RNTupleFillContext; -class RNTupleParallelWriter; -} // namespace Experimental class REntry; class RFieldToken; +class RNTupleFillContext; +class RNTupleParallelWriter; class TBufferMerger; class TBufferMergerFile; } // namespace ROOT @@ -54,11 +52,11 @@ class R__CLING_PTRCHECK(off) UntypedSnapshotRNTupleHelper final : public RAction ROOT::Detail::RDF::RLoopManager *fOutputLoopManager; ColumnNames_t fInputFieldNames; // This contains the resolved aliases ColumnNames_t fOutputFieldNames; - std::unique_ptr fWriter; + std::unique_ptr fWriter; std::vector fFieldTokens; unsigned int fNSlots; - std::vector> fFillContexts; + std::vector> fFillContexts; std::vector> fEntries; std::vector fInputColumnTypeIDs; // Types for the input columns diff --git a/tree/dataframe/src/RDFSnapshotHelpers.cxx b/tree/dataframe/src/RDFSnapshotHelpers.cxx index 4374b4261d4a3..f464763440965 100644 --- a/tree/dataframe/src/RDFSnapshotHelpers.cxx +++ b/tree/dataframe/src/RDFSnapshotHelpers.cxx @@ -871,7 +871,7 @@ void ROOT::Internal::RDF::UntypedSnapshotRNTupleHelper::Initialize() // The RNTupleParallelWriter has exclusive access to the underlying TFile, no further synchronization is needed for // calls to Fill() (in Exec) and FlushCluster() (in FinalizeTask). - fWriter = ROOT::Experimental::RNTupleParallelWriter::Append(std::move(model), fNTupleName, *outputDir, writeOptions); + fWriter = ROOT::RNTupleParallelWriter::Append(std::move(model), fNTupleName, *outputDir, writeOptions); } void ROOT::Internal::RDF::UntypedSnapshotRNTupleHelper::InitTask(TTreeReader *, unsigned int slot) diff --git a/tree/ntuple/inc/ROOT/REntry.hxx b/tree/ntuple/inc/ROOT/REntry.hxx index c740227c34d67..5b9acada288f6 100644 --- a/tree/ntuple/inc/ROOT/REntry.hxx +++ b/tree/ntuple/inc/ROOT/REntry.hxx @@ -31,10 +31,10 @@ namespace ROOT { +class RNTupleFillContext; class RNTupleReader; namespace Experimental { -class RNTupleFillContext; class RNTupleProcessor; class RNTupleSingleProcessor; class RNTupleChainProcessor; @@ -52,9 +52,9 @@ with values are managed through shared pointers. */ // clang-format on class REntry { + friend class RNTupleFillContext; friend class RNTupleModel; friend class RNTupleReader; - friend class Experimental::RNTupleFillContext; friend class Experimental::RNTupleProcessor; friend class Experimental::RNTupleSingleProcessor; friend class Experimental::RNTupleChainProcessor; diff --git a/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx b/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx index 1f151f9405ffd..0737cfd827cd8 100644 --- a/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleFillContext.hxx @@ -2,8 +2,6 @@ /// \ingroup NTuple /// \author Jakob Blomer /// \date 2024-02-22 -/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback -/// is welcome! /************************************************************************* * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. * @@ -32,11 +30,10 @@ #include namespace ROOT { -namespace Experimental { // clang-format off /** -\class ROOT::Experimental::RNTupleFillContext +\class ROOT::RNTupleFillContext \ingroup NTuple \brief A context for filling entries (data) into clusters of an RNTuple @@ -61,7 +58,7 @@ private: /// Needs to be destructed before fSink std::unique_ptr fModel; - Detail::RNTupleMetrics fMetrics; + Experimental::Detail::RNTupleMetrics fMetrics; ROOT::NTupleSize_t fLastFlushed = 0; ROOT::NTupleSize_t fNEntries = 0; @@ -132,14 +129,14 @@ public: /// /// This method will check the entry's model ID to ensure it comes from the context's own model or throw an exception /// otherwise. - void FillNoFlush(Detail::RRawPtrWriteEntry &entry, ROOT::RNTupleFillStatus &status) + void FillNoFlush(Experimental::Detail::RRawPtrWriteEntry &entry, ROOT::RNTupleFillStatus &status) { FillNoFlushImpl(entry, status); } /// Fill an RRawPtrWriteEntry into this context. This method will check the entry's model ID to ensure it comes /// from the context's own model or throw an exception otherwise. /// \return The number of uncompressed bytes written. - std::size_t Fill(Detail::RRawPtrWriteEntry &entry) { return FillImpl(entry); } + std::size_t Fill(Experimental::Detail::RRawPtrWriteEntry &entry) { return FillImpl(entry); } /// Flush column data, preparing for CommitCluster or to reduce memory usage. This will trigger compression of pages, /// but not actually write to storage. @@ -151,7 +148,7 @@ public: const ROOT::RNTupleModel &GetModel() const { return *fModel; } std::unique_ptr CreateEntry() const { return fModel->CreateEntry(); } - std::unique_ptr CreateRawPtrWriteEntry() const + std::unique_ptr CreateRawPtrWriteEntry() const { return fModel->CreateRawPtrWriteEntry(); } @@ -171,10 +168,9 @@ public: bool IsStagedClusterCommittingEnabled() const { return fStagedClusterCommitting; } void EnableMetrics() { fMetrics.Enable(); } - const Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; } + const Experimental::Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; } }; -} // namespace Experimental } // namespace ROOT #endif // ROOT_RNTupleFillContext diff --git a/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx b/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx index dc334e44f49df..6ff249e6e9179 100644 --- a/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleFillStatus.hxx @@ -20,9 +20,7 @@ namespace ROOT { -namespace Experimental { class RNTupleFillContext; -} // clang-format off /** @@ -35,7 +33,7 @@ ShouldFlushCluster() and call RNTupleWriter::FlushCluster() or RNTupleFillContex */ // clang-format on class RNTupleFillStatus { - friend class Experimental::RNTupleFillContext; + friend class RNTupleFillContext; private: /// Number of entries written into the current cluster diff --git a/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx b/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx index 333065562df5e..26e586ee4d1cf 100644 --- a/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleParallelWriter.hxx @@ -2,8 +2,6 @@ /// \ingroup NTuple /// \author Jonas Hahnfeld /// \date 2024-02-01 -/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback -/// is welcome! /************************************************************************* * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. * @@ -34,12 +32,10 @@ namespace Internal { class RPageSink; } // namespace Internal -namespace Experimental { - class RNTupleFillContext; /** -\class ROOT::Experimental::RNTupleParallelWriter +\class ROOT::RNTupleParallelWriter \ingroup NTuple \brief A writer to fill an RNTuple from multiple contexts @@ -72,7 +68,7 @@ private: std::unique_ptr fSink; /// The original RNTupleModel connected to fSink; needs to be destructed before it. std::unique_ptr fModel; - Detail::RNTupleMetrics fMetrics; + Experimental::Detail::RNTupleMetrics fMetrics; /// List of all created helpers. They must be destroyed before this RNTupleParallelWriter is destructed. std::vector> fFillContexts; @@ -109,10 +105,9 @@ public: void CommitDataset(); void EnableMetrics() { fMetrics.Enable(); } - const Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; } + const Experimental::Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; } }; -} // namespace Experimental } // namespace ROOT #endif diff --git a/tree/ntuple/inc/ROOT/RNTupleWriter.hxx b/tree/ntuple/inc/ROOT/RNTupleWriter.hxx index a771345486a46..c80d17bb84c0b 100644 --- a/tree/ntuple/inc/ROOT/RNTupleWriter.hxx +++ b/tree/ntuple/inc/ROOT/RNTupleWriter.hxx @@ -104,7 +104,7 @@ class RNTupleWriter { Internal::CreateRNTupleWriter(std::unique_ptr, std::unique_ptr); private: - Experimental::RNTupleFillContext fFillContext; + RNTupleFillContext fFillContext; Experimental::Detail::RNTupleMetrics fMetrics; ROOT::NTupleSize_t fLastCommittedClusterGroup = 0; diff --git a/tree/ntuple/inc/ROOT/RRawPtrWriteEntry.hxx b/tree/ntuple/inc/ROOT/RRawPtrWriteEntry.hxx index d0c70672d437a..ea941f7bbcdb4 100644 --- a/tree/ntuple/inc/ROOT/RRawPtrWriteEntry.hxx +++ b/tree/ntuple/inc/ROOT/RRawPtrWriteEntry.hxx @@ -28,10 +28,9 @@ namespace ROOT { class RNTupleModel; -namespace Experimental { - class RNTupleFillContext; +namespace Experimental { namespace Detail { // clang-format off @@ -46,7 +45,7 @@ provided by REntry, with safe interfaces, type checks, and shared object ownersh // clang-format on class RRawPtrWriteEntry { friend class ROOT::RNTupleModel; - friend class ROOT::Experimental::RNTupleFillContext; + friend class ROOT::RNTupleFillContext; private: /// The entry must be linked to a specific model, identified by a model ID diff --git a/tree/ntuple/src/RNTupleFillContext.cxx b/tree/ntuple/src/RNTupleFillContext.cxx index 6ba8504268ddd..825451f849ae5 100644 --- a/tree/ntuple/src/RNTupleFillContext.cxx +++ b/tree/ntuple/src/RNTupleFillContext.cxx @@ -2,8 +2,6 @@ /// \ingroup NTuple /// \author Jakob Blomer /// \date 2024-02-22 -/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback -/// is welcome! /************************************************************************* * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. * @@ -27,8 +25,8 @@ #include #include -ROOT::Experimental::RNTupleFillContext::RNTupleFillContext(std::unique_ptr model, - std::unique_ptr sink) +ROOT::RNTupleFillContext::RNTupleFillContext(std::unique_ptr model, + std::unique_ptr sink) : fSink(std::move(sink)), fModel(std::move(model)), fMetrics("RNTupleFillContext") { fModel->Freeze(); @@ -42,7 +40,7 @@ ROOT::Experimental::RNTupleFillContext::RNTupleFillContext(std::unique_ptr /// \date 2024-02-01 -/// \warning This is part of the ROOT 7 prototype! It will change without notice. It might trigger earthquakes. Feedback -/// is welcome! /************************************************************************* * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. * @@ -119,8 +117,8 @@ class RPageSynchronizingSink : public RPageSink { } // namespace -ROOT::Experimental::RNTupleParallelWriter::RNTupleParallelWriter(std::unique_ptr model, - std::unique_ptr sink) +ROOT::RNTupleParallelWriter::RNTupleParallelWriter(std::unique_ptr model, + std::unique_ptr sink) : fSink(std::move(sink)), fModel(std::move(model)), fMetrics("RNTupleParallelWriter") { if (fModel->GetRegisteredSubfieldNames().size() > 0) { @@ -131,7 +129,7 @@ ROOT::Experimental::RNTupleParallelWriter::RNTupleParallelWriter(std::unique_ptr fMetrics.ObserveMetrics(fSink->GetMetrics()); } -ROOT::Experimental::RNTupleParallelWriter::~RNTupleParallelWriter() +ROOT::RNTupleParallelWriter::~RNTupleParallelWriter() { try { CommitDataset(); @@ -140,7 +138,7 @@ ROOT::Experimental::RNTupleParallelWriter::~RNTupleParallelWriter() } } -void ROOT::Experimental::RNTupleParallelWriter::CommitDataset() +void ROOT::RNTupleParallelWriter::CommitDataset() { if (fModel->IsExpired()) return; @@ -157,10 +155,9 @@ void ROOT::Experimental::RNTupleParallelWriter::CommitDataset() fModel->Expire(); } -std::unique_ptr -ROOT::Experimental::RNTupleParallelWriter::Recreate(std::unique_ptr model, - std::string_view ntupleName, std::string_view storage, - const ROOT::RNTupleWriteOptions &options) +std::unique_ptr +ROOT::RNTupleParallelWriter::Recreate(std::unique_ptr model, std::string_view ntupleName, + std::string_view storage, const ROOT::RNTupleWriteOptions &options) { if (!options.GetUseBufferedWrite()) { throw RException(R__FAIL("parallel writing requires buffering")); @@ -171,10 +168,9 @@ ROOT::Experimental::RNTupleParallelWriter::Recreate(std::unique_ptr(new RNTupleParallelWriter(std::move(model), std::move(sink))); } -std::unique_ptr -ROOT::Experimental::RNTupleParallelWriter::Append(std::unique_ptr model, - std::string_view ntupleName, TDirectory &fileOrDirectory, - const ROOT::RNTupleWriteOptions &options) +std::unique_ptr +ROOT::RNTupleParallelWriter::Append(std::unique_ptr model, std::string_view ntupleName, + TDirectory &fileOrDirectory, const ROOT::RNTupleWriteOptions &options) { auto file = fileOrDirectory.GetFile(); if (!file) { @@ -195,7 +191,7 @@ ROOT::Experimental::RNTupleParallelWriter::Append(std::unique_ptr(new RNTupleParallelWriter(std::move(model), std::move(sink))); } -std::shared_ptr ROOT::Experimental::RNTupleParallelWriter::CreateFillContext() +std::shared_ptr ROOT::RNTupleParallelWriter::CreateFillContext() { std::lock_guard g(fMutex); diff --git a/tree/ntuple/test/ntuple_test.hxx b/tree/ntuple/test/ntuple_test.hxx index a4180b60da803..9ee0efc067cc9 100644 --- a/tree/ntuple/test/ntuple_test.hxx +++ b/tree/ntuple/test/ntuple_test.hxx @@ -82,7 +82,7 @@ using RNTupleFillStatus = ROOT::RNTupleFillStatus; using RNTupleDescriptorBuilder = ROOT::Internal::RNTupleDescriptorBuilder; using RNTupleFileWriter = ROOT::Internal::RNTupleFileWriter; using RNTupleJoinTable = ROOT::Experimental::Internal::RNTupleJoinTable; -using RNTupleParallelWriter = ROOT::Experimental::RNTupleParallelWriter; +using RNTupleParallelWriter = ROOT::RNTupleParallelWriter; using RNTupleReader = ROOT::RNTupleReader; using RNTupleReadOptions = ROOT::RNTupleReadOptions; using RNTupleWriter = ROOT::RNTupleWriter; diff --git a/tutorials/io/ntuple/ntpl009_parallelWriter.C b/tutorials/io/ntuple/ntpl009_parallelWriter.C index 3ac6cd58609d4..b129b18fb1453 100644 --- a/tutorials/io/ntuple/ntpl009_parallelWriter.C +++ b/tutorials/io/ntuple/ntpl009_parallelWriter.C @@ -9,9 +9,6 @@ /// \date Feburary 2024 /// \author The ROOT Team -// NOTE: The RNTupleParallelWriter class is experimental at this point. -// Functionality and interface are still subject to changes. - #include #include #include @@ -32,9 +29,6 @@ #include #include -// Import classes from experimental namespace for the time being -using ROOT::Experimental::RNTupleParallelWriter; - // Where to store the ntuple of this example constexpr char const *kNTupleFileName = "ntpl009_parallelWriter.root"; @@ -45,7 +39,7 @@ constexpr int kNWriterThreads = 4; constexpr int kNEventsPerThread = 25000; // Thread function to generate and write events -void FillData(RNTupleParallelWriter *writer) +void FillData(ROOT::RNTupleParallelWriter *writer) { static std::atomic gThreadId; const auto threadId = ++gThreadId; @@ -99,7 +93,7 @@ void Write() options.SetApproxZippedClusterSize(1024 * 1024); // We hand-over the data model to a newly created ntuple of name "NTuple", stored in kNTupleFileName - auto writer = RNTupleParallelWriter::Recreate(std::move(model), "NTuple", kNTupleFileName, options); + auto writer = ROOT::RNTupleParallelWriter::Recreate(std::move(model), "NTuple", kNTupleFileName, options); std::vector threads; for (int i = 0; i < kNWriterThreads; ++i) diff --git a/tutorials/io/ntuple/ntpl013_staged.C b/tutorials/io/ntuple/ntpl013_staged.C index 254768ba04df0..668065063856d 100644 --- a/tutorials/io/ntuple/ntpl013_staged.C +++ b/tutorials/io/ntuple/ntpl013_staged.C @@ -8,9 +8,6 @@ /// \date September 2024 /// \author The ROOT Team -// NOTE: The RNTupleParallelWriter is experimental at this point. -// Functionality and interface are still subject to changes. - #include #include #include @@ -24,9 +21,6 @@ #include #include -// Import classes from experimental namespace for the time being -using ROOT::Experimental::RNTupleParallelWriter; - // Where to store the ntuple of this example constexpr char const *kNTupleFileName = "ntpl013_staged.root"; @@ -40,7 +34,7 @@ constexpr int kNEventsPerThread = 25000; constexpr int kNEventsPerBlock = 10000; // Thread function to generate and write events -void FillData(int id, RNTupleParallelWriter *writer) +void FillData(int id, ROOT::RNTupleParallelWriter *writer) { // static variables that are shared between threads; this is done for simplicity in this tutorial, use proper data // structures in real code! @@ -99,7 +93,7 @@ void Write() options.SetApproxZippedClusterSize(32'000); // We hand over the data model to a newly created ntuple of name "NTuple", stored in kNTupleFileName - auto writer = RNTupleParallelWriter::Recreate(std::move(model), "NTuple", kNTupleFileName, options); + auto writer = ROOT::RNTupleParallelWriter::Recreate(std::move(model), "NTuple", kNTupleFileName, options); std::vector threads; for (int i = 0; i < kNWriterThreads; ++i) @@ -111,7 +105,7 @@ void Write() // and closes the attached ROOT file. } -void FillDataInBlocks(int id, RNTupleParallelWriter *writer) +void FillDataInBlocks(int id, ROOT::RNTupleParallelWriter *writer) { // static variables that are shared between threads; this is done for simplicity in this tutorial, use proper data // structures in real code! @@ -189,7 +183,7 @@ void WriteInBlocks() options.SetApproxZippedClusterSize(32'000); // We hand over the data model to a newly created ntuple of name "NTuple", stored in kNTupleFileName - auto writer = RNTupleParallelWriter::Recreate(std::move(model), "NTuple", kNTupleFileName, options); + auto writer = ROOT::RNTupleParallelWriter::Recreate(std::move(model), "NTuple", kNTupleFileName, options); std::vector threads; for (int i = 0; i < kNWriterThreads; ++i) diff --git a/tutorials/io/ntuple/ntpl014_framework.C b/tutorials/io/ntuple/ntpl014_framework.C index 5947306b5e425..26e320fa354a4 100644 --- a/tutorials/io/ntuple/ntpl014_framework.C +++ b/tutorials/io/ntuple/ntpl014_framework.C @@ -24,7 +24,7 @@ /// \date September 2024 /// \author The ROOT Team -// NOTE: The RNTupleParallelWriter, RNTupleFillContext, and RRawPtrWriteEntry are experimental at this point. +// NOTE: The RRawPtrWriteEntry is experimental at this point. // Functionality and interface are still subject to changes. #include @@ -50,8 +50,6 @@ #include // Import classes from Experimental namespace for the time being -using ROOT::Experimental::RNTupleFillContext; -using ROOT::Experimental::RNTupleParallelWriter; using ROOT::Experimental::Detail::RRawPtrWriteEntry; using ModelTokensPair = std::pair, std::vector>; @@ -92,11 +90,11 @@ public: // A ParallelOutputter uses an RNTupleParallelWriter to append an RNTuple to a TFile. class ParallelOutputter final : public Outputter { FileService &fFileService; - std::unique_ptr fParallelWriter; + std::unique_ptr fParallelWriter; std::vector fTokens; struct SlotData { - std::shared_ptr fillContext; + std::shared_ptr fillContext; std::unique_ptr entry; }; std::vector fSlots; @@ -109,7 +107,8 @@ public: auto &model = modelTokens.first; std::lock_guard g(fileService.GetMutex()); - fParallelWriter = RNTupleParallelWriter::Append(std::move(model), ntupleName, fFileService.GetFile(), options); + fParallelWriter = + ROOT::RNTupleParallelWriter::Append(std::move(model), ntupleName, fFileService.GetFile(), options); } void InitSlot(unsigned slot) final