35#ifdef _PERFORM_TIMING_
54 mFiredChipsPtr.clear();
57 mFiredChipsPtr.push_back(curChipData);
58 nPix += curChipData->
getData().size();
61 auto& rof = vecROFRec->emplace_back(reader.
getInteractionRecord(), vecROFRec->size(), compClus->size(), 0);
63 uint16_t nFired = mFiredChipsPtr.size();
70 if (nFired < nThreads) {
76 uint16_t chipStep = nThreads > 1 ? (nThreads == 2 ? 20 : 10) : nFired;
77 int dynGrp = std::min(4, std::max(1, nThreads / 2));
78 if (nThreads > mThreads.size()) {
79 int oldSz = mThreads.size();
80 mThreads.resize(nThreads);
81 for (
size_t i = oldSz;
i < nThreads;
i++) {
82 mThreads[
i] = std::make_unique<ClustererThread>(
this,
i);
86#pragma omp parallel for schedule(dynamic, dynGrp) num_threads(nThreads)
88 for (uint16_t ic = 0; ic < nFired; ic += chipStep) {
89 auto ith = omp_get_thread_num();
91 mThreads[ith]->process(ic, std::min(chipStep, uint16_t(nFired - ic)),
92 &mThreads[ith]->compClusters,
93 patterns ? &mThreads[ith]->patterns :
nullptr,
95 labelsCl ? &mThreads[ith]->labels :
nullptr, rof);
97 mThreads[0]->process(0, nFired, compClus, patterns, labelsCl ? reader.
getDigitsMCTruth() :
nullptr, labelsCl, rof);
102 mThreads[0]->process(0, nFired, compClus, patterns, labelsCl ? reader.
getDigitsMCTruth() :
nullptr, labelsCl, rof);
106#ifdef _PERFORM_TIMING_
107 mTimerMerge.Start(
false);
109 size_t nClTot = 0, nPattTot = 0;
111 std::vector<size_t> thrStatIdx(nThreads, 0);
112 for (
int ith = 0; ith < nThreads; ith++) {
113 std::sort(mThreads[ith]->stats.begin(), mThreads[ith]->stats.end(), [](
const ThreadStat&
a,
const ThreadStat&
b) { return a.firstChip < b.firstChip; });
114 nClTot += mThreads[ith]->compClusters.size();
115 nPattTot += mThreads[ith]->patterns.size();
117 compClus->reserve(nClTot);
119 patterns->reserve(nPattTot);
121 while (
chid < nFired) {
122 for (
int ith = 0; ith < nThreads; ith++) {
123 if (thrStatIdx[ith] >= mThreads[ith]->stats.size()) {
126 const auto& stat = mThreads[ith]->stats[thrStatIdx[ith]];
127 if (stat.firstChip ==
chid) {
130 const auto clbeg = mThreads[ith]->compClusters.begin() + stat.firstClus;
131 compClus->insert(compClus->end(), clbeg, clbeg + stat.nClus);
133 const auto ptbeg = mThreads[ith]->patterns.begin() + stat.firstPatt;
134 patterns->insert(patterns->end(), ptbeg, ptbeg + stat.nPatt);
137 labelsCl->
mergeAtBack(mThreads[ith]->labels, stat.firstClus, stat.nClus);
142 for (
int ith = 0; ith < nThreads; ith++) {
143 mThreads[ith]->patterns.clear();
144 mThreads[ith]->compClusters.clear();
145 mThreads[ith]->labels.clear();
146 mThreads[ith]->stats.clear();
148#ifdef _PERFORM_TIMING_
152 mThreads[0]->stats.clear();
154 rof.setNEntries(compClus->size() - rof.getFirstEntry());
155 }
while (autoDecode);
157#ifdef _PERFORM_TIMING_
166 if (
stats.empty() ||
stats.back().firstChip +
stats.back().nChips != chip) {
167 stats.emplace_back(
ThreadStat{chip, 0, uint32_t(compClusPtr->size()), patternsPtr ? uint32_t(patternsPtr->size()) : 0, 0, 0});
169 for (
int ic = 0; ic < nChips; ic++) {
170 auto* curChipData =
parent->mFiredChipsPtr[chip + ic];
171 auto chipID = curChipData->getChipID();
172 if (
parent->mMaxBCSeparationToMask > 0) {
173 const auto& chipInPrevROF =
parent->mChipsOld[chipID];
175 parent->mMaxRowColDiffToMask != 0 ? curChipData->maskFiredInSample(
parent->mChipsOld[chipID],
parent->mMaxRowColDiffToMask) : curChipData->maskFiredInSample(
parent->mChipsOld[chipID]);
178 auto validPixID = curChipData->getFirstUnmasked();
179 auto npix = curChipData->getData().size();
180 if (validPixID < npix) {
181 auto valp = validPixID++;
182 if (validPixID == npix) {
186 for (; validPixID < npix; validPixID++) {
187 if (!curChipData->getData()[validPixID].isMasked()) {
191 finishChip(curChipData, compClusPtr, patternsPtr, labelsDigPtr, labelsClPtr);
194 if (
parent->mMaxBCSeparationToMask > 0) {
195 parent->mChipsOld[chipID].swap(*curChipData);
198 auto& currStat =
stats.back();
199 currStat.nChips += nChips;
200 currStat.nClus = compClusPtr->size() - currStat.firstClus;
201 currStat.nPatt = patternsPtr ? (patternsPtr->size() - currStat.firstPatt) : 0;
208 const auto& pixData = curChipData->
getData();
209 for (
size_t i1 = 0; i1 < preClusterHeads.size(); ++i1) {
210 auto ci = preClusterIndices[i1];
216 int next = preClusterHeads[i1];
219 const auto& pixEntry =
pixels[next];
220 const auto pix = pixData[pixEntry.second];
221 pixArrBuff.push_back(pix);
222 bbox.adjust(pix.getRowDirect(), pix.getCol());
224 if (parent->mSquashingDepth) {
225 fetchMCLabels(curChipData->
getOrderedPixId(pixEntry.second), labelsDigPtr, nlab);
227 fetchMCLabels(pixEntry.second + curChipData->
getStartID(), labelsDigPtr, nlab);
230 next = pixEntry.first;
232 preClusterIndices[i1] = -1;
233 for (
size_t i2 = i1 + 1; i2 < preClusterHeads.size(); ++i2) {
234 if (preClusterIndices[i2] != ci) {
237 next = preClusterHeads[i2];
239 const auto& pixEntry =
pixels[next];
240 const auto pix = pixData[pixEntry.second];
241 pixArrBuff.push_back(pix);
242 bbox.adjust(pix.getRowDirect(), pix.getCol());
243 if (labelsClusPtr !=
nullptr) {
244 if (parent->mSquashingDepth) {
245 fetchMCLabels(curChipData->
getOrderedPixId(pixEntry.second), labelsDigPtr, nlab);
247 fetchMCLabels(pixEntry.second + curChipData->
getStartID(), labelsDigPtr, nlab);
250 next = pixEntry.first;
252 preClusterIndices[i2] = -1;
254 if (
bbox.isAcceptableSize()) {
255 parent->streamCluster(pixArrBuff, &labelsBuff,
bbox, parent->mPattIdConverter, compClusPtr, patternsPtr, labelsClusPtr, nlab);
259 LOGP(warn,
"Splitting a huge cluster: chipID {}, rows {}:{} cols {}:{}{}",
bbox.chipID,
bbox.rowMin,
bbox.rowMax,
bbox.colMin,
bbox.colMax,
260 warnLeft == 1 ?
" (Further warnings will be muted)" :
"");
265 parent->mNHugeClus++;
269 std::vector<PixelData> pixbuf;
275 for (
const auto& pix : pixArrBuff) {
276 if (bboxT.
isInside(pix.getRowDirect(), pix.getCol())) {
277 pixbuf.push_back(pix);
280 if (!pixbuf.empty()) {
281 parent->streamCluster(pixbuf, &labelsBuff, bboxT, parent->mPattIdConverter, compClusPtr, patternsPtr, labelsClusPtr, nlab,
true);
296 auto pix = curChipData->
getData()[hit];
297 uint16_t
row = pix.getRowDirect(),
col = pix.getCol();
301 fetchMCLabels(curChipData->
getStartID() + hit, labelsDigPtr, nlab);
302 auto cnt = compClusPtr->size();
303 for (
int i = nlab;
i--;) {
312 patternsPtr->emplace_back(1);
313 patternsPtr->emplace_back(1);
314 patternsPtr->insert(patternsPtr->end(), std::begin(patt), std::begin(patt) + 1);