ATLAS Offline Software
Loading...
Searching...
No Matches
triton::backend::traccc::TracccTritonRunner Class Reference

Drives the device reconstruction chain for a single Triton request. More...

#include <TracccTritonRunner.h>

Collaboration diagram for triton::backend::traccc::TracccTritonRunner:

Classes

struct  Output
 The host-resident reconstruction result of one request: the track container, the measurements its states index into, and the clusters (cell indices) those measurements were built from. More...
struct  Impl

Public Member Functions

 TracccTritonRunner (TracccTritonInitializer &initializer, std::size_t slot)
 TracccTritonInitializer::acquireSlot().
 ~TracccTritonRunner ()
 TracccTritonRunner (const TracccTritonRunner &)=delete
TracccTritonRunner & operator= (const TracccTritonRunner &)=delete
void run (const uint8_t *buffer, std::size_t byteSize, const EventIDBase &eventID, EventIDBase::number_type conditionsRun, bool printStats, Output &output)
 Run the full chain for one request.

Private Attributes

std::unique_ptr< Impl > m_impl

Detailed Description

Drives the device reconstruction chain for a single Triton request.

Definition at line 34 of file TracccTritonRunner.h.

Constructor & Destructor Documentation

◆ TracccTritonRunner() [1/2]

triton::backend::traccc::TracccTritonRunner::TracccTritonRunner ( TracccTritonInitializer & initializer,
std::size_t slot )

TracccTritonInitializer::acquireSlot().

Exceptions
std::runtime_errorif the initializer is not ready or slot is not one of the slots the application was configured with.

Definition at line 107 of file TracccTritonRunner.cxx.

109 : m_impl(std::make_unique<Impl>(initializer, slot)) {
110
111 if (!initializer.isReady()) {
112 throw std::runtime_error(
113 "TracccTritonRunner: initializer is not ready");
114 }
115
116 if (cudaSetDevice(initializer.deviceId()) != cudaSuccess) {
117 throw std::runtime_error(
118 "TracccTritonRunner: cudaSetDevice(" +
119 std::to_string(initializer.deviceId()) + ") failed");
120 }
121
122 if (m_impl->eventStore.retrieve().isFailure() || !m_impl->eventStore) {
123 throw std::runtime_error(
124 "TracccTritonRunner: could not retrieve StoreGateSvc");
125 }
126
127 SmartIF<ISvcLocator> svcLocator(&initializer.serviceLocator());
128
129 // plumbing to allow multi-model-inst. per GPU
130 m_impl->whiteboard =
131 svcLocator->service<IHiveWhiteBoard>("EventDataSvc", /*createIf*/ false);
132 if (!m_impl->whiteboard) {
133 throw std::runtime_error(
134 "TracccTritonRunner: EventDataSvc is not an IHiveWhiteBoard");
135 }
136 if (slot >= m_impl->whiteboard->getNumberOfStores()) {
137 throw std::runtime_error(
138 "TracccTritonRunner: slot " + std::to_string(slot) +
139 " is out of range, the whiteboard has only " +
140 std::to_string(m_impl->whiteboard->getNumberOfStores()) +
141 " store(s)");
142 }
143
144 // The device chain takes its stream from this service, one per slot
145 SmartIF<AthCUDA::IStreamSvc> streamSvc =
146 svcLocator->service<AthCUDA::IStreamSvc>(
147 initializer.config().streamSvcName, /*createIf*/ false);
148 if (!streamSvc) {
149 throw std::runtime_error(
150 "TracccTritonRunner: could not retrieve the CUDA stream service '" +
151 initializer.config().streamSvcName +
152 "'; TracccTritonBootstrap.py has to set "
153 "flags.CUDA.Stream = CUDAStream.PerEvent");
154 }
155 m_impl->stream = static_cast<cudaStream_t>(
156 streamSvc->stream(EventContext(0, slot)));
157 m_impl->copy.emplace(m_impl->stream);
158
159 IAlgManager* algMgr = svcLocator.as<IAlgManager>();
160 if (!algMgr) {
161 throw std::runtime_error(
162 "TracccTritonRunner: no IAlgManager in the embedded application");
163 }
164 m_impl->chain = algMgr->algorithm(initializer.config().sequenceName,
165 /*createIf*/ false);
166 if (!m_impl->chain) {
167 throw std::runtime_error(
168 "TracccTritonRunner: could not retrieve the device chain '" +
169 initializer.config().sequenceName +
170 "' from the embedded Athena application");
171 }
172 m_impl->condChain = algMgr->algorithm(initializer.config().condSequenceName,
173 /*createIf*/ false);
174
175 m_impl->incidentSvc =
176 svcLocator->service<IIncidentSvc>("IncidentSvc", /*createIf*/ false);
177 if (!m_impl->incidentSvc) {
178 throw std::runtime_error(
179 "TracccTritonRunner: could not retrieve IncidentSvc");
180 }
181
182 // Drops conditions objects no longer needed by any event, as the event
183 // loop manager does at the start of each event; without it a long-running server
184 // keeps every IOV it has ever seen
185 if (m_impl->condChain) {
186 m_impl->conditionsCleaner =
187 svcLocator->service<Athena::IConditionsCleanerSvc>(
188 "Athena::ConditionsCleanerSvc", /*createIf*/ true);
189 if (!m_impl->conditionsCleaner) {
190 throw std::runtime_error(
191 "TracccTritonRunner: could not retrieve "
192 "Athena::ConditionsCleanerSvc");
193 }
194 }
195
196 // AthSequencer::execute() skips itself if its AlgExecState for this
197 // context is already Done, so the states have to be reset once per
198 // request the way AthenaEventLoopMgr does between events
199 m_impl->algExecStates = svcLocator->service<IAlgExecStateSvc>(
200 "AlgExecStateSvc", /*createIf*/ false);
201 if (!m_impl->algExecStates) {
202 throw std::runtime_error(
203 "TracccTritonRunner: could not retrieve AlgExecStateSvc");
204 }
205}

