|
|
|||
File indexing completed on 2026-10-31 09:45:46
0001 /// \file ROOT/RNTupleParallelWriter.hxx 0002 /// \ingroup NTuple 0003 /// \author Jonas Hahnfeld <jonas.hahnfeld@cern.ch> 0004 /// \date 2024-02-01 0005 0006 /************************************************************************* 0007 * Copyright (C) 1995-2024, Rene Brun and Fons Rademakers. * 0008 * All rights reserved. * 0009 * * 0010 * For the licensing terms see $ROOTSYS/LICENSE. * 0011 * For the list of contributors see $ROOTSYS/README/CREDITS. * 0012 *************************************************************************/ 0013 0014 #ifndef ROOT_RNTupleParallelWriter 0015 #define ROOT_RNTupleParallelWriter 0016 0017 #include <ROOT/RNTupleMetrics.hxx> 0018 #include <ROOT/RNTupleWriteOptions.hxx> 0019 0020 #include <memory> 0021 #include <mutex> 0022 #include <string_view> 0023 #include <vector> 0024 0025 class TDirectory; 0026 0027 namespace ROOT { 0028 0029 class RNTupleModel; 0030 0031 namespace Internal { 0032 class RPageSink; 0033 } // namespace Internal 0034 0035 class RNTupleFillContext; 0036 0037 /** 0038 \class ROOT::RNTupleParallelWriter 0039 \ingroup NTuple 0040 \brief A writer to fill an RNTuple from multiple contexts 0041 0042 Compared to the sequential RNTupleWriter, a parallel writer enables the creation of multiple RNTupleFillContext (see 0043 CreateFillContext()). Each fill context prepares independent clusters that are appended to the common RNTuple with 0044 internal synchronization. Before destruction, all fill contexts must have flushed their data and been destroyed (or 0045 data could be lost!). 0046 0047 For user convenience, CreateFillContext() is thread-safe and may be called from multiple threads in parallel at any 0048 time, also after some data has already been written. Internally, the original model is cloned and ownership is passed 0049 to a newly created RNTupleFillContext. For that reason, it is recommended to use RNTupleModel::CreateBare when creating 0050 the model for parallel writing and avoid the allocation of a useless default REntry per context. 0051 0052 Note that the sequence of independently prepared clusters is indeterminate and therefore entries are only partially 0053 ordered: Entries from one context are totally ordered as they were filled. However, there is no orderering with other 0054 contexts and the entries may be appended to the RNTuple either before or after other entries written in parallel into 0055 other contexts. In addition, two consecutive entries in one fill context can end up separated in the final RNTuple, if 0056 they happen to fall onto a cluster boundary and other contexts append more entries before the next cluster is full. 0057 0058 At the moment, the parallel writer does not (yet) support incremental updates of the underlying model. Please refer to 0059 RNTupleWriter::CreateModelUpdater if required for your use case. 0060 */ 0061 class RNTupleParallelWriter { 0062 private: 0063 /// A global mutex to protect the internal data structures of this object. 0064 std::mutex fMutex; 0065 /// A mutex to synchronize the final page sink. 0066 std::mutex fSinkMutex; 0067 /// The final RPageSink that represents the synchronization point. 0068 std::unique_ptr<ROOT::Internal::RPageSink> fSink; 0069 /// The original RNTupleModel connected to fSink; needs to be destructed before it. 0070 std::unique_ptr<ROOT::RNTupleModel> fModel; 0071 Experimental::Detail::RNTupleMetrics fMetrics; 0072 /// List of all created helpers. They must be destroyed before this RNTupleParallelWriter is destructed. 0073 std::vector<std::weak_ptr<RNTupleFillContext>> fFillContexts; 0074 0075 RNTupleParallelWriter(std::unique_ptr<ROOT::RNTupleModel> model, std::unique_ptr<ROOT::Internal::RPageSink> sink); 0076 RNTupleParallelWriter(const RNTupleParallelWriter &) = delete; 0077 RNTupleParallelWriter &operator=(const RNTupleParallelWriter &) = delete; 0078 RNTupleParallelWriter(RNTupleParallelWriter &&) = delete; 0079 RNTupleParallelWriter &operator=(RNTupleParallelWriter &&) = delete; 0080 0081 public: 0082 /// Recreate a new file and return a writer to write an RNTuple. 0083 static std::unique_ptr<RNTupleParallelWriter> 0084 Recreate(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName, std::string_view storage, 0085 const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions()); 0086 /// Append an RNTuple to the existing file. 0087 /// 0088 /// While the writer synchronizes between multiple fill contexts created from the same writer, there is no 0089 /// synchronization with other writers or other clients that write into the same file. The caller must ensure that 0090 /// the underlying file is not be accessed while data is filled into any created context. To improve performance, it 0091 /// is allowed to use special methods that are guaranteed to not interact with the underlying file, such as 0092 /// RNTupleFillContext::FillNoFlush(). 0093 static std::unique_ptr<RNTupleParallelWriter> 0094 Append(std::unique_ptr<ROOT::RNTupleModel> model, std::string_view ntupleName, TDirectory &fileOrDirectory, 0095 const ROOT::RNTupleWriteOptions &options = ROOT::RNTupleWriteOptions()); 0096 0097 ~RNTupleParallelWriter(); 0098 0099 /// Create a new RNTupleFillContext that can be used to fill entries and prepare clusters in parallel. This method is 0100 /// thread-safe and may be called from multiple threads in parallel at any time, also after some data has already 0101 /// been written. 0102 /// 0103 /// Note that all fill contexts must be destroyed before CommitDataset() is called. 0104 std::shared_ptr<RNTupleFillContext> CreateFillContext(); 0105 0106 /// Automatically called by the destructor 0107 void CommitDataset(); 0108 0109 void EnableMetrics() { fMetrics.Enable(); } 0110 const Experimental::Detail::RNTupleMetrics &GetMetrics() const { return fMetrics; } 0111 }; 0112 0113 } // namespace ROOT 0114 0115 #endif
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|