|
|
|||
File indexing completed on 2026-11-03 09:49:40
0001 //------------------------------- -*- C++ -*- -------------------------------// 0002 // Copyright Celeritas contributors: see top-level COPYRIGHT file for details 0003 // SPDX-License-Identifier: (Apache-2.0 OR MIT) 0004 //---------------------------------------------------------------------------// 0005 //! \file accel/LocalTransporter.hh 0006 //! \sa TrackingManagerIntegration.test.cc 0007 //---------------------------------------------------------------------------// 0008 #pragma once 0009 0010 #include <memory> 0011 0012 #include "corecel/Types.hh" 0013 #include "corecel/io/Logger.hh" 0014 #include "geocel/BoundingBox.hh" 0015 #include "celeritas/Types.hh" 0016 #include "celeritas/ext/GeantTrackReconstruction.hh" 0017 0018 #include "TrackOffloadInterface.hh" 0019 0020 class G4EventManager; 0021 class G4Track; 0022 0023 namespace celeritas 0024 { 0025 //---------------------------------------------------------------------------// 0026 namespace detail 0027 { 0028 class HitProcessor; 0029 } // namespace detail 0030 0031 struct SetupOptions; 0032 class CoreStateInterface; 0033 class OffloadWriter; 0034 class OpticalCollector; 0035 class ParticleParams; 0036 class SharedParams; 0037 class StepperInterface; 0038 struct StepperResult; 0039 0040 //---------------------------------------------------------------------------// 0041 /*! 0042 * Manage offloading of tracks to Celeritas. 0043 * 0044 * This class \em must be constructed locally on each worker 0045 * thread/task/stream, usually as a shared pointer that's accessible to: 0046 * - a run action (for initialization), 0047 * - an event action (to set the event ID and flush offloaded tracks at the end 0048 * of the event) 0049 * - a tracking action (to try offloading every track) 0050 * 0051 * \par Primary buffering 0052 * 0053 * Stepper owns two fixed-capacity host primary buffers and the device event 0054 * that protects the source of an asynchronous H2D copy. LocalTransporter 0055 * validates and converts Geant4 tracks, pushes accepted primaries into the 0056 * Stepper producer buffer, and keeps the corresponding Geant4 energy and loss 0057 * accounting. Primaries outside the Celeritas geometry are counted as lost but 0058 * are not added to either Stepper buffer. 0059 * 0060 * \par Device execution 0061 * 0062 * When the producer buffer first reaches capacity, \c Push stages it and 0063 * immediately calls \c StepperInterface::async. Same-stream ordering ensures 0064 * that the primary-copy completes before the stepping kernels use it. The 0065 * Stepper retains the staged host storage until the copy completes, while 0066 * Geant4 can continue filling the second buffer. 0067 * 0068 * At most one step result, one staged batch, and one producer batch can be 0069 * pending. Before reusing a full producer buffer, \c Push submits any staged 0070 * batch. It then applies backpressure by consuming and advancing the current 0071 * result only until start-of-step initialization can consume enough queued 0072 * tracks and primaries to preserve room for the secondary stack. Active tail 0073 * tracks may remain when a new batch is staged and launched. Calls to \c 0074 * stage_primaries and \c async can still block on synchronization internal to 0075 * the current Stepper implementation. 0076 * Before accepting each subsequent track, \c Push polls a pending step. If it 0077 * is ready, its result is consumed and another step is launched whenever 0078 * existing transport remains or another batch is staged. This allows device 0079 * transport to progress while Geant4 continues producing primaries. A full 0080 * producer batch is staged only when it fits alongside queued initializers and 0081 * leaves the maximum usable initializer capacity for secondaries after vacant 0082 * track slots have been filled. 0083 * 0084 * \par Event completion 0085 * 0086 * At event end, \c Flush first submits any staged batch. If a partially filled 0087 * producer buffer remains, it advances the current transport until that batch 0088 * satisfies the same initializer and secondary-capacity admission rule, then 0089 * stages and launches the producer batch. It finally steps all transport 0090 * synchronously to completion. Selection and compaction of device-generated 0091 * Geant SD data are enqueued on the device during the action launch, so a step 0092 * is not ready until they complete. The compacted data is copied to the host 0093 * and reconstructed only when the completed step result is consumed, keeping 0094 * the host copy and hit processing out of the asynchronous action launch. The 0095 * current copy still synchronizes before the next step starts. Hit processing 0096 * and Geant4 track reconstruction 0097 * are kept alive across the asynchronous work and cleared only after the drain 0098 * completes. A flush with only rejected primaries still reports and clears 0099 * their loss accounting. 0100 * 0101 * Host mode has the same buffering interface but no asynchronous overlap: a 0102 * full producer buffer calls \c Flush and is transported to completion before 0103 * \c Push returns. 0104 * 0105 * \internal 0106 * 0107 * LocalTransporter accounting follows the Stepper primary lifecycle: 0108 * 0109 * | State | Stepper state | Local accounting | 0110 * | ----- | ------------- | ---------------- | 0111 * | Producer | Primaries accepted by \c push_primary | \c buffered_accum_ | 0112 * | Staged | H2D copy queued; actions not submitted | \c staged_accum_ | 0113 * | Submitted | Batch submitted by \c async | \c in_flight_accum_ | 0114 * | Accounted | First result for batch consumed | Added to \c run_accum_ | 0115 * 0116 * \c in_flight_accum_ is cleared when the first result for its submitted batch 0117 * is consumed, even if the resulting active tracks require additional steps. 0118 * \c GetBufferSize returns accepted primaries that have not yet reached this 0119 * accounting point. It does not count rejected primaries, active Celeritas 0120 * tracks, or generated secondaries. The \c transport_active_ flag records 0121 * whether the last consumed result requires another step, while \c valid on 0122 * the Stepper records a currently pending result. The step iteration count 0123 * spans all overlapping primary batches and resets only after transport 0124 * becomes empty. Calling \c Finalize requires both states to be idle, normally 0125 * by first calling \c Flush. 0126 * 0127 * \warning Due to Geant4 thread-local allocators, this class \em must be 0128 * finalized or destroyed on the same CPU thread in which is created and used! 0129 */ 0130 class LocalTransporter final : public TrackOffloadInterface 0131 { 0132 public: 0133 // Construct in an invalid state 0134 LocalTransporter() = default; 0135 0136 // Initialized with shared (across threads) params 0137 LocalTransporter(SetupOptions const& options, SharedParams& params); 0138 0139 //!@{ 0140 //! \name LocalOffload interface 0141 0142 // Alternative to construction + move assignment 0143 inline void Initialize(SetupOptions const& options, 0144 SharedParams& params) final; 0145 0146 // Set the event ID and reseed the Celeritas RNG at the start of an event 0147 void InitializeEvent(int) final; 0148 0149 // Transport all queued and in-flight tracks to completion 0150 void Flush() final; 0151 0152 // Clear local data and return to an invalid state 0153 void Finalize() final; 0154 0155 // Whether the class instance is initialized 0156 bool Initialized() const final { return static_cast<bool>(step_); } 0157 0158 // Number of accepted primaries not yet accounted as transported 0159 size_type GetBufferSize() const final; 0160 0161 // Get accumulated action times 0162 MapStrDbl GetActionTime() const final; 0163 //!@} 0164 0165 // Offload this track 0166 void Push(G4Track&) final; 0167 0168 // Access core state data for user diagnostics 0169 CoreStateInterface const& GetState() const; 0170 0171 // Access core state data for user diagnostics 0172 CoreStateInterface& GetState(); 0173 0174 //! Whether the class instance is initialized 0175 explicit operator bool() const { return this->Initialized(); } 0176 0177 private: 0178 //// TYPES //// 0179 0180 using SPOffloadWriter = std::shared_ptr<OffloadWriter>; 0181 using BBox = BoundingBox<double>; 0182 0183 struct BufferAccum 0184 { 0185 size_type primaries{0}; 0186 double energy{0}; // MeV 0187 double lost_energy{0}; // MeV 0188 std::size_t lost_primaries{0}; 0189 0190 bool empty() const { return primaries == 0 && lost_primaries == 0; } 0191 }; 0192 0193 struct RunAccum 0194 { 0195 std::size_t events{0}; 0196 std::size_t flushes{0}; 0197 std::size_t primaries{0}; 0198 std::size_t steps{0}; 0199 std::size_t lost_primaries{0}; 0200 std::size_t hits{0}; 0201 }; 0202 0203 //// HELPER FUNCTIONS //// 0204 0205 void flush_impl(); 0206 void push_impl(G4Track&); 0207 void stage_buffered_primaries(StepperResult const&); 0208 size_type available_primary_capacity(StepperResult const&) const; 0209 void launch_step(); 0210 StepperResult complete_step(); 0211 void advance_if_ready(); 0212 StepperResult advance_transport(); 0213 StepperResult wait_for_initializer_capacity(); 0214 void drain_transport(); 0215 void reset_local_state(); 0216 void launch_pending_primaries(); 0217 0218 //// DATA //// 0219 0220 // Shared problem data and local configuration 0221 std::shared_ptr<ParticleParams const> particles_; 0222 BBox bbox_; 0223 SPOffloadWriter dump_primaries_; 0224 size_type max_step_iters_{}; 0225 0226 // Thread-local stepper data 0227 std::shared_ptr<StepperInterface> step_; 0228 BufferAccum buffered_accum_; 0229 BufferAccum staged_accum_; 0230 BufferAccum in_flight_accum_; 0231 // Completed iterations in the current uninterrupted transport epoch 0232 size_type step_iters_{0}; 0233 // Whether the last consumed result requires another step 0234 bool transport_active_{false}; 0235 0236 // Thread-local Geant4 integration data 0237 std::shared_ptr<detail::HitProcessor> hit_processor_; 0238 std::shared_ptr<GeantTrackReconstruction> track_reconstruction_; 0239 std::shared_ptr<OpticalCollector const> optical_; 0240 0241 // Last seen event ID and manager for obtaining it 0242 int event_id_{-1}; 0243 G4EventManager* event_manager_{nullptr}; 0244 0245 // Run summary diagnostics 0246 RunAccum run_accum_; 0247 }; 0248 0249 //---------------------------------------------------------------------------// 0250 /*! 0251 * Helper for making initialization more obvious from user code. 0252 * 0253 * This gives it some symmetry with Finalize, which is provided as an 0254 * exception-friendly destructor. 0255 */ 0256 void LocalTransporter::Initialize(SetupOptions const& options, 0257 SharedParams& params) 0258 { 0259 *this = LocalTransporter(options, params); 0260 } 0261 0262 //---------------------------------------------------------------------------// 0263 } // namespace celeritas
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|