42#include <sys/select.h>
56#if not(defined(__ARM_NEON) or defined(__aarch64__))
81std::unique_ptr<GPUReconstructionTimeframe>
tf;
90#if not(defined(__ARM_NEON) or defined(__aarch64__))
91#ifdef FE_DFL_DISABLE_SSE_DENORMS_ENV
92 fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV);
94#ifndef _MM_FLUSH_ZERO_ON
95#define _MM_FLUSH_ZERO_ON 0x8000
97#ifndef _MM_DENORMALS_ZERO_ON
98#define _MM_DENORMALS_ZERO_ON 0x0040
100 _mm_setcsr(_mm_getcsr() | (_MM_FLUSH_ZERO_ON | _MM_DENORMALS_ZERO_ON));
110 printf(
"Error parsing command line parameters\n");
115 printf(
"Config Dump before ReadConfiguration\n");
122 setlocale(LC_ALL,
"en_US.utf-8");
123 setlocale(LC_NUMERIC,
"en_US.utf-8");
129 printf(
"Setting affinitiy to restrict on CPU core %d\n",
configStandalone.cpuAffinity);
130 if (0 != sched_setaffinity(0,
sizeof(
mask), &
mask)) {
131 printf(
"Error setting CPU affinity\n");
136 printf(
"Setting FIFO scheduler\n");
138 sched_getparam(0, &
param);
139 param.sched_priority = 1;
140 if (0 != sched_setscheduler(0, SCHED_FIFO, &
param)) {
141 printf(
"Error setting scheduler\n");
146 feenableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
154 printf(
"Affinity setting not supported on Windows\n");
158 printf(
"FIFO Scheduler setting not supported on Windows\n");
162 printf(
"FPE not supported on Windows\n");
166#ifndef GPUCA_TPC_GEOMETRY_O2
167#error Why was configStandalone.rec.tpc.mergerReadFromTrackerDirectly = 0 needed?
174#ifndef GPUCA_BUILD_QA
176 printf(
"QA not enabled in build\n");
181 printf(
"Cannot run asynchronous processing with double pipeline\n");
185 printf(
"Double pipeline mode needs at least 3 runs per event and external output. To cycle though multiple events, use --preloadEvents and --runs n for n iterations round-robin\n");
189 printf(
"Cannot run --MERGE and --SIMBUNCHES togeterh\n");
206 printf(
"Can only produce QA pdf output when input files are specified!\n");
235 bool forceEmptyMemory = getenv(
"LD_PRELOAD") && strstr(getenv(
"LD_PRELOAD"),
"valgrind") !=
nullptr;
237 if (forceEmptyMemory) {
238 printf(
"Valgrind detected, emptying GPU output memory to avoid false positive undefined reads");
243 if (forceEmptyMemory) {
265 printf(
"No GPU backend / device found, running on CPU is disabled due to runGPUforce\n");
277 printf(
"Config Dump after ReadConfiguration\n");
293 printf(
"Error reading event config file\n");
310 GPUSettingsProcessing procSet;
326 printf(
"ERROR: requested to overlay continuous data - not supported\n");
330 printf(
"Continuous mode forced\n");
341 printf(
"Standalone Test Framework for CA Tracker - Using CPU\n");
343 printf(
"Standalone Test Framework for CA Tracker - Using GPU\n");
350 throw std::runtime_error(
"Requested display not available");
352 printf(
"Enabling event display (%s backend)\n",
eventDisplay->frontendName());
355 procSet.runMC =
true;
360 procSet.runMC =
true;
363 steps.
steps = GPUDataTypes::RecoStep::AllRecoSteps;
367 steps.
steps.
setBits(GPUDataTypes::RecoStep::TRDTracking,
false);
380 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCMerging,
false);
381 steps.
steps.
setBits(GPUDataTypes::RecoStep::TRDTracking,
false);
382 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCdEdx,
false);
383 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCCompression,
false);
384 steps.
steps.
setBits(GPUDataTypes::RecoStep::Refit,
false);
388 steps.
steps.
setBits(GPUDataTypes::RecoStep::TRDTracking,
false);
390 steps.
inputs.
set(GPUDataTypes::InOutType::TPCClusters, GPUDataTypes::InOutType::TRDTracklets);
391 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCDecompression,
false);
392 steps.
inputs.
setBits(GPUDataTypes::InOutType::TPCCompressedClusters,
false);
394 steps.
inputs.
setBits(GPUDataTypes::InOutType::TPCCompressedClusters,
true);
395 steps.
inputs.
setBits(GPUDataTypes::InOutType::TPCClusters,
false);
396 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCCompression,
false);
397 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCClusterFinding,
false);
398 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCDecompression,
true);
399 steps.
outputs.
setBits(GPUDataTypes::InOutType::TPCCompressedClusters,
false);
402 steps.
inputs.
setBits(GPUDataTypes::InOutType::TPCClusters,
false);
404 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCClusterFinding,
false);
415 steps.
outputs.
setBits(GPUDataTypes::InOutType::TPCSectorTracks,
false);
416 steps.
outputs.
setBits(GPUDataTypes::InOutType::TPCMergedTracks, steps.
steps.
isSet(GPUDataTypes::RecoStep::TPCMerging));
417 steps.
outputs.
setBits(GPUDataTypes::InOutType::TPCCompressedClusters, steps.
steps.
isSet(GPUDataTypes::RecoStep::TPCCompression));
419 steps.
outputs.
setBits(GPUDataTypes::InOutType::TPCClusters, steps.
steps.
isSet(GPUDataTypes::RecoStep::TPCClusterFinding));
421 if (steps.
steps.
isSet(GPUDataTypes::RecoStep::TRDTracking)) {
422 if (recSet.tpc.nWays > 1) {
423 recSet.tpc.nWaysOuter = 1;
425 if (procSet.createO2Output && !procSet.trdTrackModelO2) {
426 procSet.createO2Output = 1;
433 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCdEdx, 0);
435 recSet.useMatLUT =
false;
437 procSet.eventDisplay =
nullptr;
450 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCDecompression,
true);
451 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCdEdx,
true);
452 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCCompression,
false);
453 steps.
steps.
setBits(GPUDataTypes::RecoStep::TPCClusterFinding,
false);
454 steps.
inputs.
setBits(GPUDataTypes::InOutType::TPCRaw,
false);
455 steps.
inputs.
setBits(GPUDataTypes::InOutType::TPCClusters,
false);
456 steps.
inputs.
setBits(GPUDataTypes::InOutType::TPCCompressedClusters,
true);
457 steps.
outputs.
setBits(GPUDataTypes::InOutType::TPCCompressedClusters,
false);
458 procSet.runMC =
false;
459 procSet.runQA =
false;
461 procSet.runCompressionStatistics = 0;
462 procSet.rtc.optSpecialCode = 0;
464 procSet.tpcInputWithClusterRejection = 1;
466 recSet.tpc.disableRefitAttachment = 0xFF;
467 recSet.tpc.looperInterpolationInExtraPass = 0;
468 recSet.maxTrackQPtB5 = CAMath::Min(recSet.maxTrackQPtB5, recSet.tpc.rejectQPtB5);
469 recSet.useMatLUT =
true;
492 procSet.o2PropagatorUseGPUField =
true;
495 printf(
"Error initializing GPUReconstruction!\n");
500 printf(
"ERROR registering memory for the GPU!!!\n");
506 printf(
"ERROR registering input memory for the GPU!!!\n");
527#if defined(GPUCA_TPC_GEOMETRY_O2) && defined(GPUCA_BUILD_QA) && !defined(GPUCA_O2_LIB)
535 throw std::runtime_error(
"Error reading O2 MC dump");
542 printf(
"Converting Native to Legacy ClusterData for overlaying - WARNING: No raw clusters produced - Compression etc will not run!!!\n");
552 if (
tf->LoadCreateTimeFrame(iEvent)) {
556 if (
tf->LoadMergedEvents(iEvent)) {
566 if (encodeZS || zsFilter) {
568 printf(
"Need digit input to run ZS\n");
584 printf(
"Converting Legacy Raw Cluster to Native\n");
599 printf(
"Need cluster native data for on-the-fly TPC transform\n");
621 if (nTracksTotal && nClustersTotal) {
622 *nTracksTotal += nTracks;
629 int32_t iRun = 0, iteration = 0;
630 while ((iteration =
nIteration.fetch_add(1)) < runs) {
632 printf(
"Run %d (thread %d)\n", iteration + 1, threadId);
640 printf(
"Running synchronous phase\n");
643 chainTrackingUse->
mIOPtrs = ioPtrs;
646 timerPipeline->Start();
656 timerPipeline->Stop();
663 if (tmpRetVal == 0 || tmpRetVal == 2) {
664 OutputStat(chainTrackingUse, iRun == 0 ? nTracksTotal :
nullptr, iRun == 0 ? nClustersTotal :
nullptr);
674 printf(
"Running asynchronous phase\n");
699 if (tmpRetVal == 0 || tmpRetVal == 2) {
711 if (tmpRetVal == 2) {
716 printf(
"Non-FATAL GPU error occured, ignoring\n");
718 if (tmpRetVal != 2) {
719 printf(
"Error occured\n");
732int32_t
main(
int argc,
char** argv)
734 std::unique_ptr<GPUReconstruction> recUnique, recUniqueAsync, recUniquePipeline;
745 deviceSet.
master =
nullptr;
747 rec = recUnique.get();
758 printf(
"Error initializing GPUReconstruction\n");
788 std::unique_ptr<std::thread> pipelineThread;
794 std::random_device
rd;
805 in.open(
filename, std::ifstream::binary);
839 printf(
"Preloading events%s",
configStandalone.proc.debugLevel >= 2 ?
"\n" :
"");
844 printf(
"Loading event %d\n",
i);
853 for (int32_t iRunOuter = 0; iRunOuter <
configStandalone.runs2; iRunOuter++) {
859 printf(
"RUN2: %d\n", iRunOuter);
861 int64_t nTracksTotal = 0;
862 int64_t nClustersTotal = 0;
863 int32_t nEventsProcessed = 0;
883 snprintf(fname, 1024,
"event.%d.dump", nEventsProcessed);
885 if (nEventsProcessed == 0) {
893 printf(
"Cannot override max time bin for non-continuous data!\n");
908 printf(
"Processing Event %d\n", iEvent);
912 double pipelineWalltime = 1.;
915 if (
RunBenchmark(
rec,
chainTracking, 1, iEvent, &nTracksTotal, &nClustersTotal) ||
RunBenchmark(
recPipeline,
chainTrackingPipeline, 2, iEvent, &nTracksTotal, &nClustersTotal)) {
920 if (pipeline1.get() || pipeline2.get()) {
935 const int32_t nOrbits = 32;
936 const double colRate = 50000;
937 const double orbitRate = 11245;
938 const double nClsPerTF = 755851. * nOrbits * colRate / orbitRate;
940 const double nGPUsReq = timePerTF * orbitRate / nOrbits;
942 snprintf(stat, 1024,
"Sync phase: %.2f sec per %d orbit TF, %.1f GPUs required", timePerTF, nOrbits, nGPUsReq);
945 snprintf(stat + strlen(stat), 1024 - strlen(stat),
" - Async phase: %f sec per TF", timePerTF);
947 printf(
"%s (Measured %s time - Extrapolated from %d clusters to %d)\n", stat,
configStandalone.proc.debugLevel ?
"kernel" :
"wall", (int32_t)
nClusters, (int32_t)nClsPerTF);
955 if (nEventsProcessed > 1) {
956 printf(
"Total: %ld clusters, %ld tracks\n", nClustersTotal, nTracksTotal);
967 fedisableexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW);
973 pipelineThread->join();
979 printf(
"Error unregistering memory\n");
985 printf(
"Press a key to exit!\n");
Helper class to access correction maps.
#define GPUCA_OPERATOR_NEW_ALIGNMENT
#define GPUCA_EVDUMP_FILE
double GetCurrentElapsedTime(bool reset=false)
bitfield & setBits(const bitfield v, bool w)
bool isSet(const bitfield &v) const
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
void SetQAFromForeignChain(GPUChainTracking *chain)
const CorrectionMapsHelper * GetTPCTransformHelper() const
const GPUTPCGMMerger & GetTPCMerger() const
void ConvertNativeToClusterDataLegacy()
void ConvertZSFilter(bool zs12bit)
void SetO2Propagator(const o2::base::Propagator *prop)
const GPUTRDGeometry * GetTRDGeometry() const
void DumpData(const char *filename)
const o2::base::MatLayerCylSet * GetMatLUT() const
void ConvertRun2RawToNative()
const GPUSettingsDisplay * mConfigDisplay
const GPUQA * GetQA() const
void ConvertZSEncoder(int32_t version)
GPUTrackingInOutPointers & mIOPtrs
struct o2::gpu::GPUChainTracking::InOutMemory mIOMem
int32_t ReadData(const char *filename)
const GPUSettingsQA * mConfigQA
const GPUSettingsProcessing & GetProcessingSettings() const
static constexpr int32_t NSECTORS
static DeviceType GetDeviceType(const char *type)
static GPUDisplayFrontendInterface * getFrontend(const char *type)
int32_t ReadO2MCData(const char *filename)
void UpdateChain(GPUChainTracking *chain)
static int32_t GetMaxTimeBin(const o2::tpc::ClusterNativeAccess &native)
static constexpr int32_t TPCZ
static constexpr int32_t DRIFT_TIME
static DeviceType GetDeviceType(const char *type)
void SetInputControl(void *ptr, size_t size)
void TerminatePipelineWorker()
virtual void startGPUProfiling()
void SetDebugLevelTmp(int32_t level)
const GPUParam & GetParam() const
static bool CheckInstanceAvailable(DeviceType type, bool verbose)
void SetSettings(float solenoidBzNominalGPU, const GPURecoStepConfiguration *workflow=nullptr)
T * AddChain(Args... args)
static GPUReconstruction * CreateInstance(const GPUSettingsDeviceBackend &cfg)
void UpdateSettings(const GPUSettingsGRP *g, const GPUSettingsProcessing *p=nullptr, const GPUSettingsRecDynamic *d=nullptr)
virtual int32_t RunChains()=0
void ClearAllocatedMemory(bool clearOutputs=true)
void PrintMemoryOverview()
void PrintMemoryStatistics()
double GetStatKernelTime()
const GPUSettingsProcessing & GetProcessingSettings() const
void DumpSettings(const char *dir="")
int32_t unregisterMemoryForGPU(const void *ptr)
int32_t registerMemoryForGPU(const void *ptr, size_t size)
const GPUSettingsGRP & GetGRPSettings() const
virtual void PrintKernelOccupancies()
void SetResetTimers(bool reset)
virtual void endGPUProfiling()
int32_t ReadSettings(const char *dir="")
void SetOutputControl(const GPUOutputControl &v)
static void RunEventGenerator(GPUChainTracking *rec)
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLenum GLenum GLsizei len
GPUSettingsStandalone configStandalone
int32_t qConfigParse(int argc, const char **argv, const char *filename)
std::unique_ptr< GPUReconstructionTimeframe > tf
int32_t RunBenchmark(GPUReconstruction *recUse, GPUChainTracking *chainTrackingUse, int32_t runs, int32_t iEvent, int64_t *nTracksTotal, int64_t *nClustersTotal, int32_t threadId=0, HighResTimer *timerPipeline=nullptr)
int32_t SetupReconstruction()
std::unique_ptr< char, void(*)(char *)> outputmemoryPipeline(nullptr, unique_ptr_aligned_delete)
std::atomic< uint32_t > nIteration
GPUReconstruction * recPipeline
std::unique_ptr< char, void(*)(char *)> outputmemory(nullptr, unique_ptr_aligned_delete)
int32_t nEventsInDirectory
int32_t ReadConfiguration(int argc, char **argv)
std::unique_ptr< char, void(*)(char *)> inputmemory(nullptr, unique_ptr_aligned_delete)
int32_t LoadEvent(int32_t iEvent, int32_t x)
std::vector< GPUTrackingInOutPointers > ioPtrEvents
GPUChainITS * chainITSPipeline
int32_t ReadEvent(int32_t n)
void unique_ptr_aligned_delete(char *v)
std::vector< GPUChainTracking::InOutMemory > ioMemEvents
std::unique_ptr< GPUDisplayFrontendInterface > eventDisplay
GPUChainTracking * chainTrackingAsync
GPUChainITS * chainITSAsync
GPUChainTracking * chainTrackingPipeline
GPUReconstruction * recAsync
void OutputStat(GPUChainTracking *t, int64_t *nTracksTotal=nullptr, int64_t *nClustersTotal=nullptr)
void SetCPUAndOSSettings()
std::atomic< uint32_t > nIterationEnd
GPUChainTracking * chainTracking
GPUDataTypes::RecoStepField stepsGPUMask
GPUDataTypes::InOutTypeField outputs
GPUDataTypes::RecoStepField steps
GPUDataTypes::InOutTypeField inputs
GPUReconstruction * master
int32_t doCompClusterDecode
int32_t grpContinuousMaxTimeBin
float solenoidBzNominalGPU
const o2::tpc::ClusterNativeAccess * clustersNative
const GPUTPCMCInfo * mcInfosTPC
uint32_t nClusterData[NSECTORS]
uint32_t nRawClusters[NSECTORS]
const o2::tpc::CompressedClustersFlat * tpcCompressedClusters
const AliHLTTPCClusterMCLabel * mcLabelsTPC
const GPUTrackingInOutZS * tpcZS
const AliHLTTPCRawCluster * rawClusters[NSECTORS]
const GPUTPCClusterData * clusterData[NSECTORS]
uint32_t nOutputTracksTPCO2
uint32_t nMergedTrackHits
const GPUTrackingInOutDigits * tpcPackedDigits
const GPUTPCMCInfoCol * mcInfosTPCCol
const GPUTPCGMMergedTrack * mergedTracks
GPUTPCGMPolynomialField polynomialField
typename std::vector< T, vecpod_allocator< T > > vecpod