Project
Loading...
Searching...
No Matches
GPUO2Interface.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#include "GPUO2Interface.h"
16#include "GPUReconstruction.h"
17#include "GPUChainTracking.h"
18#include "GPUChainITS.h"
20#include "GPUOutputControl.h"
23#include "GPUParam.inc"
24#include "GPUQA.h"
25#include "GPUOutputControl.h"
26#include <iostream>
27#include <fstream>
28#include <thread>
29#include <optional>
30#include <mutex>
31
32using namespace o2::gpu;
33
35
36namespace o2::gpu
37{
39 std::unique_ptr<GPUReconstruction> mRec;
41 std::unique_ptr<GPUTrackingOutputs> mOutputRegions;
42};
43
45 std::unique_ptr<std::thread> pipelineThread;
46};
47} // namespace o2::gpu
48
50
52
54{
55 if (mNContexts) {
56 return (1);
57 }
58 mConfig.reset(new GPUO2InterfaceConfiguration(config));
59 mNContexts = mConfig->configProcessing.doublePipeline ? 2 : 1;
60 mCtx.reset(new GPUO2Interface_processingContext[mNContexts]);
61 if (mConfig->configWorkflow.inputs.isSet(GPUDataTypes::InOutType::TPCRaw)) {
62 mConfig->configGRP.needsClusterer = 1;
63 }
64 if (mConfig->configWorkflow.inputs.isSet(GPUDataTypes::InOutType::TPCCompressedClusters)) {
65 mConfig->configGRP.doCompClusterDecode = 1;
66 }
67 for (uint32_t i = 0; i < mNContexts; i++) {
68 if (i) {
69 mConfig->configDeviceBackend.master = mCtx[0].mRec.get();
70 }
71 mCtx[i].mRec.reset(GPUReconstruction::CreateInstance(mConfig->configDeviceBackend));
72 mConfig->configDeviceBackend.master = nullptr;
73 if (mCtx[i].mRec == nullptr) {
74 GPUError("Error obtaining instance of GPUReconstruction");
75 mNContexts = 0;
76 mCtx.reset(nullptr);
77 return 1;
78 }
79 }
80 for (uint32_t i = 0; i < mNContexts; i++) {
81 mCtx[i].mChain = mCtx[i].mRec->AddChain<GPUChainTracking>(mConfig->configInterface.maxTPCHits, mConfig->configInterface.maxTRDTracklets);
82 if (i) {
83 mCtx[i].mChain->SetQAFromForeignChain(mCtx[0].mChain);
84 }
85 mCtx[i].mChain->mConfigDisplay = &mConfig->configDisplay;
86 mCtx[i].mChain->mConfigQA = &mConfig->configQA;
87 mCtx[i].mRec->SetSettings(&mConfig->configGRP, &mConfig->configReconstruction, &mConfig->configProcessing, &mConfig->configWorkflow);
88 mCtx[i].mChain->SetCalibObjects(mConfig->configCalib);
89
90 if (i == 0 && mConfig->configWorkflow.steps.isSet(GPUDataTypes::RecoStep::ITSTracking)) {
91 mChainITS = mCtx[i].mRec->AddChain<GPUChainITS>();
92 }
93
94 mCtx[i].mOutputRegions.reset(new GPUTrackingOutputs);
95 if (mConfig->configInterface.outputToExternalBuffers) {
96 for (uint32_t j = 0; j < mCtx[i].mOutputRegions->count(); j++) {
97 mCtx[i].mChain->SetSubOutputControl(j, &mCtx[i].mOutputRegions->asArray()[j]);
98 }
99 GPUOutputControl dummy;
100 dummy.set([](size_t size) -> void* {throw std::runtime_error("invalid output memory request, no common output buffer set"); return nullptr; });
101 mCtx[i].mRec->SetOutputControl(dummy);
102 }
103 }
104 for (uint32_t i = 0; i < mNContexts; i++) {
105 if (i == 0 && mCtx[i].mRec->Init()) {
106 mNContexts = 0;
107 mCtx.reset(nullptr);
108 return (1);
109 }
110 if (!mCtx[i].mRec->IsGPU() && mCtx[i].mRec->GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) {
111 mCtx[i].mRec->MemoryScalers()->factor *= 2;
112 }
113 }
114 if (mConfig->configProcessing.doublePipeline) {
115 mInternals->pipelineThread.reset(new std::thread([this]() { mCtx[0].mRec->RunPipelineWorker(); }));
116 }
117 return (0);
118}
119
121{
122 if (mNContexts) {
123 if (mConfig->configProcessing.doublePipeline) {
124 mCtx[0].mRec->TerminatePipelineWorker();
125 mInternals->pipelineThread->join();
126 }
127 for (uint32_t i = 0; i < mNContexts; i++) {
128 mCtx[i].mRec->Finalize();
129 }
130 mCtx[0].mRec->Exit();
131 for (int32_t i = mNContexts - 1; i >= 0; i--) {
132 mCtx[i].mRec.reset();
133 }
134 }
135 mNContexts = 0;
136}
137
139{
140 mCtx[0].mChain->ClearIOPointers();
141 mCtx[0].mChain->mIOPtrs = *data;
142 char fname[1024];
143 snprintf(fname, 1024, "event.%d.dump", nEvent);
144 mCtx[0].mChain->DumpData(fname);
145 if (nEvent == 0) {
146#ifdef GPUCA_BUILD_QA
147 if (mConfig->configProcessing.runMC) {
148 mCtx[0].mChain->ForceInitQA();
149 snprintf(fname, 1024, "mc.%d.dump", nEvent);
150 mCtx[0].mChain->GetQA()->UpdateChain(mCtx[0].mChain);
151 mCtx[0].mChain->GetQA()->DumpO2MCData(fname);
152 }
153#endif
154 }
155}
156
158{
159 mCtx[0].mChain->DoQueuedUpdates(-1);
160 mCtx[0].mRec->DumpSettings();
161}
162
164{
165 if (mNContexts <= iThread) {
166 return (1);
167 }
168
169 mCtx[iThread].mChain->mIOPtrs = *data;
170
171 auto setOutputs = [this, iThread](GPUInterfaceOutputs* outputs) {
172 if (mConfig->configInterface.outputToExternalBuffers) {
173 for (uint32_t i = 0; i < mCtx[iThread].mOutputRegions->count(); i++) {
174 if (outputs->asArray()[i].allocator) {
175 mCtx[iThread].mOutputRegions->asArray()[i].set(outputs->asArray()[i].allocator);
176 } else if (outputs->asArray()[i].ptrBase) {
177 mCtx[iThread].mOutputRegions->asArray()[i].set(outputs->asArray()[i].ptrBase, outputs->asArray()[i].size);
178 } else {
179 mCtx[iThread].mOutputRegions->asArray()[i].reset();
180 }
181 }
182 }
183 };
184
185 auto inputWaitCallback = [this, iThread, inputUpdateCallback, &data, &outputs, &setOutputs]() {
186 GPUTrackingInOutPointers* updatedData;
187 GPUInterfaceOutputs* updatedOutputs;
188 if (inputUpdateCallback->callback) {
189 inputUpdateCallback->callback(updatedData, updatedOutputs);
190 mCtx[iThread].mChain->mIOPtrs = *updatedData;
191 outputs = updatedOutputs;
192 data = updatedData;
193 setOutputs(outputs);
194 }
195 if (inputUpdateCallback->notifyCallback) {
196 inputUpdateCallback->notifyCallback();
197 }
198 };
199
200 if (inputUpdateCallback) {
201 mCtx[iThread].mChain->SetFinalInputCallback(inputWaitCallback);
202 } else {
203 mCtx[iThread].mChain->SetFinalInputCallback(nullptr);
204 }
205 if (!inputUpdateCallback || !inputUpdateCallback->callback) {
206 setOutputs(outputs);
207 }
208
209 int32_t retVal = mCtx[iThread].mRec->RunChains();
210 if (retVal == 2) {
211 retVal = 0; // 2 signals end of event display, ignore
212 }
213 if (mConfig->configQA.shipToQC && mCtx[iThread].mChain->QARanForTF()) {
214 outputs->qa.hist1 = &mCtx[iThread].mChain->GetQA()->getHistograms1D();
215 outputs->qa.hist2 = &mCtx[iThread].mChain->GetQA()->getHistograms2D();
216 outputs->qa.hist3 = &mCtx[iThread].mChain->GetQA()->getHistograms1Dd();
217 outputs->qa.hist4 = &mCtx[iThread].mChain->GetQA()->getGraphs();
218 outputs->qa.newQAHistsCreated = true;
219 }
220 *data = mCtx[iThread].mChain->mIOPtrs;
221
222 return retVal;
223}
224
225void GPUO2Interface::Clear(bool clearOutputs, uint32_t iThread) { mCtx[iThread].mRec->ClearAllocatedMemory(clearOutputs); }
226
228{
229 return mCtx[0].mRec->registerMemoryForGPU(ptr, size);
230}
231
233{
234 return mCtx[0].mRec->unregisterMemoryForGPU(ptr);
235}
236
237int32_t GPUO2Interface::UpdateCalibration(const GPUCalibObjectsConst& newCalib, const GPUNewCalibValues& newVals, uint32_t iThread)
238{
239 for (uint32_t i = 0; i < mNContexts; i++) {
240 mCtx[i].mChain->SetUpdateCalibObjects(newCalib, newVals);
241 }
242 return 0;
243}
244
245void GPUO2Interface::setErrorCodeOutput(std::vector<std::array<uint32_t, 4>>* v)
246{
247 for (uint32_t i = 0; i < mNContexts; i++) {
248 mCtx[i].mRec->setErrorCodeOutput(v);
249 }
250}
251
253{
254 trackerTraits = mChainITS->GetITSTrackerTraits();
255 vertexerTraits = mChainITS->GetITSVertexerTraits();
256 timeFrame = mChainITS->GetITSTimeframe();
257}
258
260{
261 return mCtx[iThread].mChain->GetDeviceO2Propagator();
262}
263
265{
266 prop->setGPUField(&mCtx[0].mRec->GetParam().polynomialField);
267}
Class of a TPC cluster in TPC-native coordinates (row, time)
int32_t i
int32_t retVal
uint32_t j
Definition RawData.h:0
TBranch * ptr
o2::its::VertexerTraits * GetITSVertexerTraits()
o2::its::TimeFrame * GetITSTimeframe()
o2::its::TrackerTraits * GetITSTrackerTraits()
int32_t unregisterMemoryForGPU(const void *ptr)
const o2::base::Propagator * GetDeviceO2Propagator(int32_t iThread=0) const
int32_t Initialize(const GPUO2InterfaceConfiguration &config)
void setErrorCodeOutput(std::vector< std::array< uint32_t, 4 > > *v)
void UseGPUPolynomialFieldInPropagator(o2::base::Propagator *prop) const
void DumpEvent(int32_t nEvent, GPUTrackingInOutPointers *data)
int32_t RunTracking(GPUTrackingInOutPointers *data, GPUInterfaceOutputs *outputs=nullptr, uint32_t iThread=0, GPUInterfaceInputUpdate *inputUpdateCallback=nullptr)
void GetITSTraits(o2::its::TrackerTraits *&trackerTraits, o2::its::VertexerTraits *&vertexerTraits, o2::its::TimeFrame *&timeFrame)
int32_t registerMemoryForGPU(const void *ptr, size_t size)
void Clear(bool clearOutputs, uint32_t iThread=0)
int32_t UpdateCalibration(const GPUCalibObjectsConst &newCalib, const GPUNewCalibValues &newVals, uint32_t iThread=0)
static GPUReconstruction * CreateInstance(const GPUSettingsDeviceBackend &cfg)
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLboolean * data
Definition glcorearb.h:298
std::function< void(GPUTrackingInOutPointers *&data, GPUInterfaceOutputs *&outputs)> callback
const std::vector< TGraphAsymmErrors > * hist4
std::unique_ptr< std::thread > pipelineThread
std::unique_ptr< GPUReconstruction > mRec
std::unique_ptr< GPUTrackingOutputs > mOutputRegions
void set(void *p, size_t s)
std::function< void *(size_t)> allocator
GPUOutputControl * asArray()