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 "GPUChainTrackingGetters.inc"
19#include "GPUChainITS.h"
21#include "GPUOutputControl.h"
24#include "GPUParam.inc"
25#include "GPUQA.h"
26#include "GPUOutputControl.h"
28#include <iostream>
29#include <fstream>
30#include <thread>
31#include <optional>
32#include <mutex>
33
34using namespace o2::gpu;
35
37
38namespace o2::gpu
39{
41 std::unique_ptr<GPUReconstruction> mRec;
43 std::unique_ptr<GPUTrackingOutputs> mOutputRegions;
44};
45
47 std::unique_ptr<std::thread> pipelineThread;
48};
49} // namespace o2::gpu
50
52
54
56{
57 if (mNContexts) {
58 return (1);
59 }
60 mConfig.reset(new GPUO2InterfaceConfiguration(config));
61 mNContexts = mConfig->configProcessing.doublePipeline ? 2 : 1;
62 mCtx.reset(new GPUO2Interface_processingContext[mNContexts]);
63 if (mConfig->configWorkflow.inputs.isSet(GPUDataTypes::InOutType::TPCRaw)) {
64 mConfig->configGRP.needsClusterer = 1;
65 }
66 if (mConfig->configWorkflow.inputs.isSet(GPUDataTypes::InOutType::TPCCompressedClusters)) {
67 mConfig->configGRP.doCompClusterDecode = 1;
68 }
69 for (uint32_t i = 0; i < mNContexts; i++) {
70 if (i) {
71 mConfig->configDeviceBackend.master = mCtx[0].mRec.get();
72 }
73 mCtx[i].mRec.reset(GPUReconstruction::CreateInstance(mConfig->configDeviceBackend));
74 mConfig->configDeviceBackend.master = nullptr;
75 if (mCtx[i].mRec == nullptr) {
76 GPUError("Error obtaining instance of GPUReconstruction");
77 mNContexts = 0;
78 mCtx.reset(nullptr);
79 return 1;
80 }
81 }
82 for (uint32_t i = 0; i < mNContexts; i++) {
83 mCtx[i].mChain = mCtx[i].mRec->AddChain<GPUChainTracking>(mConfig->configInterface.maxTPCHits, mConfig->configInterface.maxTRDTracklets);
84 if (i) {
85 mCtx[i].mChain->SetQAFromForeignChain(mCtx[0].mChain);
86 }
87 mCtx[i].mChain->mConfigDisplay = &mConfig->configDisplay;
88 mCtx[i].mChain->mConfigQA = &mConfig->configQA;
89 mCtx[i].mRec->SetSettings(&mConfig->configGRP, &mConfig->configReconstruction, &mConfig->configProcessing, &mConfig->configWorkflow);
90 mCtx[i].mChain->SetCalibObjects(mConfig->configCalib);
91
92 if (i == 0 && mConfig->configWorkflow.steps.isSet(GPUDataTypes::RecoStep::ITSTracking)) {
93 mChainITS = mCtx[i].mRec->AddChain<GPUChainITS>();
94 }
95
96 mCtx[i].mOutputRegions.reset(new GPUTrackingOutputs);
97 if (mConfig->configInterface.outputToExternalBuffers) {
98 for (uint32_t j = 0; j < mCtx[i].mOutputRegions->count(); j++) {
99 mCtx[i].mChain->SetSubOutputControl(j, &mCtx[i].mOutputRegions->asArray()[j]);
100 }
101 GPUOutputControl dummy;
102 dummy.set([](size_t size) -> void* {throw std::runtime_error("invalid output memory request, no common output buffer set"); return nullptr; });
103 mCtx[i].mRec->SetOutputControl(dummy);
104 }
105 }
106 for (uint32_t i = 0; i < mNContexts; i++) {
107 if (i == 0 && mCtx[i].mRec->Init()) {
108 mNContexts = 0;
109 mCtx.reset(nullptr);
110 return (1);
111 }
112 if (!mCtx[i].mRec->IsGPU() && mCtx[i].mRec->GetProcessingSettings().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL) {
113 mCtx[i].mRec->MemoryScalers()->factor *= 2;
114 }
115 }
116 if (mConfig->configProcessing.doublePipeline) {
117 mInternals->pipelineThread.reset(new std::thread([this]() { mCtx[0].mRec->RunPipelineWorker(); }));
118 }
119 return (0);
120}
121
123{
124 if (mNContexts) {
125 if (mConfig->configProcessing.doublePipeline) {
126 mCtx[0].mRec->TerminatePipelineWorker();
127 mInternals->pipelineThread->join();
128 }
129 for (uint32_t i = 0; i < mNContexts; i++) {
130 mCtx[i].mRec->Finalize();
131 }
132 mCtx[0].mRec->Exit();
133 for (int32_t i = mNContexts - 1; i >= 0; i--) {
134 mCtx[i].mRec.reset();
135 }
136 }
137 mNContexts = 0;
138}
139
141{
142 mCtx[0].mChain->ClearIOPointers();
143 mCtx[0].mChain->mIOPtrs = *data;
144 char fname[1024];
145 snprintf(fname, 1024, "event.%d.dump", nEvent);
146 mCtx[0].mChain->DumpData(fname);
147 if (nEvent == 0) {
148#ifdef GPUCA_BUILD_QA
149 if (mConfig->configProcessing.runMC) {
150 mCtx[0].mChain->ForceInitQA();
151 snprintf(fname, 1024, "mc.%d.dump", nEvent);
152 mCtx[0].mChain->GetQA()->UpdateChain(mCtx[0].mChain);
153 mCtx[0].mChain->GetQA()->DumpO2MCData(fname);
154 }
155#endif
156 }
157}
158
160{
161 mCtx[0].mChain->DoQueuedUpdates(-1);
162 mCtx[0].mRec->DumpSettings();
163}
164
166{
167 if (mNContexts <= iThread) {
168 return (1);
169 }
170
171 mCtx[iThread].mChain->mIOPtrs = *data;
172
173 auto setOutputs = [this, iThread](GPUInterfaceOutputs* outputs) {
174 if (mConfig->configInterface.outputToExternalBuffers) {
175 for (uint32_t i = 0; i < mCtx[iThread].mOutputRegions->count(); i++) {
176 if (outputs->asArray()[i].allocator) {
177 mCtx[iThread].mOutputRegions->asArray()[i].set(outputs->asArray()[i].allocator);
178 } else if (outputs->asArray()[i].ptrBase) {
179 mCtx[iThread].mOutputRegions->asArray()[i].set(outputs->asArray()[i].ptrBase, outputs->asArray()[i].size);
180 } else {
181 mCtx[iThread].mOutputRegions->asArray()[i].reset();
182 }
183 }
184 }
185 };
186
187 auto inputWaitCallback = [this, iThread, inputUpdateCallback, &data, &outputs, &setOutputs]() {
188 GPUTrackingInOutPointers* updatedData;
189 GPUInterfaceOutputs* updatedOutputs;
190 if (inputUpdateCallback->callback) {
191 inputUpdateCallback->callback(updatedData, updatedOutputs);
192 mCtx[iThread].mChain->mIOPtrs = *updatedData;
193 outputs = updatedOutputs;
194 data = updatedData;
195 setOutputs(outputs);
196 }
197 if (inputUpdateCallback->notifyCallback) {
198 inputUpdateCallback->notifyCallback();
199 }
200 };
201
202 if (inputUpdateCallback) {
203 mCtx[iThread].mChain->SetFinalInputCallback(inputWaitCallback);
204 } else {
205 mCtx[iThread].mChain->SetFinalInputCallback(nullptr);
206 }
207 if (!inputUpdateCallback || !inputUpdateCallback->callback) {
208 setOutputs(outputs);
209 }
210
211 int32_t retVal = mCtx[iThread].mRec->RunChains();
212 if (retVal == 2) {
213 retVal = 0; // 2 signals end of event display, ignore
214 }
215 if (mConfig->configQA.shipToQC && mCtx[iThread].mChain->QARanForTF()) {
216 outputs->qa.hist1 = &mCtx[iThread].mChain->GetQA()->getHistograms1D();
217 outputs->qa.hist2 = &mCtx[iThread].mChain->GetQA()->getHistograms2D();
218 outputs->qa.hist3 = &mCtx[iThread].mChain->GetQA()->getHistograms1Dd();
219 outputs->qa.hist4 = &mCtx[iThread].mChain->GetQA()->getGraphs();
220 outputs->qa.newQAHistsCreated = true;
221 }
222 *data = mCtx[iThread].mChain->mIOPtrs;
223
224 return retVal;
225}
226
227void GPUO2Interface::Clear(bool clearOutputs, uint32_t iThread) { mCtx[iThread].mRec->ClearAllocatedMemory(clearOutputs); }
228
230{
231 return mCtx[0].mRec->registerMemoryForGPU(ptr, size);
232}
233
235{
236 return mCtx[0].mRec->unregisterMemoryForGPU(ptr);
237}
238
239int32_t GPUO2Interface::UpdateCalibration(const GPUCalibObjectsConst& newCalib, const GPUNewCalibValues& newVals, uint32_t iThread)
240{
241 for (uint32_t i = 0; i < mNContexts; i++) {
242 mCtx[i].mChain->SetUpdateCalibObjects(newCalib, newVals);
243 }
244 return 0;
245}
246
247void GPUO2Interface::setErrorCodeOutput(std::vector<std::array<uint32_t, 4>>* v)
248{
249 for (uint32_t i = 0; i < mNContexts; i++) {
250 mCtx[i].mRec->setErrorCodeOutput(v);
251 }
252}
253
255{
256 trackerTraits = mChainITS->GetITSTrackerTraits();
257 vertexerTraits = mChainITS->GetITSVertexerTraits();
258 timeFrame = mChainITS->GetITSTimeframe();
259}
260
262{
263 return mCtx[iThread].mChain->GetDeviceO2Propagator();
264}
265
267{
268 prop->setGPUField(&mCtx[0].mRec->GetParam().polynomialField);
269}
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()