2626#include " CalibdEdxContainer.h"
2727#include < iostream>
2828#include < fstream>
29+ #include < thread>
30+ #include < optional>
31+ #include < mutex>
2932
3033using namespace o2 ::gpu;
3134
@@ -37,77 +40,99 @@ GPUO2Interface::~GPUO2Interface() { Deinitialize(); }
3740
3841int GPUO2Interface::Initialize (const GPUO2InterfaceConfiguration& config)
3942{
40- if (mInitialized ) {
43+ if (mNContexts ) {
4144 return (1 );
4245 }
4346 mConfig .reset (new GPUO2InterfaceConfiguration (config));
44- mContinuous = mConfig ->configGRP .continuousMaxTimeBin != 0 ;
45- mRec .reset (GPUReconstruction::CreateInstance (mConfig ->configDeviceBackend ));
46- if (mRec == nullptr ) {
47- GPUError (" Error obtaining instance of GPUReconstruction" );
48- return 1 ;
49- }
50- mChain = mRec ->AddChain <GPUChainTracking>(mConfig ->configInterface .maxTPCHits , mConfig ->configInterface .maxTRDTracklets );
51- mChain ->mConfigDisplay = &mConfig ->configDisplay ;
52- mChain ->mConfigQA = &mConfig ->configQA ;
47+ mNContexts = mConfig ->configProcessing .doublePipeline ? 2 : 1 ;
48+ mCtx .reset (new GPUO2Interface::processingContext[mNContexts ]);
5349 if (mConfig ->configWorkflow .inputs .isSet (GPUDataTypes::InOutType::TPCRaw)) {
5450 mConfig ->configGRP .needsClusterer = 1 ;
5551 }
5652 if (mConfig ->configWorkflow .inputs .isSet (GPUDataTypes::InOutType::TPCCompressedClusters)) {
5753 mConfig ->configGRP .doCompClusterDecode = 1 ;
5854 }
59- mRec ->SetSettings (&mConfig ->configGRP , &mConfig ->configReconstruction , &mConfig ->configProcessing , &mConfig ->configWorkflow );
60- mChain ->SetCalibObjects (mConfig ->configCalib );
61-
62- if (mConfig ->configWorkflow .steps .isSet (GPUDataTypes::RecoStep::ITSTracking)) {
63- mChainITS = mRec ->AddChain <GPUChainITS>();
64- }
55+ for (unsigned int i = 0 ; i < mNContexts ; i++) {
56+ if (i) {
57+ mConfig ->configDeviceBackend .master = mCtx [0 ].mRec .get ();
58+ }
59+ mCtx [i].mRec .reset (GPUReconstruction::CreateInstance (mConfig ->configDeviceBackend ));
60+ mConfig ->configDeviceBackend .master = nullptr ;
61+ if (mCtx [i].mRec == nullptr ) {
62+ GPUError (" Error obtaining instance of GPUReconstruction" );
63+ mNContexts = 0 ;
64+ mCtx .reset (nullptr );
65+ return 1 ;
66+ }
67+ mCtx [i].mChain = mCtx [i].mRec ->AddChain <GPUChainTracking>(mConfig ->configInterface .maxTPCHits , mConfig ->configInterface .maxTRDTracklets );
68+ mCtx [i].mChain ->mConfigDisplay = &mConfig ->configDisplay ;
69+ mCtx [i].mChain ->mConfigQA = &mConfig ->configQA ;
70+ mCtx [i].mRec ->SetSettings (&mConfig ->configGRP , &mConfig ->configReconstruction , &mConfig ->configProcessing , &mConfig ->configWorkflow );
71+ mCtx [i].mChain ->SetCalibObjects (mConfig ->configCalib );
72+
73+ if (i == 0 && mConfig ->configWorkflow .steps .isSet (GPUDataTypes::RecoStep::ITSTracking)) {
74+ mChainITS = mCtx [i].mRec ->AddChain <GPUChainITS>();
75+ }
6576
66- mOutputRegions .reset (new GPUTrackingOutputs);
67- if (mConfig ->configInterface .outputToExternalBuffers ) {
68- for (unsigned int i = 0 ; i < mOutputRegions ->count (); i++) {
69- mChain ->SetSubOutputControl (i, &mOutputRegions ->asArray ()[i]);
77+ mCtx [i].mOutputRegions .reset (new GPUTrackingOutputs);
78+ if (mConfig ->configInterface .outputToExternalBuffers ) {
79+ for (unsigned int j = 0 ; j < mCtx [i].mOutputRegions ->count (); j++) {
80+ mCtx [i].mChain ->SetSubOutputControl (j, &mCtx [i].mOutputRegions ->asArray ()[j]);
81+ }
82+ GPUOutputControl dummy;
83+ dummy.set ([](size_t size) -> void * {throw std::runtime_error (" invalid output memory request, no common output buffer set" ); return nullptr ; });
84+ mCtx [i].mRec ->SetOutputControl (dummy);
7085 }
71- GPUOutputControl dummy;
72- dummy.set ([](size_t size) -> void * {throw std::runtime_error (" invalid output memory request, no common output buffer set" ); return nullptr ; });
73- mRec ->SetOutputControl (dummy);
74- }
7586
76- if (mRec ->Init ()) {
77- return (1 );
87+ if (i == 0 && mCtx [i].mRec ->Init ()) {
88+ mNContexts = 0 ;
89+ mCtx .reset (nullptr );
90+ return (1 );
91+ }
92+ if (!mCtx [i].mRec ->IsGPU () && mCtx [i].mRec ->GetProcessingSettings ().memoryAllocationStrategy == GPUMemoryResource::ALLOCATION_INDIVIDUAL ) {
93+ mCtx [i].mRec ->MemoryScalers ()->factor *= 2 ;
94+ }
7895 }
79- if (! mRec -> IsGPU () && mRec -> GetProcessingSettings (). memoryAllocationStrategy == GPUMemoryResource:: ALLOCATION_INDIVIDUAL ) {
80- mRec ->MemoryScalers ()-> factor *= 2 ;
96+ if (mConfig -> configProcessing . doublePipeline ) {
97+ mPipelineThread . reset ( new std::thread ([ this ]() { mCtx [ 0 ]. mRec ->RunPipelineWorker (); })) ;
8198 }
82- mInitialized = true ;
8399 return (0 );
84100}
85101
86102void GPUO2Interface::Deinitialize ()
87103{
88- if (mInitialized ) {
89- mRec ->Finalize ();
90- mRec .reset ();
104+ if (mNContexts ) {
105+ if (mConfig ->configProcessing .doublePipeline ) {
106+ mCtx [0 ].mRec ->TerminatePipelineWorker ();
107+ mPipelineThread ->join ();
108+ }
109+ for (unsigned int i = 0 ; i < mNContexts ; i++) {
110+ mCtx [i].mRec ->Finalize ();
111+ }
112+ mCtx [0 ].mRec ->Exit ();
113+ for (int i = mNContexts - 1 ; i >= 0 ; i--) {
114+ mCtx [i].mRec .reset ();
115+ }
91116 }
92- mInitialized = false ;
117+ mNContexts = 0 ;
93118}
94119
95120void GPUO2Interface::DumpEvent (int nEvent, GPUTrackingInOutPointers* data)
96121{
97122 if (mConfig ->configProcessing .doublePipeline ) {
98123 throw std::runtime_error (" Cannot dump events in double pipeline mode" );
99124 }
100- mChain ->ClearIOPointers ();
101- mChain ->mIOPtrs = *data;
125+ mCtx [ 0 ]. mChain ->ClearIOPointers ();
126+ mCtx [ 0 ]. mChain ->mIOPtrs = *data;
102127 char fname[1024 ];
103128 snprintf (fname, 1024 , " event.%d.dump" , nEvent);
104- mChain ->DumpData (fname);
129+ mCtx [ 0 ]. mChain ->DumpData (fname);
105130 if (nEvent == 0 ) {
106131#ifdef GPUCA_BUILD_QA
107132 if (mConfig ->configProcessing .runMC ) {
108- mChain ->ForceInitQA ();
133+ mCtx [ 0 ]. mChain ->ForceInitQA ();
109134 snprintf (fname, 1024 , " mc.%d.dump" , nEvent);
110- mChain ->GetQA ()->DumpO2MCData (fname);
135+ mCtx [ 0 ]. mChain ->GetQA ()->DumpO2MCData (fname);
111136 }
112137#endif
113138 }
@@ -118,61 +143,55 @@ void GPUO2Interface::DumpSettings()
118143 if (mConfig ->configProcessing .doublePipeline ) {
119144 throw std::runtime_error (" Cannot dump events in double pipeline mode" );
120145 }
121- mChain ->DoQueuedCalibUpdates (-1 );
122- mRec ->DumpSettings ();
146+ mCtx [ 0 ]. mChain ->DoQueuedCalibUpdates (-1 );
147+ mCtx [ 0 ]. mRec ->DumpSettings ();
123148}
124149
125- int GPUO2Interface::RunTracking (GPUTrackingInOutPointers* data, GPUInterfaceOutputs* outputs)
150+ int GPUO2Interface::RunTracking (GPUTrackingInOutPointers* data, GPUInterfaceOutputs* outputs, unsigned int iThread )
126151{
127- if (! mInitialized ) {
152+ if (mNContexts <= iThread ) {
128153 return (1 );
129154 }
130155
131- mChain ->mIOPtrs = *data;
156+ mCtx [iThread]. mChain ->mIOPtrs = *data;
132157 if (mConfig ->configInterface .outputToExternalBuffers ) {
133- for (unsigned int i = 0 ; i < mOutputRegions ->count (); i++) {
158+ for (unsigned int i = 0 ; i < mCtx [iThread]. mOutputRegions ->count (); i++) {
134159 if (outputs->asArray ()[i].allocator ) {
135- mOutputRegions ->asArray ()[i].set (outputs->asArray ()[i].allocator );
160+ mCtx [iThread]. mOutputRegions ->asArray ()[i].set (outputs->asArray ()[i].allocator );
136161 } else if (outputs->asArray ()[i].ptrBase ) {
137- mOutputRegions ->asArray ()[i].set (outputs->asArray ()[i].ptrBase , outputs->asArray ()[i].size );
162+ mCtx [iThread]. mOutputRegions ->asArray ()[i].set (outputs->asArray ()[i].ptrBase , outputs->asArray ()[i].size );
138163 } else {
139- mOutputRegions ->asArray ()[i].reset ();
164+ mCtx [iThread]. mOutputRegions ->asArray ()[i].reset ();
140165 }
141166 }
142167 }
143168
144- int retVal = mRec ->RunChains ();
169+ int retVal = mCtx [iThread]. mRec ->RunChains ();
145170 if (retVal == 2 ) {
146171 retVal = 0 ; // 2 signals end of event display, ignore
147172 }
148- if (mConfig ->configQA .shipToQC && mChain ->QARanForTF ()) {
149- outputs->qa .hist1 = &mChain ->GetQA ()->getHistograms1D ();
150- outputs->qa .hist2 = &mChain ->GetQA ()->getHistograms2D ();
151- outputs->qa .hist3 = &mChain ->GetQA ()->getHistograms1Dd ();
152- outputs->qa .hist4 = &mChain ->GetQA ()->getGraphs ();
173+ if (mConfig ->configQA .shipToQC && mCtx [iThread]. mChain ->QARanForTF ()) {
174+ outputs->qa .hist1 = &mCtx [iThread]. mChain ->GetQA ()->getHistograms1D ();
175+ outputs->qa .hist2 = &mCtx [iThread]. mChain ->GetQA ()->getHistograms2D ();
176+ outputs->qa .hist3 = &mCtx [iThread]. mChain ->GetQA ()->getHistograms1Dd ();
177+ outputs->qa .hist4 = &mCtx [iThread]. mChain ->GetQA ()->getGraphs ();
153178 outputs->qa .newQAHistsCreated = true ;
154179 }
155- *data = mChain ->mIOPtrs ;
180+ *data = mCtx [iThread]. mChain ->mIOPtrs ;
156181
157182 return retVal;
158183}
159184
160- void GPUO2Interface::Clear (bool clearOutputs) { mRec ->ClearAllocatedMemory (clearOutputs); }
161-
162- void GPUO2Interface::GetClusterErrors2 (int row, float z, float sinPhi, float DzDs, short clusterState, float & ErrY2, float & ErrZ2) const
163- {
164- mRec ->GetParam ().GetClusterErrors2 (row, z, sinPhi, DzDs, ErrY2, ErrZ2);
165- mRec ->GetParam ().UpdateClusterError2ByState (clusterState, ErrY2, ErrZ2);
166- }
185+ void GPUO2Interface::Clear (bool clearOutputs, unsigned int iThread) { mCtx [iThread].mRec ->ClearAllocatedMemory (clearOutputs); }
167186
168187int GPUO2Interface::registerMemoryForGPU (const void * ptr, size_t size)
169188{
170- return mRec ->registerMemoryForGPU (ptr, size);
189+ return mCtx [ 0 ]. mRec ->registerMemoryForGPU (ptr, size);
171190}
172191
173192int GPUO2Interface::unregisterMemoryForGPU (const void * ptr)
174193{
175- return mRec ->unregisterMemoryForGPU (ptr);
194+ return mCtx [ 0 ]. mRec ->unregisterMemoryForGPU (ptr);
176195}
177196
178197std::unique_ptr<TPCPadGainCalib> GPUO2Interface::getPadGainCalibDefault ()
@@ -190,15 +209,17 @@ std::unique_ptr<o2::tpc::CalibdEdxContainer> GPUO2Interface::getCalibdEdxContain
190209 return std::make_unique<o2::tpc::CalibdEdxContainer>();
191210}
192211
193- int GPUO2Interface::UpdateCalibration (const GPUCalibObjectsConst& newCalib, const GPUNewCalibValues& newVals)
212+ int GPUO2Interface::UpdateCalibration (const GPUCalibObjectsConst& newCalib, const GPUNewCalibValues& newVals, unsigned int iThread )
194213{
195- mChain ->SetUpdateCalibObjects (newCalib, newVals);
214+ mCtx [iThread]. mChain ->SetUpdateCalibObjects (newCalib, newVals);
196215 return 0 ;
197216}
198217
199218void GPUO2Interface::setErrorCodeOutput (std::vector<std::array<unsigned int , 4 >>* v)
200219{
201- mRec ->setErrorCodeOutput (v);
220+ for (unsigned int i = 0 ; i < mNContexts ; i++) {
221+ mCtx [i].mRec ->setErrorCodeOutput (v);
222+ }
202223}
203224
204225void GPUO2Interface::GetITSTraits (o2::its::TrackerTraits*& trackerTraits, o2::its::VertexerTraits*& vertexerTraits, o2::its::TimeFrame*& timeFrame)
0 commit comments