From de1aa0a0801c28d64a5aa0e160dbfa84d58eeef4 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Wed, 11 Nov 2020 19:18:47 +0100 Subject: [PATCH 1/6] GPU: Add garbage collection to GPU TPC Standalone QA --- .../GPUTPCCompressionKernels.h | 1 - GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 145 ++++++++++-------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 8 +- 3 files changed, 86 insertions(+), 68 deletions(-) diff --git a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h index 06fb6a6ffa297..bcee016899094 100644 --- a/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h +++ b/GPU/GPUTracking/DataCompression/GPUTPCCompressionKernels.h @@ -42,7 +42,6 @@ class GPUTPCCompressionKernels : public GPUKernelTemplate template GPUd() static void Thread(int nBlocks, int nThreads, int iBlock, int iThread, GPUsharedref() GPUSharedMemory& GPUrestrict() smem, processorType& GPUrestrict() processors); - public: template class GPUTPCCompressionKernels_Compare { diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 50d3db0f8569c..c8b1600c68750 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -190,8 +190,6 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; -static TCanvas cfit; - #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" @@ -283,7 +281,27 @@ void GPUQA::createHist(T*& h, const char* name, Args... args) h = &p.first->back(); } -GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)) +namespace GPUCA_NAMESPACE::gpu +{ +struct GPUQAGarbageCollection { + std::tuple>, std::vector>, std::vector>, std::vector>, std::vector>> v; +}; +} // namespace GPUCA_NAMESPACE::gpu + +template +T* GPUQA::createGarbageCollected(Args... args) +{ + auto& v = std::get>>(mGarbageCollector->v); + v.emplace_back(std::make_unique(args...)); + return v.back().get(); +} +void GPUQA::clearGarbagageCollector() +{ + std::get>>(mGarbageCollector->v).clear(); // Make sure to depete TPad first due to ROOT ownership (std::tuple has no defined order in its destructor) + std::apply([](auto&&... args) { ((args.clear()), ...); }, mGarbageCollector->v); +} + +GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)), mGarbageCollector(std::make_unique()) { mRunForQC = chain == nullptr || mConfig.forQC; } @@ -295,6 +313,7 @@ GPUQA::~GPUQA() delete mHist2D; delete mHist1Dd; } + clearGarbagageCollector(); // Needed to guarantee correct order for ROOT ownership } inline bool GPUQA::MCComp(const mcLabel_t& a, const mcLabel_t& b) { return (GPUQA::GetMCLabelID(a) > GPUQA::GetMCLabelID(b)); } @@ -366,7 +385,7 @@ void GPUQA::doPerfFigure(float x, float y, float size) if (!PERF_FIGURE) { return; } - TLatex* t = new TLatex; + TLatex* t = createGarbageCollected(); t->SetNDC(kTRUE); t->SetTextColor(1); t->SetTextSize(size); @@ -393,7 +412,7 @@ int GPUQA::InitQACreateHistograms() for (int m = 0; m < 2; m++) { sprintf(name, "%s%s%s%sVs%s", m ? "eff" : "tracks", EFF_TYPES[i], FINDABLE_NAMES[j], PRIM_NAMES[k], VSPARAMETER_NAMES[l]); if (l == 4) { - std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], k == 0 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], binsPt.get()); } else { createHist(mEff[i][j][k][l][m], name, name, AXIS_BINS[l], AXES_MIN[l], AXES_MAX[l]); @@ -413,7 +432,7 @@ int GPUQA::InitQACreateHistograms() sprintf(name, "rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); sprintf(fname, "mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; createHist(mRes[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); createHist(mRes[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); } else { @@ -424,7 +443,7 @@ int GPUQA::InitQACreateHistograms() const float* axis = mConfig.nativeFitResolutions ? RES_AXES_NATIVE : RES_AXES; const int nbins = i == 4 && mConfig.nativeFitResolutions ? (10 * RES_AXIS_BINS[0]) : RES_AXIS_BINS[0]; if (j == 4) { - std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], mConfig.resPrimaries == 1 ? PT_MIN_PRIM : AXES_MIN[4], AXES_MAX[4])}; createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], binsPt.get()); } else { createHist(mRes2[i][j], name, name, nbins, -axis[i], axis[i], AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); @@ -438,7 +457,7 @@ int GPUQA::InitQACreateHistograms() sprintf(name, "pull_rms_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); sprintf(fname, "pull_mean_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; createHist(mPull[i][j][0], name, name, AXIS_BINS[j], binsPt.get()); createHist(mPull[i][j][1], fname, fname, AXIS_BINS[j], binsPt.get()); } else { @@ -447,7 +466,7 @@ int GPUQA::InitQACreateHistograms() } sprintf(name, "pull_%s_vs_%s", VSPARAMETER_NAMES[i], VSPARAMETER_NAMES[j]); if (j == 4) { - std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; + std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], AXES_MIN[4], AXES_MAX[4])}; createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], binsPt.get()); } else { createHist(mPull2[i][j], name, name, RES_AXIS_BINS[0], -PULL_AXIS, PULL_AXIS, AXIS_BINS[j], AXES_MIN[j], AXES_MAX[j]); @@ -460,7 +479,7 @@ int GPUQA::InitQACreateHistograms() int ioffset = i >= (2 * N_CLS_HIST - 1) ? (2 * N_CLS_HIST - 1) : i >= N_CLS_HIST ? N_CLS_HIST : 0; int itype = i >= (2 * N_CLS_HIST - 1) ? 2 : i >= N_CLS_HIST ? 1 : 0; sprintf(name, "clusters%s%s", CLUSTER_NAMES_SHORT[i - ioffset], CLUSTER_TYPES[itype]); - std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; + std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; createHist(mClusters[i], name, name, AXIS_BINS[4], binsPt.get()); } { @@ -471,7 +490,7 @@ int GPUQA::InitQACreateHistograms() // Create Tracks Histograms { sprintf(name, "tracks"); - std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; + std::unique_ptr binsPt{CreateLogAxis(AXIS_BINS[4], PT_MIN_CLUST, PT_MAX)}; createHist(mTracks, name, name, AXIS_BINS[4], binsPt.get()); } @@ -617,11 +636,11 @@ int GPUQA::InitQA() if (mConfig.matchMCLabels.size()) { unsigned int nFiles = mConfig.matchMCLabels.size(); - std::vector files(nFiles); + std::vector> files; std::vector>*> labelsBuffer(nFiles); std::vector>*> effBuffer(nFiles); for (unsigned int i = 0; i < nFiles; i++) { - files[i] = new TFile(mConfig.matchMCLabels[i]); + files.emplace_back(std::make_unique(mConfig.matchMCLabels[i])); labelsBuffer[i] = (std::vector>*)files[i]->Get("mcLabelBuffer"); effBuffer[i] = (std::vector>*)files[i]->Get("mcEffBuffer"); if (labelsBuffer[i] == nullptr || effBuffer[i] == nullptr) { @@ -651,10 +670,6 @@ int GPUQA::InitQA() mGoodTracks[iEvent][k] = labelsOK[abs((*labelsBuffer[0])[iEvent][k])]; } } - - for (unsigned int i = 0; i < nFiles; i++) { - delete files[i]; - } } mQAInitialized = true; return 0; @@ -1618,7 +1633,7 @@ void GPUQA::GetName(char* fname, int k) } template -T* GPUQA::GetHist(T*& ee, std::vector& tin, int k, int nNewInput) +T* GPUQA::GetHist(T*& ee, std::vector>& tin, int k, int nNewInput) { T* e = ee; if ((mConfig.inputHistogramsOnly || k) && (e = dynamic_cast(tin[k - nNewInput]->Get(e->GetName()))) == nullptr) { @@ -1640,13 +1655,13 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) const int nNewInput = mConfig.inputHistogramsOnly ? 0 : 1; const int ConfigNumInputs = nNewInput + mConfig.compareInputs.size(); - std::vector tin(mConfig.compareInputs.size()); + std::vector> tin; for (unsigned int i = 0; i < mConfig.compareInputs.size(); i++) { - tin[i] = new TFile(mConfig.compareInputs[i]); + tin.emplace_back(std::make_unique(mConfig.compareInputs[i])); } - TFile* tout = nullptr; + std::unique_ptr tout = nullptr; if (mConfig.output.size()) { - tout = new TFile(mConfig.output.c_str(), "RECREATE"); + tout = std::make_unique(mConfig.output.c_str(), "RECREATE"); } if (!mRunForQC) { @@ -1663,22 +1678,22 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) int i = ii == 5 ? 4 : ii; sprintf(fname, "ceff_%d", ii); sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); - mCEff[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCEff[ii] = createGarbageCollected(fname, name, 0, 0, 700, 700. * 2. / 3.); mCEff[ii]->cd(); float dy = 1. / 2.; - mPEff[ii][0] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPEff[ii][0] = createGarbageCollected("p0", "", 0.0, dy * 0, 0.5, dy * 1); mPEff[ii][0]->Draw(); mPEff[ii][0]->SetRightMargin(0.04); - mPEff[ii][1] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPEff[ii][1] = createGarbageCollected("p1", "", 0.5, dy * 0, 1.0, dy * 1); mPEff[ii][1]->Draw(); mPEff[ii][1]->SetRightMargin(0.04); - mPEff[ii][2] = new TPad("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); + mPEff[ii][2] = createGarbageCollected("p2", "", 0.0, dy * 1, 0.5, dy * 2 - .001); mPEff[ii][2]->Draw(); mPEff[ii][2]->SetRightMargin(0.04); - mPEff[ii][3] = new TPad("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); + mPEff[ii][3] = createGarbageCollected("p3", "", 0.5, dy * 1, 1.0, dy * 2 - .001); mPEff[ii][3]->Draw(); mPEff[ii][3]->SetRightMargin(0.04); - mLEff[ii] = new TLegend(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); + mLEff[ii] = createGarbageCollected(0.92 - legendSpacingString * 1.45, 0.83 - (0.93 - 0.82) / 2. * (float)ConfigNumInputs, 0.98, 0.849); SetLegend(mLEff[ii]); } @@ -1691,31 +1706,31 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } else { sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); } - mCRes[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCRes[ii] = createGarbageCollected(fname, name, 0, 0, 700, 700. * 2. / 3.); mCRes[ii]->cd(); gStyle->SetOptFit(1); float dy = 1. / 2.; - mPRes[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPRes[ii][3] = createGarbageCollected("p0", "", 0.0, dy * 0, 0.5, dy * 1); mPRes[ii][3]->Draw(); mPRes[ii][3]->SetRightMargin(0.04); - mPRes[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPRes[ii][4] = createGarbageCollected("p1", "", 0.5, dy * 0, 1.0, dy * 1); mPRes[ii][4]->Draw(); mPRes[ii][4]->SetRightMargin(0.04); - mPRes[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPRes[ii][0] = createGarbageCollected("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); mPRes[ii][0]->Draw(); mPRes[ii][0]->SetRightMargin(0.04); mPRes[ii][0]->SetLeftMargin(0.15); - mPRes[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPRes[ii][1] = createGarbageCollected("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); mPRes[ii][1]->Draw(); mPRes[ii][1]->SetRightMargin(0.04); mPRes[ii][1]->SetLeftMargin(0.135); - mPRes[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPRes[ii][2] = createGarbageCollected("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); mPRes[ii][2]->Draw(); mPRes[ii][2]->SetRightMargin(0.06); mPRes[ii][2]->SetLeftMargin(0.135); if (ii < 6) { - mLRes[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLRes[ii] = createGarbageCollected(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLRes[ii]); } } @@ -1729,31 +1744,31 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } else { sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); } - mCPull[ii] = new TCanvas(fname, name, 0, 0, 700, 700. * 2. / 3.); + mCPull[ii] = createGarbageCollected(fname, name, 0, 0, 700, 700. * 2. / 3.); mCPull[ii]->cd(); gStyle->SetOptFit(1); float dy = 1. / 2.; - mPPull[ii][3] = new TPad("p0", "", 0.0, dy * 0, 0.5, dy * 1); + mPPull[ii][3] = createGarbageCollected("p0", "", 0.0, dy * 0, 0.5, dy * 1); mPPull[ii][3]->Draw(); mPPull[ii][3]->SetRightMargin(0.04); - mPPull[ii][4] = new TPad("p1", "", 0.5, dy * 0, 1.0, dy * 1); + mPPull[ii][4] = createGarbageCollected("p1", "", 0.5, dy * 0, 1.0, dy * 1); mPPull[ii][4]->Draw(); mPPull[ii][4]->SetRightMargin(0.04); - mPPull[ii][0] = new TPad("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); + mPPull[ii][0] = createGarbageCollected("p2", "", 0.0, dy * 1, 1. / 3., dy * 2 - .001); mPPull[ii][0]->Draw(); mPPull[ii][0]->SetRightMargin(0.04); mPPull[ii][0]->SetLeftMargin(0.15); - mPPull[ii][1] = new TPad("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); + mPPull[ii][1] = createGarbageCollected("p3", "", 1. / 3., dy * 1, 2. / 3., dy * 2 - .001); mPPull[ii][1]->Draw(); mPPull[ii][1]->SetRightMargin(0.04); mPPull[ii][1]->SetLeftMargin(0.135); - mPPull[ii][2] = new TPad("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); + mPPull[ii][2] = createGarbageCollected("p4", "", 2. / 3., dy * 1, 1.0, dy * 2 - .001); mPPull[ii][2]->Draw(); mPPull[ii][2]->SetRightMargin(0.06); mPPull[ii][2]->SetLeftMargin(0.135); if (ii < 6) { - mLPull[ii] = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLPull[ii] = createGarbageCollected(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLPull[ii]); } } @@ -1761,29 +1776,29 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas for Cluster Histos for (int i = 0; i < 3; i++) { sprintf(fname, "cclust_%d", i); - mCClust[i] = new TCanvas(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); + mCClust[i] = createGarbageCollected(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); mCClust[i]->cd(); - mPClust[i] = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPClust[i] = createGarbageCollected("p0", "", 0.0, 0.0, 1.0, 1.0); mPClust[i]->Draw(); float y1 = i != 1 ? 0.77 : 0.27, y2 = i != 1 ? 0.9 : 0.42; - mLClust[i] = new TLegend(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); + mLClust[i] = createGarbageCollected(i == 2 ? 0.1 : (0.65 - legendSpacingString * 1.45), y2 - (y2 - y1) * (ConfigNumInputs + (i != 1) / 2.) + 0.005, i == 2 ? (0.3 + legendSpacingString * 1.45) : 0.9, y2); SetLegend(mLClust[i]); } // Create Canvas for other histos { - mCTracks = new TCanvas("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); + mCTracks = createGarbageCollected("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); mCTracks->cd(); - mPTracks = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPTracks = createGarbageCollected("p0", "", 0.0, 0.0, 1.0, 1.0); mPTracks->Draw(); - mLTracks = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLTracks = createGarbageCollected(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLTracks); - mCNCl = new TCanvas("cncl", "Number of clusters per track", 0, 0, 700, 700. * 2. / 3.); + mCNCl = createGarbageCollected("cncl", "Number of clusters per track", 0, 0, 700, 700. * 2. / 3.); mCNCl->cd(); - mPNCl = new TPad("p0", "", 0.0, 0.0, 1.0, 1.0); + mPNCl = createGarbageCollected("p0", "", 0.0, 0.0, 1.0, 1.0); mPNCl->Draw(); - mLNCl = new TLegend(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); + mLNCl = createGarbageCollected(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLNCl); } @@ -1884,7 +1899,8 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Process / Draw Resolution Histograms TH1D *resIntegral[5] = {}, *pullIntegral[5] = {}; - TF1* customGaus = new TF1("G", "[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))"); + TCanvas* cfit = nullptr; + std::unique_ptr customGaus = std::make_unique("G", "[0]*exp(-(x-[1])*(x-[1])/(2.*[2]*[2]))"); for (int p = 0; p < 2; p++) { for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { TCanvas* can = p ? mCPull[ii] : mCRes[ii]; @@ -1898,7 +1914,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (!mConfig.inputHistogramsOnly && ii != 5) { if (!mRunForQC) { - cfit.cd(); + if (cfit == nullptr) { + cfit = createGarbageCollected(); + } + cfit->cd(); } TAxis* axis = src->GetYaxis(); @@ -1907,7 +1926,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) for (int bin = 1; bin <= nBins; bin++) { int bin0 = std::max(bin - integ, 0); int bin1 = std::min(bin + integ, nBins); - TH1D* proj = src->ProjectionX("proj", bin0, bin1); + std::unique_ptr proj{src->ProjectionX("proj", bin0, bin1)}; proj->ClearUnderflowAndOverflow(); if (proj->GetEntries()) { unsigned int rebin = 1; @@ -1931,8 +1950,8 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (k && !forceLogLike) { customGaus->SetParameters(fitFunc->GetParameter(0), fitFunc->GetParameter(1), fitFunc->GetParameter(2)); - proj->Fit(customGaus, "sQ"); - fitFunc = customGaus; + proj->Fit(customGaus.get(), "sQ"); + fitFunc = customGaus.get(); } const float sigma = fabs(fitFunc->GetParameter(2)); @@ -1964,7 +1983,6 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) dst[1]->SetBinContent(bin, 0.f); dst[1]->SetBinError(bin, 0.f); } - delete proj; } if (ii == 0) { dstIntegral = src->ProjectionX(mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j], 0, nBins + 1); @@ -1977,7 +1995,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } if (ii == 0) { if (mConfig.inputHistogramsOnly) { - dstIntegral = new TH1D; + dstIntegral = createGarbageCollected(); } sprintf(fname, p ? "IntPull%s" : "IntRes%s", VSPARAMETER_NAMES[j]); sprintf(name, p ? "%s Pull" : "%s Resolution", p || mConfig.nativeFitResolutions ? PARAMETER_NAMES_NATIVE[j] : PARAMETER_NAMES[j]); @@ -2109,7 +2127,6 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } } - delete customGaus; // Process Integral Resolution Histogreams for (int p = 0; p < 2; p++) { @@ -2172,11 +2189,6 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (mConfig.writeRootFiles) { can->Print(p ? "plots/pull_integral.root" : "plots/res_integral.root"); } - if (!mConfig.inputHistogramsOnly) { - for (int i = 0; i < 5; i++) { - delete (p ? pullIntegral : resIntegral)[i]; - } - } } // Process Cluster Histograms @@ -2462,11 +2474,12 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (tout) { tout->Close(); - delete tout; } for (unsigned int i = 0; i < mConfig.compareInputs.size(); i++) { tin[i]->Close(); - delete tin[i]; + } + if (!qcout) { + clearGarbagageCollector(); } return (0); } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 89dd94c6c9f1e..3bb06e915ae4e 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -79,6 +79,7 @@ namespace GPUCA_NAMESPACE::gpu { class GPUChainTracking; class GPUTPCMCInfo; +struct GPUQAGarbageCollection; class GPUQA { @@ -129,7 +130,7 @@ class GPUQA void doPerfFigure(float x, float y, float size); void GetName(char* fname, int k); template - T* GetHist(T*& ee, std::vector& tin, int k, int nNewInput); + T* GetHist(T*& ee, std::vector>& tin, int k, int nNewInput); #ifdef GPUCA_TPC_GEOMETRY_O2 using mcLabels_t = gsl::span; @@ -266,6 +267,11 @@ class GPUQA template void createHist(T*& h, const char* name, Args... args); + std::unique_ptr mGarbageCollector; + template + T* createGarbageCollected(Args... args); + void clearGarbagageCollector(); + int mNEvents = 0; bool mQAInitialized = false; std::vector> mcEffBuffer; From 95ba9cf2469d6c0a1f99e15b79b35f2f463555f0 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Nov 2020 00:21:27 +0100 Subject: [PATCH 2/6] GPU QA: Add option to ship TCanvases to QC instead of histograms --- Detectors/TPC/workflow/src/CATrackerSpec.cxx | 3 +- GPU/GPUTracking/Base/GPUSettingsList.h | 3 +- GPU/GPUTracking/Interface/GPUO2Interface.cxx | 2 +- .../Interface/GPUO2InterfaceQA.cxx | 5 + GPU/GPUTracking/Interface/GPUO2InterfaceQA.h | 1 + GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 95 +++++++++++-------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 1 + 7 files changed, 70 insertions(+), 40 deletions(-) diff --git a/Detectors/TPC/workflow/src/CATrackerSpec.cxx b/Detectors/TPC/workflow/src/CATrackerSpec.cxx index bd5be552fabff..2b16a80d6f4ef 100644 --- a/Detectors/TPC/workflow/src/CATrackerSpec.cxx +++ b/Detectors/TPC/workflow/src/CATrackerSpec.cxx @@ -163,7 +163,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config config.configProcessing.runMC = specconfig.processMC; if (specconfig.outputQA) { if (!config.configProcessing.runQA) { - config.configQA.forQC = true; + config.configQA.shipToQC = true; } config.configProcessing.runQA = true; } @@ -713,6 +713,7 @@ DataProcessorSpec getCATrackerSpec(CompletionPolicyData* policyData, ca::Config std::vector copy3 = *outputRegions.qa.hist3; processAttributes->qa->postprocess(copy1, copy2, copy3, out); pc.outputs().snapshot({gDataOriginTPC, "TRACKINGQA", 0, Lifetime::Timeframe}, out); + processAttributes->qa->cleanup(); } timer.Stop(); LOG(INFO) << "TPC CATracker time for this TF " << timer.CpuTime() - cput << " s"; diff --git a/GPU/GPUTracking/Base/GPUSettingsList.h b/GPU/GPUTracking/Base/GPUSettingsList.h index c116d67c5ceb1..34455f08d47ca 100644 --- a/GPU/GPUTracking/Base/GPUSettingsList.h +++ b/GPU/GPUTracking/Base/GPUSettingsList.h @@ -160,7 +160,8 @@ AddOptionVec(matchMCLabels, const char*, "", 0, "Read labels from files and matc AddOption(matchDisplayMinPt, float, 0, "", 0, "Minimum Pt of a matched track to be displayed") AddOption(writeRootFiles, bool, false, "", 0, "Create ROOT canvas files") AddOption(noMC, bool, false, "", 0, "Force running QA without MC labels even if present") -AddOption(forQC, bool, false, "", 0, "Do not write output files but ship histograms for QC") +AddOption(shipToQC, bool, false, "", 0, "Do not write output files but ship histograms for QC") +AddOption(shipToQCAsCanvas, bool, false, "", 0, "Send TCanvases with full layout to QC instead of individual histograms") AddShortcut("compare", 0, "--QAinput", "Compare QA histograms", "--qa", "--QAinputHistogramsOnly") AddHelp("help", 'h') EndConfig() diff --git a/GPU/GPUTracking/Interface/GPUO2Interface.cxx b/GPU/GPUTracking/Interface/GPUO2Interface.cxx index b356e5ba0f32c..2c63a5528ed93 100644 --- a/GPU/GPUTracking/Interface/GPUO2Interface.cxx +++ b/GPU/GPUTracking/Interface/GPUO2Interface.cxx @@ -160,7 +160,7 @@ int GPUTPCO2Interface::RunTracking(GPUTrackingInOutPointers* data, GPUInterfaceO outputs->clustersNative.size = mOutputClustersNative->EndOfSpace ? 0 : (mChain->mIOPtrs.clustersNative->nClustersTotal * sizeof(*mChain->mIOPtrs.clustersNative->clustersLinear)); outputs->tpcTracks.size = mOutputCompressedClusters->EndOfSpace ? 0 : (size_t)((char*)mOutputCompressedClusters->OutputPtr - (char*)mOutputCompressedClusters->OutputBase); } - if (mConfig->configQA.forQC) { + if (mConfig->configQA.shipToQC) { outputs->qa.hist1 = &mChain->GetQA()->getHistograms1D(); outputs->qa.hist2 = &mChain->GetQA()->getHistograms2D(); outputs->qa.hist3 = &mChain->GetQA()->getHistograms1Dd(); diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx index a30db8bef77a8..31bc68d340edb 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.cxx @@ -30,3 +30,8 @@ int GPUO2InterfaceQA::postprocess(std::vector& in1, std::vector& in2 } return mQA->DrawQAHistograms(&out); } + +void GPUO2InterfaceQA::cleanup() +{ + mQA->DrawQAHistogramsCleanup(); +} diff --git a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h index 83f0d00e3f018..6d75cdb645967 100644 --- a/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h +++ b/GPU/GPUTracking/Interface/GPUO2InterfaceQA.h @@ -45,6 +45,7 @@ class GPUO2InterfaceQA // Input might be modified, so we assume non-const. If it is const, a copy should be created before. int postprocess(std::vector& in1, std::vector& in2, std::vector& in3, TObjArray& out); + void cleanup(); private: std::unique_ptr mQA; diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index c8b1600c68750..ce87941b99cd2 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -303,7 +303,7 @@ void GPUQA::clearGarbagageCollector() GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)), mGarbageCollector(std::make_unique()) { - mRunForQC = chain == nullptr || mConfig.forQC; + mRunForQC = chain == nullptr || mConfig.shipToQC; } GPUQA::~GPUQA() @@ -1644,6 +1644,11 @@ T* GPUQA::GetHist(T*& ee, std::vector>& tin, int k, int n return (e); } +void GPUQA::DrawQAHistogramsCleanup() +{ + clearGarbagageCollector(); +} + int GPUQA::DrawQAHistograms(TObjArray* qcout) { if (!mQAInitialized) { @@ -1664,7 +1669,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) tout = std::make_unique(mConfig.output.c_str(), "RECREATE"); } - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { float legendSpacingString = 0.025; for (int i = 0; i < ConfigNumInputs; i++) { GetName(fname, i); @@ -1801,23 +1806,23 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) mLNCl = createGarbageCollected(0.9 - legendSpacingString * 1.45, 0.93 - (0.93 - 0.86) / 2. * (float)ConfigNumInputs, 0.98, 0.949); SetLegend(mLNCl); } + } - if (!mConfig.inputHistogramsOnly) { - GPUInfo("QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int)mEff[3][1][0][0][0]->GetEntries(), (int)mEff[3][1][0][3][0]->GetEntries(), (int)mEff[3][1][0][4][0]->GetEntries(), - mEff[0][0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0][0]->GetSumOfWeights()), (int)mEff[3][1][1][0][0]->GetEntries(), (int)mEff[3][1][1][3][0]->GetEntries(), - (int)mEff[3][1][1][4][0]->GetEntries(), mEff[0][0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0][0]->GetSumOfWeights()), mEff[0][1][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0][0]->GetSumOfWeights()), (int)mRes2[0][0]->GetEntries(), - (int)mRes2[0][3]->GetEntries(), (int)mRes2[0][4]->GetEntries()); - } + if (!mRunForQC && !mConfig.inputHistogramsOnly) { + GPUInfo("QA Stats: Eff: Tracks Prim %d (Eta %d, Pt %d) %f%% (%f%%) Sec %d (Eta %d, Pt %d) %f%% (%f%%) - Res: Tracks %d (Eta %d, Pt %d)", (int)mEff[3][1][0][0][0]->GetEntries(), (int)mEff[3][1][0][3][0]->GetEntries(), (int)mEff[3][1][0][4][0]->GetEntries(), + mEff[0][0][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][0][0][0]->GetSumOfWeights()), mEff[0][1][0][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][0][0][0]->GetSumOfWeights()), (int)mEff[3][1][1][0][0]->GetEntries(), (int)mEff[3][1][1][3][0]->GetEntries(), + (int)mEff[3][1][1][4][0]->GetEntries(), mEff[0][0][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][0][1][0][0]->GetSumOfWeights()), mEff[0][1][1][0][0]->GetSumOfWeights() / std::max(1., mEff[3][1][1][0][0]->GetSumOfWeights()), (int)mRes2[0][0]->GetEntries(), + (int)mRes2[0][3]->GetEntries(), (int)mRes2[0][4]->GetEntries()); } - int flagShowVsPtLog = mRunForQC ? 0 : 1; + int flagShowVsPtLog = (mRunForQC && !mConfig.shipToQCAsCanvas) ? 0 : 1; // Process / Draw Efficiency Histograms for (int ii = 0; ii < 5 + flagShowVsPtLog; ii++) { int i = ii == 5 ? 4 : ii; for (int k = 0; k < ConfigNumInputs; k++) { for (int j = 0; j < 4; j++) { - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { mPEff[ii][j]->cd(); } for (int l = 0; l < 3; l++) { @@ -1858,10 +1863,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) e->SetLineWidth(1); e->SetLineStyle(CONFIG_DASHED_MARKERS ? k + 1 : 1); SetAxisSize(e); - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } e->SetMarkerColor(kBlack); @@ -1876,21 +1881,26 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) mPEff[ii][j]->SetLogx(); } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } mCEff[ii]->cd(); ChangePadTitleSize(mPEff[ii][j], 0.056); } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } mLEff[ii]->Draw(); + if (mRunForQC) { + if (qcout) { + qcout->Add(mCEff[ii]); + } + continue; + } doPerfFigure(0.2, 0.295, 0.025); - mCEff[ii]->Print(Form("plots/eff_vs_%s.pdf", VSPARAMETER_NAMES[ii])); if (mConfig.writeRootFiles) { mCEff[ii]->Print(Form("plots/eff_vs_%s.root", VSPARAMETER_NAMES[ii])); @@ -1913,12 +1923,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) TPad* pad = p ? mPPull[ii][j] : mPRes[ii][j]; if (!mConfig.inputHistogramsOnly && ii != 5) { - if (!mRunForQC) { - if (cfit == nullptr) { - cfit = createGarbageCollected(); - } - cfit->cd(); + if (cfit == nullptr) { + cfit = createGarbageCollected(); } + cfit->cd(); TAxis* axis = src->GetYaxis(); int nBins = axis->GetNbins(); @@ -2002,7 +2010,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) dstIntegral->SetName(fname); dstIntegral->SetTitle(name); } - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { pad->cd(); } int numColor = 0; @@ -2080,10 +2088,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } else if (j < 3) { e->GetYaxis()->SetTitleOffset(1.4); } - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2101,7 +2109,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2113,14 +2121,19 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) ChangePadTitleSize(pad, 0.056); } } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } leg->Draw(); + if (mRunForQC) { + if (qcout) { + qcout->Add(can); + } + continue; + } doPerfFigure(0.2, 0.295, 0.025); - can->Print(Form(p ? "plots/pull_vs_%s.pdf" : "plots/res_vs_%s.pdf", VSPARAMETER_NAMES[ii])); if (mConfig.writeRootFiles) { can->Print(Form(p ? "plots/pull_vs_%s.root" : "plots/res_vs_%s.root", VSPARAMETER_NAMES[ii])); @@ -2135,7 +2148,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) TPad* pad = p ? mPPull[6][i] : mPRes[6][i]; TH1D* hist = p ? pullIntegral[i] : resIntegral[i]; int numColor = 0; - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { pad->cd(); } if (!mConfig.inputHistogramsOnly && mcAvail) { @@ -2166,22 +2179,25 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (tout && !mConfig.inputHistogramsOnly && k == 0) { e->Write(); } - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } can->cd(); } if (mRunForQC) { + if (qcout) { + qcout->Add(can); + } continue; } @@ -2300,7 +2316,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } for (int i = 0; i < N_CLS_TYPE; i++) { - if (!mRunForQC) { + if (!mRunForQC || mConfig.shipToQCAsCanvas) { mPClust[i]->cd(); mPClust[i]->SetLogx(); } @@ -2328,10 +2344,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (i == 0) { e->GetXaxis()->SetRange(2, AXIS_BINS[4]); } - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2346,10 +2362,10 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (ConfigNumInputs == 1) { TH1* e = reinterpret_cast(mClusters[begin + CL_att_adj]->Clone()); e->Add(mClusters[begin + CL_prot], -1); - if (qcout) { + if (qcout && !mConfig.shipToQCAsCanvas) { qcout->Add(e); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } @@ -2357,14 +2373,19 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) e->Draw("same"); mLClust[i]->AddEntry(e, "Removed", "l"); } - if (mRunForQC) { + if (mRunForQC && !mConfig.shipToQCAsCanvas) { continue; } mLClust[i]->Draw(); + if (mRunForQC) { + if (qcout) { + qcout->Add(mCClust[i]); + } + continue; + } doPerfFigure(i != 2 ? 0.37 : 0.6, 0.295, 0.030); - mCClust[i]->cd(); mCClust[i]->Print(i == 2 ? "plots/clusters_integral.pdf" : i == 1 ? "plots/clusters_relative.pdf" : "plots/clusters.pdf"); if (mConfig.writeRootFiles) { diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 3bb06e915ae4e..62e65a44dc508 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -91,6 +91,7 @@ class GPUQA int InitQA(); void RunQA(bool matchOnly = false); int DrawQAHistograms(TObjArray* qcout = nullptr); + void DrawQAHistogramsCleanup(); // Needed after call to DrawQAHistograms with qcout != nullptr when GPUSettingsQA.shipToQCAsCanvas = true to clean up the Canvases etc. void SetMCTrackRange(int min, int max); bool SuppressTrack(int iTrack) const; bool SuppressHit(int iHit) const; From d559d5e70266470fd9cae52d073fc4eea43f0cf9 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Nov 2020 00:26:59 +0100 Subject: [PATCH 3/6] GPU QA: Make color array static since it is constant --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 28 ++++++++++++++++--------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 5 +++-- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index ce87941b99cd2..748484b0f0b90 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -190,6 +190,22 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; +std::vector GPUQA::mColorNums; +std::vector GPUQA::mColors; +int GPUQA::initColors() +{ + mColorNums.resize(COLORCOUNT); + mColors.reserve(COLORCOUNT); + for (int i = 0; i < COLORCOUNT; i++) { + float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; + float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; + float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; + mColors.emplace_back(10000 + i, f1, f2, f3); + mColorNums[i] = mColors.back().GetNumber(); + } + return 0; +} + #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" #include "SimulationDataFormat/ConstMCTruthContainer.h" @@ -303,6 +319,8 @@ void GPUQA::clearGarbagageCollector() GPUQA::GPUQA(GPUChainTracking* chain, const GPUSettingsQA* config) : mTracking(chain), mConfig(config ? *config : GPUQA_GetConfig(chain)), mGarbageCollector(std::make_unique()) { + static int initColorsInitialized = initColors(); + (void)initColorsInitialized; mRunForQC = chain == nullptr || mConfig.shipToQC; } @@ -536,16 +554,6 @@ int GPUQA::InitQA() mHist2D = new std::vector; mHist1Dd = new std::vector; - mColorNums.resize(COLORCOUNT); - mColors.reserve(COLORCOUNT); - for (int i = 0; i < COLORCOUNT; i++) { - float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; - float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; - float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; - mColors.emplace_back(10000 + i, f1, f2, f3); - mColorNums[i] = mColors.back().GetNumber(); - } - if (InitQACreateHistograms()) { return 1; } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index 62e65a44dc508..d9beaa8b887b1 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -280,8 +280,9 @@ class GPUQA std::vector> mGoodTracks; std::vector> mGoodHits; - std::vector mColorNums; - std::vector mColors; + static std::vector mColorNums; + static std::vector mColors; + static int initColors(); int mMCTrackMin = -1, mMCTrackMax = -1; }; From 414df94afe7abf83c265a80d088fdb7261b35d73 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Nov 2020 14:28:57 +0100 Subject: [PATCH 4/6] GPU: Remove spurious void* reinterprete cast after config is no nested class anymore --- GPU/GPUTracking/Global/GPUChainTracking.cxx | 2 +- GPU/GPUTracking/Global/GPUChainTracking.h | 4 ++-- GPU/GPUTracking/Standalone/display/GPUDisplay.cxx | 2 +- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/GPU/GPUTracking/Global/GPUChainTracking.cxx b/GPU/GPUTracking/Global/GPUChainTracking.cxx index 6caf6545c278a..16c8ef2c9cab2 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.cxx +++ b/GPU/GPUTracking/Global/GPUChainTracking.cxx @@ -421,7 +421,7 @@ int GPUChainTracking::ForceInitQA() int GPUChainTracking::Finalize() { - if (GetProcessingSettings().runQA && mQA->IsInitialized()) { + if (GetProcessingSettings().runQA && mQA->IsInitialized() && !(mConfigQA && mConfigQA->shipToQC)) { mQA->DrawQAHistograms(); } if (GetProcessingSettings().debugLevel >= 6) { diff --git a/GPU/GPUTracking/Global/GPUChainTracking.h b/GPU/GPUTracking/Global/GPUChainTracking.h index d7ae3816579c2..f9cb5022e9830 100644 --- a/GPU/GPUTracking/Global/GPUChainTracking.h +++ b/GPU/GPUTracking/Global/GPUChainTracking.h @@ -171,8 +171,8 @@ class GPUChainTracking : public GPUChain, GPUReconstructionHelpers::helperDelega void SetOutputControlTPCTracks(GPUOutputControl* v) { mOutputTPCTracks = v; } void SetOutputControlClusterLabels(GPUOutputControl* v) { mOutputClusterLabels = v; } - const void* mConfigDisplay = nullptr; // Abstract pointer to Standalone Display Configuration Structure - const void* mConfigQA = nullptr; // Abstract pointer to Standalone QA Configuration Structure + const GPUSettingsDisplay* mConfigDisplay = nullptr; // Abstract pointer to Standalone Display Configuration Structure + const GPUSettingsQA* mConfigQA = nullptr; // Abstract pointer to Standalone QA Configuration Structure protected: struct GPUTrackingFlatObjects : public GPUProcessor { diff --git a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx index 7aa72568bac25..b8f4bb302ceb5 100644 --- a/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx +++ b/GPU/GPUTracking/Standalone/display/GPUDisplay.cxx @@ -89,7 +89,7 @@ static const GPUSettingsDisplay& GPUDisplay_GetConfig(GPUChainTracking* chain) #if !defined(GPUCA_STANDALONE) static GPUSettingsDisplay defaultConfig; if (chain->mConfigDisplay) { - return *((const GPUSettingsDisplay*)chain->mConfigDisplay); + return *chain->mConfigDisplay; } else { return defaultConfig; } diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index 748484b0f0b90..de5bf2c9c239b 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -125,7 +125,7 @@ static const GPUSettingsQA& GPUQA_GetConfig(GPUChainTracking* chain) #if !defined(GPUCA_STANDALONE) static GPUSettingsQA defaultConfig; if (chain && chain->mConfigQA) { - return *((const GPUSettingsQA*)chain->mConfigQA); + return *chain->mConfigQA; } else { return defaultConfig; } From d65af392d5cd46ab041fd2a89f142fe4d8873a67 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Nov 2020 14:35:04 +0100 Subject: [PATCH 5/6] GPU: use standard ROOT colors when shipping TCanvas to QC --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 24 ++++++++++++++---------- GPU/GPUTracking/Standalone/qa/GPUQA.h | 1 - 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index de5bf2c9c239b..b9efccec0a614 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -190,21 +190,19 @@ static const constexpr float RES_AXES[5] = {1., 1., 0.03, 0.03, 1.0}; static const constexpr float RES_AXES_NATIVE[5] = {1., 1., 0.1, 0.1, 5.0}; static const constexpr float PULL_AXIS = 10.f; -std::vector GPUQA::mColorNums; std::vector GPUQA::mColors; int GPUQA::initColors() { - mColorNums.resize(COLORCOUNT); mColors.reserve(COLORCOUNT); for (int i = 0; i < COLORCOUNT; i++) { float f1 = (float)((COLORS_HEX[i] >> 16) & 0xFF) / (float)0xFF; float f2 = (float)((COLORS_HEX[i] >> 8) & 0xFF) / (float)0xFF; float f3 = (float)((COLORS_HEX[i] >> 0) & 0xFF) / (float)0xFF; mColors.emplace_back(10000 + i, f1, f2, f3); - mColorNums[i] = mColors.back().GetNumber(); } return 0; } +static constexpr Color_t defaultColorNUms[COLORCOUNT] = {kRed, kBlue, kGreen, kMagenta, kOrange, kAzure, kBlack, kYellow, kGray, kTeal, kSpring, kPink}; #ifdef GPUCA_TPC_GEOMETRY_O2 #include "SimulationDataFormat/MCCompLabel.h" @@ -1662,6 +1660,12 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) if (!mQAInitialized) { return 1; } + + std::vector colorNums(COLORCOUNT); + for (int i = 0; i < COLORCOUNT; i++) { + colorNums[i] = qcout ? defaultColorNUms[i] : mColors[i].GetNumber(); + } + bool mcAvail = mcPresent(); char name[2048], fname[1024]; @@ -1878,7 +1882,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) continue; } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); + e->SetLineColor(colorNums[(l == 2 ? (ConfigNumInputs * 2 + k) : (k * 2 + l)) % COLORCOUNT]); e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -2104,7 +2108,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw(k || l ? "same" : ""); if (j == 0) { GetName(fname, k); @@ -2194,7 +2198,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) continue; } - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); } if (mRunForQC && !mConfig.shipToQCAsCanvas) { @@ -2360,7 +2364,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw(j == end - 1 && k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%s%s", fname, CLUSTER_NAMES[j - begin]); @@ -2377,7 +2381,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) continue; } - e->SetLineColor(mColorNums[numColor++ % COLORCOUNT]); + e->SetLineColor(colorNums[numColor++ % COLORCOUNT]); e->Draw("same"); mLClust[i]->AddEntry(e, "Removed", "l"); } @@ -2435,7 +2439,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) qcout->Add(e); } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[k % COLORCOUNT]); + e->SetLineColor(colorNums[k % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%sTrack Pt", fname); @@ -2477,7 +2481,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) qcout->Add(e); } e->SetMarkerColor(kBlack); - e->SetLineColor(mColorNums[k % COLORCOUNT]); + e->SetLineColor(colorNums[k % COLORCOUNT]); e->Draw(k == 0 ? "" : "same"); GetName(fname, k); sprintf(name, "%sNClusters", fname); diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.h b/GPU/GPUTracking/Standalone/qa/GPUQA.h index d9beaa8b887b1..63f24cbf70327 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.h +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.h @@ -280,7 +280,6 @@ class GPUQA std::vector> mGoodTracks; std::vector> mGoodHits; - static std::vector mColorNums; static std::vector mColors; static int initColors(); From 793375a87817b796f389a94b6746d3e8d7b859c8 Mon Sep 17 00:00:00 2001 From: David Rohr Date: Thu, 12 Nov 2020 15:07:18 +0100 Subject: [PATCH 6/6] GPU QA: Use reasonable canvas names --- GPU/GPUTracking/Standalone/qa/GPUQA.cxx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx index b9efccec0a614..7fadcbbe066e0 100644 --- a/GPU/GPUTracking/Standalone/qa/GPUQA.cxx +++ b/GPU/GPUTracking/Standalone/qa/GPUQA.cxx @@ -1429,7 +1429,7 @@ void GPUQA::RunQA(bool matchOnly) GPUWarning("No MC information available, only running partial TPC QA!"); } - // Fill other histograms + // Fill track statistic histograms for (unsigned int i = 0; i < mTracking->mIOPtrs.nMergedTracks; i++) { const GPUTPCGMMergedTrack& track = mTracking->mIOPtrs.mergedTracks[i]; if (!track.OK()) { @@ -1693,7 +1693,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas / Pads for Efficiency Histograms for (int ii = 0; ii < 6; ii++) { int i = ii == 5 ? 4 : ii; - sprintf(fname, "ceff_%d", ii); + sprintf(fname, "eff_vs_%s_layout", VSPARAMETER_NAMES[ii]); sprintf(name, "Efficiency versus %s", VSPARAMETER_NAMES[i]); mCEff[ii] = createGarbageCollected(fname, name, 0, 0, 700, 700. * 2. / 3.); mCEff[ii]->cd(); @@ -1717,10 +1717,11 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas / Pads for Resolution Histograms for (int ii = 0; ii < 7; ii++) { int i = ii == 5 ? 4 : ii; - sprintf(fname, "cres_%d", ii); if (ii == 6) { + sprintf(fname, "res_integral_layout"); sprintf(name, "Integral Resolution"); } else { + sprintf(fname, "res_vs_%s_layout", VSPARAMETER_NAMES[ii]); sprintf(name, "Resolution versus %s", VSPARAMETER_NAMES[i]); } mCRes[ii] = createGarbageCollected(fname, name, 0, 0, 700, 700. * 2. / 3.); @@ -1755,10 +1756,12 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas / Pads for Pull Histograms for (int ii = 0; ii < 7; ii++) { int i = ii == 5 ? 4 : ii; - sprintf(fname, "cpull_%d", ii); + if (ii == 6) { + sprintf(fname, "pull_integral_layout"); sprintf(name, "Integral Pull"); } else { + sprintf(fname, "pull_vs_%s_layout", VSPARAMETER_NAMES[ii]); sprintf(name, "Pull versus %s", VSPARAMETER_NAMES[i]); } mCPull[ii] = createGarbageCollected(fname, name, 0, 0, 700, 700. * 2. / 3.); @@ -1792,7 +1795,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) // Create Canvas for Cluster Histos for (int i = 0; i < 3; i++) { - sprintf(fname, "cclust_%d", i); + sprintf(fname, "clusters_%s_layout", CLUSTER_TYPES[i]); mCClust[i] = createGarbageCollected(fname, CLUSTER_TITLES[i], 0, 0, 700, 700. * 2. / 3.); mCClust[i]->cd(); mPClust[i] = createGarbageCollected("p0", "", 0.0, 0.0, 1.0, 1.0); @@ -1802,8 +1805,8 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) SetLegend(mLClust[i]); } - // Create Canvas for other histos - { + // Create Canvas for track statistic histos + if (!mRunForQC) { mCTracks = createGarbageCollected("ctracks", "Track Pt", 0, 0, 700, 700. * 2. / 3.); mCTracks->cd(); mPTracks = createGarbageCollected("p0", "", 0.0, 0.0, 1.0, 1.0); @@ -2406,7 +2409,7 @@ int GPUQA::DrawQAHistograms(TObjArray* qcout) } } - // Process track histograms + // Process track statistic histograms if (!mRunForQC) { float tmpMax = 0.; for (int k = 0; k < ConfigNumInputs; k++) {