◆ ~TracccTritonRunner()

triton::backend::traccc::TracccTritonRunner::~TracccTritonRunner ( )
default

◆ TracccTritonRunner() [2/2]

triton::backend::traccc::TracccTritonRunner::TracccTritonRunner ( const TracccTritonRunner & )
delete

Member Function Documentation

◆ operator=()

TracccTritonRunner & triton::backend::traccc::TracccTritonRunner::operator= ( const TracccTritonRunner & )
delete

◆ run()

void triton::backend::traccc::TracccTritonRunner::run ( const uint8_t * buffer,
std::size_t byteSize,
const EventIDBase & eventID,
EventIDBase::number_type conditionsRun,
bool printStats,
Output & output )

Run the full chain for one request.

Parameters
bufferpointer to the gathered CELLS bytes, a serialized traccc silicon_cell_collection (TracccEdmSerialization.h)
byteSizesize of buffer in bytes.
eventIDthe client event's id (run, lumiblock, time stamp), which the conditions are looked up for
conditionsRunrun number override for the conditions (MC)
printStatsemit per-stage timing to stdout.
outputfilled with the result
Exceptions
std::runtime_erroron any deserialization, algorithm or copy failure.

Definition at line 209 of file TracccTritonRunner.cxx.

212 {
213 const auto& keys = m_impl->initializer.config();
214
215 auto t0 = std::chrono::high_resolution_clock::now();
216
217 // Deserialize the CELLS tensor into a host cell collection
218 ::traccc::edm::silicon_cell_collection::host cells(m_impl->host_mr);
219 if (buffer == nullptr) {
220 throw std::runtime_error("TracccTritonRunner: no CELLS buffer");
221 }
222 TracccTriton::deserialize(buffer, byteSize, cells);
223
224 auto t1 = std::chrono::high_resolution_clock::now();
225
226 if (m_impl->whiteboard->selectStore(m_impl->slot).isFailure()) {
227 throw std::runtime_error(
228 "TracccTritonRunner: could not select store for slot " +
229 std::to_string(m_impl->slot));
230 }
231
232 // Copy cells to the device and record them in StoreGate
233 if (m_impl->eventStore->clearStore().isFailure()) {
234 throw std::runtime_error("TracccTritonRunner: clearStore() failed");
235 }
236
237 // Conditions handles are resolved against the event's IOV, so the
238 // context carries the client event's id and conditions run, as the
239 // event loop manager would set them up
240 const std::size_t eventNumber = m_impl->eventCounter++;
241 EventContext ctx(eventNumber, m_impl->slot);
242 EventIDBase ctxEventID(eventID);
243 ctxEventID.set_event_number(eventNumber);
244 ctx.setEventID(ctxEventID);
245 ctx.setExtension(Atlas::ExtendedEventContext(
246 m_impl->eventStore->hiveProxyDict(), conditionsRun));
247 Gaudi::Hive::setCurrentContext(ctx);
248 {
249 auto deviceCells =
250 std::make_unique<::traccc::edm::silicon_cell_collection::buffer>(
251 static_cast<unsigned int>(cells.size()), m_impl->device_mr);
252 m_impl->copy->setup(*deviceCells)->ignore();
253 (*m_impl->copy)(vecmem::get_data(cells), *deviceCells)->wait();
254
255 if (m_impl->eventStore
256 ->record(std::move(deviceCells), keys.cellsKey)
257 .isFailure()) {
258 throw std::runtime_error(
259 "TracccTritonRunner: failed to record cells under '" +
260 keys.cellsKey + "'");
261 }
262 }
263
264 auto t2 = std::chrono::high_resolution_clock::now();
265
266 // Run the device chain as the python configuration declared it.
267 // Clear the previous request's execution states first, otherwise the
268 // sequencer sees itself as Done and silently runs nothing.
269 m_impl->algExecStates->reset(ctx);
270
271 if (m_impl->condChain) {
272 std::lock_guard<std::mutex> lock(sharedRunState.mutex);
273
274 // IOVDbSvc resolves conditions folders at the time it is given on
275 // BeginRun (there is no BeginEvent/EventInfo here), so fire it
276 // whenever the run changes, as the event loop manager does
277 const EventIDBase::number_type run = ctx.eventID().run_number();
278 if (sharedRunState.currentRun != run) {
279 sharedRunState.currentRun = run;
280 m_impl->incidentSvc->fireIncident(
281 Incident("TracccTritonRunner", IncidentType::BeginRun, ctx));
282 }
283
284 // Drop the conditions objects no event in flight needs any more,
285 // as the event loop manager does at the start of each event.
286 // Synchronously, since there is no scheduler to run it in a task.
287 if (m_impl->conditionsCleaner->event(ctx, /*allowAsync*/ false)
288 .isFailure()) {
289 throw std::runtime_error(
290 "TracccTritonRunner: conditions cleaning failed");
291 }
292
293 // Make the conditions for this IOV available; the conditions algs
294 // skip themselves once their object is valid for the IOV, so this is
295 // cheap for every request after the first one of an IOV
296 if (m_impl->condChain->sysExecute(ctx).isFailure()) {
297 std::ostringstream states;
298 m_impl->algExecStates->dump(states, ctx);
299 throw std::runtime_error(
300 "TracccTritonRunner: conditions sequence '" +
301 m_impl->condChain->name() +
302 "' failed during execute(). Algorithm states:\n" + states.str());
303 }
304 }
305
306 if (m_impl->chain->sysExecute(ctx).isFailure()) {
307 std::ostringstream states;
308 m_impl->algExecStates->dump(states, ctx);
309 throw std::runtime_error(
310 "TracccTritonRunner: device chain '" + m_impl->chain->name() +
311 "' failed during execute(). Algorithm states:\n" + states.str());
312 }
313 // The algorithms return with work still queued on the stream
314 if (cudaStreamSynchronize(m_impl->stream) != cudaSuccess) {
315 throw std::runtime_error(
316 "TracccTritonRunner: cudaStreamSynchronize failed after the "
317 "device chain");
318 }
319
320 auto t3 = std::chrono::high_resolution_clock::now();
321
322 // Copy the fitted tracks and the measurements their states point at back to the host
323 const traccc_track_container::buffer* tracksDevice = nullptr;
324 if (m_impl->eventStore->retrieve(tracksDevice, keys.tracksKey).isFailure() ||
325 tracksDevice == nullptr) {
326 throw std::runtime_error(
327 "TracccTritonRunner: could not retrieve tracks under '" +
328 keys.tracksKey + "'");
329 }
330
331 const ::traccc::edm::measurement_collection::buffer* measurementsDevice =
332 nullptr;
333 if (m_impl->eventStore
334 ->retrieve(measurementsDevice, keys.measurementsKey)
335 .isFailure() ||
336 measurementsDevice == nullptr) {
337 throw std::runtime_error(
338 "TracccTritonRunner: could not retrieve measurements under '" +
339 keys.measurementsKey + "'");
340 }
341
342 const ::traccc::edm::silicon_cluster_collection::buffer* clustersDevice =
343 nullptr;
344 if (m_impl->eventStore->retrieve(clustersDevice, keys.clustersKey)
345 .isFailure() ||
346 clustersDevice == nullptr) {
347 throw std::runtime_error(
348 "TracccTritonRunner: could not retrieve clusters under '" +
349 keys.clustersKey + "'");
350 }
351
352 const vecmem::copy& copy = *m_impl->copy;
353 copyJaggedToHost(copy, tracksDevice->tracks, output.tracks.tracks,
354 m_impl->host_mr);
355 copy(tracksDevice->states, output.tracks.states,
356 vecmem::copy::type::device_to_host)->wait();
357 copy(*measurementsDevice, output.measurements,
358 vecmem::copy::type::device_to_host)->wait();
359 copyJaggedToHost(copy, *clustersDevice, output.clusters, m_impl->host_mr);
360
361 auto t4 = std::chrono::high_resolution_clock::now();
362
363 if (printStats) {
364 auto ms = [](auto a, auto b) {
365 return std::chrono::duration_cast<std::chrono::milliseconds>(b - a)
366 .count();
367 };
368
369 const std::string tag =
370 "[TIMING][slot " + std::to_string(m_impl->slot) + "] ";
371 std::cout << tag << "Cell deserialization : " << ms(t0, t1) << " ms\n"
372 << tag << "Cell H2D + record : " << ms(t1, t2) << " ms\n"
373 << tag << "Device chain : " << ms(t2, t3) << " ms\n"
374 << tag << "Output D2H : " << ms(t3, t4) << " ms\n"
375 << tag << "Tracks: " << output.tracks.tracks.size()
376 << std::endl;
377 }
378}
virtual void lock()=0
Interface to allow an object to lock itself when made const in SG.
static Double_t a
static Double_t t0
void run(const uint8_t *buffer, std::size_t byteSize, const EventIDBase &eventID, EventIDBase::number_type conditionsRun, bool printStats, Output &output)
Run the full chain for one request.
std::vector< ALFA_RawDataContainer_p1 > t2
std::vector< ALFA_RawDataCollection_p1 > t1
std::vector< LUCID_RawDataContainer_p1 > t4
std::vector< LUCID_RawData_p1 > t3
void deserialize(const std::uint8_t *data, std::size_t size, vecmem::edm::host< vecmem::edm::schema< VARTYPES... >, INTERFACE > &container)
Fill container from size bytes at data.
bool copy
Definition calibdata.py:26
output
Definition merge.py:16

Member Data Documentation

◆ m_impl

std::unique_ptr<Impl> triton::backend::traccc::TracccTritonRunner::m_impl
private

Definition at line 81 of file TracccTritonRunner.h.


The documentation for this class was generated from the following files: