28#include "GPUDefParametersRuntime.h"
54#ifndef GPUCA_STANDALONE
73std::pair<uint32_t, uint32_t> GPUChainTracking::TPCClusterizerDecodeZSCountUpdate(uint32_t
iSector,
const CfFragment& frag)
80 for (uint16_t
j = 0;
j < GPUTrackingInOutZS::NENDPOINTS;
j++) {
83 uint16_t posInEndpoint = 0;
84 uint16_t pagesEndpoint = 0;
88 for (uint32_t l = pageFirst; l < pageLast; l++) {
99 GPUError(
"TPC raw page count mismatch in TPCClusterizerDecodeZSCountUpdate: expected %d / buffered %lu", pagesEndpoint,
mCFContext->fragmentData[frag.
index].pageDigits[
iSector][
j].size());
102 GPUFatal(
"TPC raw page count mismatch in TPCClusterizerDecodeZSCountUpdate: expected %d / buffered %lu", pagesEndpoint,
mCFContext->fragmentData[frag.
index].pageDigits[
iSector][
j].size());
115 TPCClusterizerEnsureZSOffsets(
iSector, frag);
120void GPUChainTracking::TPCClusterizerEnsureZSOffsets(uint32_t
iSector,
const CfFragment& frag)
126 uint32_t pagesEndpoint = 0;
130 uint32_t nAdcDecoded = 0;
135 for (uint32_t
j = pageFirst;
j < pageLast;
j++) {
139 const uint16_t nSamplesInPage = decHdr->
nADCsamples;
141 nAdcDecoded += nSamplesInPage;
146 if (pagesEndpoint != nPagesExpected) {
147 GPUFatal(
"Sector %d, Endpoint %d, Fragment %d: TPC raw page count mismatch: expected %d / buffered %u",
iSector,
endpoint, frag.
index, pagesEndpoint, nPagesExpected);
150 if (nAdcDecoded != nAdcsExpected) {
151 GPUFatal(
"Sector %d, Endpoint %d, Fragment %d: TPC ADC count mismatch: expected %u, buffered %u",
iSector,
endpoint, frag.
index, nAdcsExpected, nAdcDecoded);
158 nAdcs += nAdcsExpected;
168 if (frag.
index != 0) {
177 const size_t chargeMapSizeBytes = chargeMapSize *
sizeof(
PackedCharge);
180 chargeMapHostData.resize(chargeMapSize);
185 extraPositions.reserve(
digits.size());
187 GPUMemCpy(RecoStep::TPCClusterFinding, chargeMapHostData.data(), clustererShadow.
mPchargeMap, chargeMapSizeBytes, lane,
false);
190 for (
const auto& d :
digits) {
191 if (!frag.contains(d.getTimeStamp())) {
198 extraPositions.push_back(
pos);
201 GPUMemCpy(RecoStep::TPCClusterFinding, clustererShadow.
mPchargeMap, chargeMapHostData.data(), chargeMapSizeBytes, lane,
true);
204 const size_t extraPositionsOffset = nPositions - extraPositions.size();
205 GPUMemCpy(RecoStep::TPCClusterFinding, clustererShadow.
mPpositions + extraPositionsOffset, extraPositions.data(), extraPositions.size() *
sizeof(
CfChargePos), lane,
true);
214 if (frag.
index != 0) {
223 const size_t chargeMapSizeBytes = chargeMapSize *
sizeof(
PackedCharge);
226 chargeMapHostData.resize(chargeMapSize);
230 GPUMemCpy(RecoStep::TPCClusterFinding, chargeMapHostData.data(), clustererShadow.
mPchargeMap, chargeMapSizeBytes, lane,
false);
233 size_t nNonZeroADCs = 0;
235 for (
const auto& d :
digits) {
236 if (!frag.contains(d.getTimeStamp())) {
242 auto adc = chargeMapHost[
pos].unpack();
249 if (nNonZeroADCs > 0) {
250 GPUInfo(
"Non Zero ADCs: %zu", nNonZeroADCs);
252 GPUInfo(
"Cleared all extra ADC values!");
258struct TPCCFDecodeScanTmp {
270 constexpr int32_t MinTailLength = 50;
271 constexpr int32_t MaxTailLength = 200;
272 constexpr int32_t TailWidth = 3;
278 const int32_t nHIPs = 50;
279 const int32_t firstTB = 0;
280 const int32_t lastTB = 4000 - MaxTailLength;
281 const int32_t tailADC = 250;
283 std::mt19937
gen{(uint32_t)seed};
284 std::uniform_int_distribution<> randomRow(0, GPUTPCGeometry::NROWS - 1);
285 std::uniform_int_distribution<> randomTB(firstTB, lastTB);
286 std::uniform_int_distribution<> randomTailLength(MinTailLength, MaxTailLength);
289 for (int32_t iHIP = 0; iHIP < nHIPs; iHIP++) {
291 const int32_t
row = randomRow(
gen);
292 const int32_t nPads = geo.NPads(
row);
293 std::uniform_int_distribution<> randomPad(0, nPads - 1);
295 const int32_t basePad = randomPad(
gen);
296 const int32_t baseTb = randomTB(
gen);
300 const int32_t tailLength = randomTailLength(
gen);
302 for (int32_t dPad = -TailWidth; dPad <= TailWidth; dPad++) {
303 const int32_t iPad = basePad + dPad;
304 if (iPad < 0 || iPad >= nPads) {
308 for (int32_t dTime = 0; dTime < tailLength; dTime++) {
309 const int32_t iTime = baseTb + dTime;
315 const auto adc = dTime == 0 && dPad == 0 ? 1023 : tailADC;
329std::pair<uint32_t, uint32_t> GPUChainTracking::TPCClusterizerDecodeZSCount(uint32_t
iSector,
const CfFragment& frag)
332 uint32_t nDigits = 0;
334 uint32_t endpointAdcSamples[GPUTrackingInOutZS::NENDPOINTS];
335 memset(endpointAdcSamples, 0,
sizeof(endpointAdcSamples));
339 for (uint16_t
j = 0;
j < GPUTrackingInOutZS::NENDPOINTS;
j++) {
350 std::vector<std::pair<CfFragment, TPCCFDecodeScanTmp>> fragments;
352 fragments.emplace_back(std::pair<CfFragment, TPCCFDecodeScanTmp>{frag, {0, 0, 0, 0, 0, -1}});
354 fragments.emplace_back(std::pair<CfFragment, TPCCFDecodeScanTmp>{fragments.back().
first.next(), {0, 0, 0, 0, 0, -1}});
356 std::vector<bool> fragmentExtends(
mCFContext->nFragments,
false);
358 uint32_t firstPossibleFragment = 0;
360 uint32_t emptyPages = 0;
384 static bool errorShown =
false;
385 if (errorShown ==
false) {
386 GPUAlarm(
"Trigger handling only possible with TPC Dense Link Based data, received version %d, disabling",
mCFContext->zsVersion);
391 GPUError(
"Received TPC ZS 8kb page of mixed versions, expected %d, received %d (linkid %d, feeCRU %d, feeEndpoint %d, feelinkid %d)",
mCFContext->zsVersion, (int32_t)
hdr->
version, (int32_t)o2::raw::RDHUtils::getLinkID(*rdh), (int32_t)rdh_utils::getCRU(*rdh), (int32_t)rdh_utils::getEndPoint(*rdh), (int32_t)rdh_utils::getLink(*rdh));
392 constexpr size_t bufferSize = 3 * std::max(
sizeof(*rdh),
sizeof(*
hdr)) + 1;
394 for (
size_t i = 0;
i <
sizeof(*rdh);
i++) {
396 snprintf(dumpBuffer + 3 *
i, 4,
"%02X ", (int32_t)((uint8_t*)rdh)[
i]);
398 GPUAlarm(
"RDH of page: %s", dumpBuffer);
399 for (
size_t i = 0;
i <
sizeof(*hdr);
i++) {
401 snprintf(dumpBuffer + 3 *
i, 4,
"%02X ", (int32_t)((uint8_t*)
hdr)[
i]);
403 GPUAlarm(
"Metainfo of page: %s", dumpBuffer);
408 GPUFatal(
"Cannot process with invalid TPC ZS data, exiting");
413 if (hdr2->
flags & TPCZSHDRV2::ZSFlags::TriggerWordPresent) {
414 const char* triggerWord = (
const char*)
hdr - TPCZSHDRV2::TRIGGER_WORD_SIZE;
416 memcpy((
void*)&tmp.
triggerWord, triggerWord, TPCZSHDRV2::TRIGGER_WORD_SIZE);
417 tmp.
orbit = o2::raw::RDHUtils::getHeartBeatOrbit(*rdh);
425 uint32_t timeBin = (
hdr->
timeOffset + (o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) - firstHBF) * o2::constants::lhc::LHCMaxBunches) / LHCBCPERTIMEBIN;
427 if (
mCFContext->zsVersion >= ZSVersion::ZSVersionDenseLinkBased) {
429 if (hdr2->
flags & TPCZSHDRV2::ZSFlags::nTimeBinSpanBit8) {
436 bool extendsInNextPage =
false;
437 if (
mCFContext->zsVersion >= ZSVersion::ZSVersionDenseLinkBased) {
440 extendsInNextPage = o2::raw::RDHUtils::getHeartBeatOrbit(*nextrdh) == o2::raw::RDHUtils::getHeartBeatOrbit(*rdh) && o2::raw::RDHUtils::getMemorySize(*nextrdh) >
sizeof(
o2::header::RAWDataHeader);
443 while (firstPossibleFragment && (uint32_t)fragments[firstPossibleFragment - 1].first.last() > timeBin) {
444 firstPossibleFragment--;
446 auto handleExtends = [&](uint32_t ff) {
447 if (fragmentExtends[ff]) {
451 fragments[ff].second.zsPageLast++;
455 fragmentExtends[ff] =
false;
458 if (
mCFContext->zsVersion >= ZSVersion::ZSVersionDenseLinkBased) {
459 for (uint32_t ff = 0; ff < firstPossibleFragment; ff++) {
463 for (uint32_t
f = firstPossibleFragment;
f <
mCFContext->nFragments;
f++) {
464 if (timeBin < (uint32_t)fragments[
f].
first.last() && (uint32_t)fragments[
f].first.first() <= maxTimeBin) {
465 if (!fragments[
f].second.hasData) {
466 fragments[
f].second.hasData = 1;
467 fragments[
f].second.zsPtrFirst = k;
468 fragments[
f].second.zsPageFirst = l;
470 if (
pageCounter > (uint32_t)fragments[
f].second.pageCounter + 1) {
472 for (uint32_t k2 = fragments[
f].second.zsPtrLast - 1;
k2 <= k;
k2++) {
481 const TPCZSHDR*
const hdrTmp = (
const TPCZSHDR*)(rdh_utils::getLink(o2::raw::RDHUtils::getFEEID(*rdhTmp)) == rdh_utils::DLBZSLinkID ? (pageTmp + o2::raw::RDHUtils::getMemorySize(*rdhTmp) -
sizeof(
TPCZSHDRV2)) : (pageTmp +
sizeof(
o2::header::RAWDataHeader)));
487 }
else if (emptyPages) {
490 for (uint32_t
m = 0;
m < emptyPages;
m++) {
496 fragments[
f].second.zsPtrLast = k + 1;
497 fragments[
f].second.zsPageLast = l + 1;
504 fragmentExtends[
f] = extendsInNextPage;
507 if (timeBin < (uint32_t)fragments[
f].
first.last()) {
508 if (
mCFContext->zsVersion >= ZSVersion::ZSVersionDenseLinkBased) {
509 for (uint32_t ff =
f + 1; ff <
mCFContext->nFragments; ff++) {
515 firstPossibleFragment =
f + 1;
533 for (uint32_t
i = 0;
i < GPUTrackingInOutZS::NENDPOINTS;
i++) {
538 uint32_t nDigitsFragmentMax = 0;
540 uint32_t pagesInFragment = 0;
541 uint32_t digitsInFragment = 0;
542 for (uint16_t
j = 0;
j < GPUTrackingInOutZS::NENDPOINTS;
j++) {
547 nDigitsFragmentMax = std::max(nDigitsFragmentMax, digitsInFragment);
550 return {nDigits, nDigitsFragmentMax};
561 std::vector<size_t> counts;
564 if (nSteps > clusterer.
mNBufs) {
565 GPUError(
"Clusterer buffers exceeded (%u > %u)", nSteps, (int32_t)clusterer.
mNBufs);
570 size_t tmpCount =
count;
572 for (uint32_t
i = 1;
i < nSteps;
i++) {
573 counts.push_back(tmpCount);
575 runKernel<GPUTPCCFStreamCompaction, GPUTPCCFStreamCompaction::scanStart>({
GetGrid(tmpCount, scanWorkgroupSize, lane), {
iSector}},
i, stage);
577 runKernel<GPUTPCCFStreamCompaction, GPUTPCCFStreamCompaction::scanUp>({
GetGrid(tmpCount, scanWorkgroupSize, lane), {
iSector}},
i, tmpCount);
579 tmpCount = (tmpCount + scanWorkgroupSize - 1) / scanWorkgroupSize;
582 runKernel<GPUTPCCFStreamCompaction, GPUTPCCFStreamCompaction::scanTop>({
GetGrid(tmpCount, scanWorkgroupSize, lane), {
iSector}}, nSteps, tmpCount);
584 for (uint32_t
i = nSteps - 1;
i > 1;
i--) {
585 tmpCount = counts[
i - 1];
586 runKernel<GPUTPCCFStreamCompaction, GPUTPCCFStreamCompaction::scanDown>({
GetGrid(tmpCount - scanWorkgroupSize, scanWorkgroupSize, lane), {
iSector}},
i, scanWorkgroupSize, tmpCount);
590 runKernel<GPUTPCCFStreamCompaction, GPUTPCCFStreamCompaction::compactDigits>({
GetGrid(
count, scanWorkgroupSize, lane), {
iSector}}, 1, stage, in, out);
598 for (
size_t i = 0;
i < nIn;
i++) {
607std::pair<uint32_t, uint32_t> GPUChainTracking::RunTPCClusterizer_transferZS(int32_t
iSector,
const CfFragment& frag, int32_t lane,
const GPUTPCExtraADC& extraADCs)
613 auto retVal = TPCClusterizerDecodeZSCountUpdate(
iSector, frag);
614 if (frag.
index == 0) {
620 uint32_t nPagesSector = 0;
621 for (uint32_t
j = 0;
j < GPUTrackingInOutZS::NENDPOINTS;
j++) {
624 mInputsHost->mPzsPtrs[
iSector * GPUTrackingInOutZS::NENDPOINTS +
j] = clustererShadow.
mPzs + (nPagesSector + nPages) * TPCZSHDR::TPC_ZS_PAGE_SIZE;
632 GPUMemCpy(RecoStep::TPCClusterFinding, clustererShadow.
mPzs + (nPagesSector + nPages) * TPCZSHDR::TPC_ZS_PAGE_SIZE,
src,
size, lane,
true);
639 nPagesSector += nPages;
646int32_t GPUChainTracking::RunTPCClusterizer_prepare(
bool restorePointers,
const GPUTPCExtraADC& extraADCs)
649 if (restorePointers) {
664 const uint32_t maxAllowedTimebin =
param().
par.continuousTracking ? std::max<int32_t>(
param().continuousMaxTimeBin, maxFragmentLen) : constants::TPC_MAX_TIME_BIN_TRIGGERED;
665 mCFContext->tpcMaxTimeBin = maxAllowedTimebin;
672 uint32_t nDigitsFragmentMax[
NSECTORS];
678 GPUError(
"Data has invalid RDH version %d, %d required (sector %d)\n",
o2::raw::RDHUtils::getVersion(rdh), o2::raw::RDHUtils::getVersion<o2::header::RAWDataHeader>(),
iSector);
684 for (uint32_t
j = 0;
j < GPUTrackingInOutZS::NENDPOINTS;
j++) {
694 const auto&
x = TPCClusterizerDecodeZSCount(
iSector, fragmentMax);
695 nDigitsFragmentMax[
iSector] =
x.first;
700 uint32_t nDigitsBase = nDigitsFragmentMax[
iSector];
701 uint32_t threshold = 40000000;
702 uint32_t nDigitsScaled = nDigitsBase > threshold ? nDigitsBase : std::min((threshold + nDigitsBase) / 2, 2 * nDigitsBase);
729 if (
mCFContext->tpcMaxTimeBin > maxAllowedTimebin) {
730 GPUError(
"Input data has invalid time bin %u > %d",
mCFContext->tpcMaxTimeBin, maxAllowedTimebin);
733 mCFContext->tpcMaxTimeBin = maxAllowedTimebin;
759 if (
param().
rec.fwdTPCDigitsAsClusters) {
770#ifdef INSERT_SATURATED_SIGNALS
771 extraADCs = GenerateSaturatedSignals();
774 if (RunTPCClusterizer_prepare(mPipelineNotifyCtx &&
GetProcessingSettings().doublePipelineClusterizer, extraADCs)) {
782 float tpcHitLowOccupancyScalingFactor = 1.f;
790 if (nHitsBase < threshold) {
793 tpcHitLowOccupancyScalingFactor = std::min(3.5f, (
float)threshold / nHitsBase);
804 RunTPCClusterizer_prepare(
true, extraADCs);
822 if (nn_settings.applyNNclusterizer) {
823 int32_t deviceId = -1;
829 nnTimers[0] = &getTimer<GPUTPCNNClusterizer, 0>(
"GPUTPCNNClusterizer_ONNXClassification_0_", 0);
830 nnTimers[1] = &getTimer<GPUTPCNNClusterizer, 1>(
"GPUTPCNNClusterizer_ONNXRegression_1_", 1);
831 nnTimers[2] = &getTimer<GPUTPCNNClusterizer, 2>(
"GPUTPCNNClusterizer_ONNXRegression2_2_", 2);
832 nnTimers[3] = &getTimer<GPUTPCNNClusterizer, 3>(
"GPUTPCNNClusterizer_ONNXClassification_0_", 3);
833 nnTimers[4] = &getTimer<GPUTPCNNClusterizer, 4>(
"GPUTPCNNClusterizer_ONNXRegression_1_", 4);
834 nnTimers[5] = &getTimer<GPUTPCNNClusterizer, 5>(
"GPUTPCNNClusterizer_ONNXRegression2_2_", 5);
835 nnTimers[6] = &getTimer<GPUTPCNNClusterizer, 6>(
"GPUTPCNNClusterizer_ONNXClassification_0_", 6);
836 nnTimers[7] = &getTimer<GPUTPCNNClusterizer, 7>(
"GPUTPCNNClusterizer_ONNXRegression_1_", 7);
837 nnTimers[8] = &getTimer<GPUTPCNNClusterizer, 8>(
"GPUTPCNNClusterizer_ONNXRegression2_2_", 8);
838 nnTimers[9] = &getTimer<GPUTPCNNClusterizer, 9>(
"GPUTPCNNClusterizer_ONNXClassification_0_", 9);
839 nnTimers[10] = &getTimer<GPUTPCNNClusterizer, 10>(
"GPUTPCNNClusterizer_ONNXRegression_1_", 10);
840 nnTimers[11] = &getTimer<GPUTPCNNClusterizer, 11>(
"GPUTPCNNClusterizer_ONNXRegression2_2_", 11);
845 if (nnApplications[lane].mModelsUsed[0]) {
846 SetONNXGPUStream(*(nnApplications[lane].mModelClass).getSessionOptions(), lane, &deviceId);
847 (nnApplications[lane].
mModelClass).setDeviceId(deviceId);
848 if (nnApplications[lane].mModelClass.getIntraOpNumThreads() > maxThreads) {
851 (nnApplications[lane].
mModelClass).initEnvironment();
860 if (!nn_settings.nnLoadFromCCDB) {
866 if (nnApplications[lane].mModelsUsed[1]) {
867 SetONNXGPUStream(*(nnApplications[lane].mModelReg1).getSessionOptions(), lane, &deviceId);
868 (nnApplications[lane].
mModelReg1).setDeviceId(deviceId);
869 if (nnApplications[lane].mModelReg1.getIntraOpNumThreads() > maxThreads) {
873 (nnApplications[lane].
mModelReg1).initEnvironment();
875 if (!nn_settings.nnLoadFromCCDB) {
876 (nnApplications[lane].
mModelReg1).initSession();
881 if (nnApplications[lane].mModelsUsed[2]) {
882 SetONNXGPUStream(*(nnApplications[lane].mModelReg2).getSessionOptions(), lane, &deviceId);
883 (nnApplications[lane].
mModelReg2).setDeviceId(deviceId);
884 if (nnApplications[lane].mModelReg2.getIntraOpNumThreads() > maxThreads) {
888 (nnApplications[lane].
mModelReg2).initEnvironment();
890 if (!nn_settings.nnLoadFromCCDB) {
891 (nnApplications[lane].
mModelReg2).initSession();
896 if (nn_settings.nnClusterizerVerbosity > 0) {
897 LOG(info) <<
"(ORT) Allocated ONNX stream for lane " << lane <<
" and device " << deviceId;
901 const uint32_t maxAllowedTimebin =
param().
par.continuousTracking ? std::max<int32_t>(
param().continuousMaxTimeBin, maxFragmentLen) : constants::TPC_MAX_TIME_BIN_TRIGGERED;
902 for (int32_t sector = 0; sector <
NSECTORS; sector++) {
905 int32_t lane = sector % numLanes;
909 nnApplications[lane].
initClusterizer(nn_settings, clustererNN, maxFragmentLen, maxAllowedTimebin);
912 clustererNNShadow.
mISector = sector;
914 nnApplications[lane].
initClusterizer(nn_settings, clustererNNShadow, maxFragmentLen, maxAllowedTimebin);
916 if (nn_settings.nnClusterizerVerbosity > 2) {
917 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Processor initialized. Sector " << sector <<
", lane " << lane <<
", max clusters " << clustererNN.
mNnClusterizerTotalClusters <<
" (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
920 if (nn_settings.nnClusterizerVerbosity > 2) {
921 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Memory registered for memoryId " << clustererNN.
mMemoryId <<
" (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
927 if (nn_settings.nnClusterizerVerbosity > 2) {
928 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Writing to constant memory...";
931 if (nn_settings.nnClusterizerVerbosity > 2) {
932 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Writing to constant memory done";
938 size_t nClsTotal = 0;
941 std::unique_ptr<ClusterNative[]> tmpNativeClusterBuffer;
943 const bool buildNativeGPU = doGPU && NeedTPCClustersOnGPU();
949 GPUWarning(
"Requested to process MC labels, but no labels present");
955 if (buildNativeGPU) {
959 GPUFatal(
"ERROR, mWaitForFinalInputs cannot be called with nTPCClustererLanes > 6");
962 if (mWaitForFinalInputs) {
963 GPUFatal(
"Cannot use waitForFinalInput callback without delayed output");
967 tmpNativeClusters =
mInputsHost->mPclusterNativeOutput;
969 tmpNativeClusterBuffer = std::make_unique<ClusterNative[]>(
mInputsHost->mNClusterNative);
970 tmpNativeClusters = tmpNativeClusterBuffer.get();
975 if (propagateMCLabels) {
981 int8_t transferRunning[
NSECTORS] = {0};
984 auto notifyForeignChainFinished = [
this]() {
985 if (mPipelineNotifyCtx) {
988 std::lock_guard<std::mutex> lock(mPipelineNotifyCtx->
mutex);
989 mPipelineNotifyCtx->
ready =
true;
991 mPipelineNotifyCtx->
cond.notify_one();
994 bool synchronizeCalibUpdate =
false;
998 static_assert(
NSECTORS <= constants::GPU_MAX_STREAMS,
"Stream events must be able to hold all sectors");
1002 GPUInfo(
"Processing time bins [%d, %d) for sectors %d to %d", frag.
start, frag.last(), iSectorBase, iSectorBase +
GetProcessingSettings().nTPCClustererLanes - 1);
1005 if (doGPU && frag.
index != 0) {
1006 SynchronizeStream(lane);
1009 uint32_t
iSector = iSectorBase + lane;
1017 bool setDigitsOnHost = (not doGPU && not
mIOPtrs.
tpcZS) || propagateMCLabels;
1020 if (setDigitsOnGPU) {
1021 GPUMemCpy(RecoStep::TPCClusterFinding, clustererShadow.
mPdigits, inDigits->tpcDigits[
iSector],
sizeof(clustererShadow.
mPdigits[0]) * numDigits, lane,
true);
1023 if (setDigitsOnHost) {
1039 using ChargeMapType =
decltype(*clustererShadow.
mPchargeMap);
1040 using PeakMapType =
decltype(*clustererShadow.
mPpeakMap);
1043 if (frag.
index == 0) {
1065 if (propagateMCLabels) {
1066 if (frag.
index == 0) {
1073 GPUFatal(
"MC label container missing, sector %d",
iSector);
1082 runKernel<GPUTPCCFChargeMapFiller, GPUTPCCFChargeMapFiller::findFragmentStart>({
GetGrid(1, lane), {
iSector}},
mIOPtrs.
tpcZS ==
nullptr);
1084 }
else if (propagateMCLabels) {
1096 GPUFatal(
"Data with invalid TPC ZS mode (%d) received",
mCFContext->zsVersion);
1100 runKernel<GPUTPCCFDecodeZS>({
GetGridBlk(nBlocks, lane), {
iSector}}, firstHBF, tpcTimeBinCut);
1103 runKernel<GPUTPCCFDecodeZSLink>({
GetGridBlk(nBlocks, lane), {
iSector}}, firstHBF, tpcTimeBinCut);
1106 runKernel<GPUTPCCFDecodeZSDenseLink>({
GetGridBlk(nBlocks, lane), {
iSector}}, firstHBF, tpcTimeBinCut);
1113 uint32_t
iSector = iSectorBase + lane;
1124 if (nextSector < NSECTORS && mIOPtrs.tpcZS && mCFContext->nPagesSector[nextSector] &&
mCFContext->zsVersion != -1 && !
mCFContext->abandonTimeframe) {
1137 TPCClusterizerTransferExtraADC(clusterer, clustererShadow, lane, extraADCs);
1139 if (propagateMCLabels) {
1143 bool checkForNoisyPads = (
rec()->
GetParam().
rec.tpc.maxTimeBinAboveThresholdIn1000Bin > 0) || (
rec()->
GetParam().
rec.tpc.maxConsecTimeBinAboveThreshold > 0);
1144 checkForNoisyPads &= (
rec()->
GetParam().
rec.tpc.noisyPadsQuickCheck ? frag.
index == 0 :
true);
1150 if (checkForNoisyPads) {
1155 const int32_t nBlocks = GPUTPCGeometry::NROWS;
1167 TPCClusterizerCheckExtraADCZeros(clusterer, clustererShadow, lane, extraADCs);
1174 RunTPCClusterizer_compactPeaks(clusterer, clustererShadow, 0, doGPU, lane);
1179 uint32_t
iSector = iSectorBase + lane;
1194 RunTPCClusterizer_compactPeaks(clusterer, clustererShadow, 1, doGPU, lane);
1199 uint32_t
iSector = iSectorBase + lane;
1203 const bool resetClusterCounters = frag.
index == 0;
1213 if (resetClusterCounters) {
1215 if (transferRunning[lane] == 1) {
1217 transferRunning[lane] = 2;
1227 if (nRegularClusters != 0) {
1229#ifdef GPUCA_HAS_ONNX
1236 if (nn_settings.nnClusterizerApplyCfDeconvolution) {
1243 if (nn_settings.nnClusterizerVerbosity > 2) {
1247 if (nn_settings.nnClusterizerVerbosity > 3) {
1248 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Start. Loop=" << batch <<
". (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
1261 if (nn_settings.nnClusterizerVerbosity > 3) {
1262 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Done filling data. Loop=" << batch <<
". (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
1267 if (nn_settings.nnClusterizerVerbosity > 3) {
1268 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Done setting deconvolution flags. Loop=" << batch <<
". (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
1289 if (nn_settings.nnClusterizerVerbosity > 3) {
1290 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Done with NN classification inference. Loop=" << batch <<
". (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
1326 if (nn_settings.nnClusterizerVerbosity > 3) {
1327 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Done with NN regression inference. Loop=" << batch <<
". (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
1344 if (nn_settings.nnClusterizerVerbosity > 3) {
1345 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Done publishing. Loop=" << batch <<
". (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
1350 if(!nn_settings.nnClusterizerApplyCfDeconvolution) {
1355 if (nn_settings.nnClusterizerVerbosity > 3) {
1356 LOG(info) <<
"(NNCLUS, GPUChainTrackingClusterizer, this=" <<
this <<
") Done with CF regression. (clustererNN=" << &clustererNN <<
", clustererNNShadow=" << &clustererNNShadow <<
")";
1360 GPUFatal(
"Project not compiled with neural network clusterization. Aborting.");
1368 if (doGPU && propagateMCLabels) {
1378 runKernel<GPUTPCCFHIPTailConnector>({
GetGridBlk(GPUTPCGeometry::NROWS, lane), {
iSector}});
1379 runKernel<GPUTPCCFHIPClusterizer>({
GetGridBlk(GPUTPCGeometry::NROWS, lane), {
iSector}}, 0);
1384 if (doGPU && propagateMCLabels) {
1391 bool hasClusters = nRegularClusters != 0;
1398 if (
rec()->
GetParam().
rec.tpc.hipTailFilter && nRegularClusters == 0) {
1399 for (uint32_t
row = 0;
row < GPUTPCGeometry::NROWS;
row++) {
1413 laneHasData[lane] =
true;
1418 size_t nClsFirst = nClsTotal;
1419 bool anyLaneHasData =
false;
1420 for (int32_t lane = 0; lane < maxLane; lane++) {
1421 uint32_t
iSector = iSectorBase + lane;
1429 if (laneHasData[lane]) {
1430 anyLaneHasData =
true;
1437 for (uint32_t
j = 0;
j < GPUTPCGeometry::NROWS;
j++) {
1442 if (buildNativeGPU) {
1446 }
else if (buildNativeHost) {
1452 if (transferRunning[lane]) {
1456 transferRunning[lane] = 1;
1459 if (not propagateMCLabels || not laneHasData[lane]) {
1466 assert(propagateMCLabels ? mcLinearLabels.
header.size() == nClsTotal :
true);
1468 for (int32_t lane = 0; lane < maxLane; lane++) {
1471 if (buildNativeHost && buildNativeGPU && anyLaneHasData) {
1473 mOutputQueue.emplace_back(
outputQueueEntry{(
void*)((
char*)&tmpNativeClusters[nClsFirst] - (
char*)&tmpNativeClusters[0]), &
mInputsShadow->mPclusterNativeBuffer[nClsFirst], (nClsTotal - nClsFirst) *
sizeof(tmpNativeClusters[0]), RecoStep::TPCClusterFinding});
1475 GPUMemCpy(RecoStep::TPCClusterFinding, (
void*)&tmpNativeClusters[nClsFirst], (
const void*)&
mInputsShadow->mPclusterNativeBuffer[nClsFirst], (nClsTotal - nClsFirst) *
sizeof(tmpNativeClusters[0]),
mRec->
NStreams() - 1,
false);
1479 if (mWaitForFinalInputs && iSectorBase >= 21 && (int32_t)iSectorBase < 21 +
GetProcessingSettings().nTPCClustererLanes) {
1480 notifyForeignChainFinished();
1482 if (mWaitForFinalInputs && iSectorBase >= 30 && (int32_t)iSectorBase < 30 +
GetProcessingSettings().nTPCClustererLanes) {
1483 if (mWaitForFinalInputs()) {
1490#ifdef GPUCA_HAS_ONNX
1493 LOG(info) <<
"(ORT) Environment releasing...";
1501 if (transferRunning[
i]) {
1508 if (triggerOutput && triggerOutput->
allocator) {
1518 GPUInfo(
"Event has %zu TPC Clusters", nClsTotal);
1522 if (propagateMCLabels) {
1524 std::pair<ConstMCLabelContainer*, ConstMCLabelContainerView*>
buffer;
1526 if (!
GetProcessingSettings().tpcWriteClustersAfterRejection && !sortClusters && labelOutputControl && labelOutputControl->useExternal()) {
1527 if (!labelOutputControl->allocator) {
1528 throw std::runtime_error(
"Cluster MC Label buffer missing");
1531 buffer = {&container->first, &container->second};
1538 assert(propagateMCLabels ? mcLinearLabels.
header.size() == nClsTotal :
true);
1539 assert(propagateMCLabels ? mcLinearLabels.
data.size() >= nClsTotal :
true);
1544 mcLabelsConstView =
buffer.second;
1550 tmpNativeClusters =
mInputsHost->mPclusterNativeOutput;
1556 if (buildNativeHost) {
1562 auto allocator = [
this, &tmpNativeClusters](
size_t size) {
1565 return (tmpNativeClusters = this->
mInputsHost->mPclusterNativeOutput);
1567 RunTPCClusterFilter(tmpNativeAccess, allocator,
false);
1572 if (!mWaitForFinalInputs) {
1573 notifyForeignChainFinished();
1576 if (buildNativeGPU) {
1581 mInputsHost->mPclusterNativeAccess->setOffsetPtrs();
1584 if (doGPU && synchronizeOutput) {
1587 if (doGPU && synchronizeCalibUpdate) {
1591 SortClusters(buildNativeGPU, propagateMCLabels, tmpNativeAccess, tmpNativeClusters);
1595 if (mPipelineNotifyCtx) {
1597 mPipelineNotifyCtx =
nullptr;
1610 if (propagateMCLabels) {
1612 std::iota(clsOrder.begin(), clsOrder.end(), 0);
1613 std::vector<ClusterNative> tmpClusters;
1615 for (uint32_t
j = 0;
j < GPUTPCGeometry::NROWS;
j++) {
1618 return clusters[a] < clusters[b];
1620 tmpClusters.resize(clusterAccess->
nClusters[
i][
j]);
1622 for (uint32_t k = 0; k < tmpClusters.size(); k++) {
1627 tmpClusters.clear();
1629 std::pair<o2::dataformats::ConstMCLabelContainer*, o2::dataformats::ConstMCLabelContainerView*> labelBuffer;
1631 std::unique_ptr<ConstMCLabelContainerView> tmpUniqueContainerView;
1632 std::unique_ptr<ConstMCLabelContainer> tmpUniqueContainerBuffer;
1633 if (labelOutput && labelOutput->
allocator) {
1635 labelBuffer = {&labelContainer->first, &labelContainer->second};
1646 for (
const auto&
element : clusterAccess->clustersMCTruth->
getLabels(clsOrder[
i])) {
1651 *labelBuffer.second = *labelBuffer.first;
1655 for (uint32_t
j = 0;
j < GPUTPCGeometry::NROWS;
j++) {
1660 if (buildNativeGPU) {
default_random_engine gen(dev())
std::vector< std::string > header
o2::raw::RawFileWriter * raw
Class to serialize ONNX objects for ROOT snapshots of CCDB objects at runtime.
std::enable_if_t< std::is_signed< T >::value, bool > hasData(const CalArray< T > &cal)
Provides a basic fallback implementation for Vc.
Definitions of TPC Zero Suppression Data Headers.
std::unique_ptr< o2::tpc::ClusterNativeAccess > mClusterNativeAccess
int32_t RunTPCClusterizer(bool synchronizeOutput=true)
std::unique_ptr< GPUTrackingInputProvider > mInputsHost
std::unique_ptr< std::ostream > mDebugFile
std::array< GPUOutputControl *, GPUTrackingOutputs::count()> mSubOutputControls
std::unique_ptr< GPUTriggerOutputs > mTriggerBuffer
std::vector< outputQueueEntry > mOutputQueue
bool mUpdateNewCalibObjects
std::unique_ptr< GPUTPCCFChainContext > mCFContext
int32_t DoQueuedUpdates(int32_t stream, bool updateSlave=true)
std::unique_ptr< GPUNewCalibValues > mNewCalibValues
GPUTrackingInOutPointers & mIOPtrs
struct o2::gpu::GPUChainTracking::InOutMemory mIOMem
std::unique_ptr< GPUTrackingInputProvider > mInputsShadow
int32_t ForwardTPCDigits()
void RecordMarker(deviceEvent *ev, int32_t stream)
void TransferMemoryResourceLinkToGPU(RecoStep step, int16_t res, int32_t stream=-1, deviceEvent *ev=nullptr, deviceEvent *evList=nullptr, int32_t nEvents=1)
void GPUMemCpyAlways(RecoStep step, void *dst, const void *src, size_t size, int32_t stream, int32_t toGPU, deviceEvent *ev=nullptr, deviceEvent *evList=nullptr, int32_t nEvents=1)
void GPUMemCpy(RecoStep step, void *dst, const void *src, size_t size, int32_t stream, int32_t toGPU, deviceEvent *ev=nullptr, deviceEvent *evList=nullptr, int32_t nEvents=1)
bool DoDebugAndDump(RecoStep step, uint32_t mask, T &processor, S T::*func, Args &&... args)
GPUReconstruction::RecoStepField GetRecoStepsGPU() const
GPUReconstruction::RecoStepField GetRecoSteps() const
void WriteToConstantMemory(RecoStep step, size_t offset, const void *src, size_t size, int32_t stream=-1, deviceEvent *ev=nullptr)
void ReleaseEvent(deviceEvent ev, bool doGPU=true)
krnlExec GetGrid(uint32_t totalItems, uint32_t nThreads, int32_t stream, GPUReconstruction::krnlDeviceType d=GPUReconstruction::krnlDeviceType::Auto, gpudatatypes::RecoStep st=gpudatatypes::RecoStep::NoRecoStep)
size_t AllocateRegisteredMemory(GPUProcessor *proc)
virtual std::unique_ptr< GPUReconstructionProcessing::threadContext > GetThreadContext()
GPUConstantMem * processors()
static constexpr krnlRunRange krnlRunRangeNone
void SetONNXGPUStream(Ort::SessionOptions &opt, int32_t stream, int32_t *deviceId)
krnlExec GetGridAutoStep(int32_t stream, gpudatatypes::RecoStep st=gpudatatypes::RecoStep::NoRecoStep)
void SetupGPUProcessor(T *proc, bool allocate)
const GPUSettingsProcessing & GetProcessingSettings() const
void SynchronizeStream(int32_t stream)
GPUReconstructionCPU * mRec
GPUConstantMem * processorsShadow()
krnlExec GetGridBlk(uint32_t nBlocks, int32_t stream, GPUReconstruction::krnlDeviceType d=GPUReconstruction::krnlDeviceType::Auto, gpudatatypes::RecoStep st=gpudatatypes::RecoStep::NoRecoStep)
static constexpr int32_t NSECTORS
const GPUParam & GetParam() const
void TransferMemoryResourceLinkToHost(RecoStep step, int16_t res, int32_t stream=-1, deviceEvent *ev=nullptr, deviceEvent *evList=nullptr, int32_t nEvents=1)
void TransferMemoryResourcesToHost(RecoStep step, GPUProcessor *proc, int32_t stream=-1, bool all=false)
GPUReconstruction * rec()
HighResTimer & getGeneralStepTimer(GeneralStep step)
void runParallelOuterLoop(bool doGPU, uint32_t nThreads, std::function< void(uint32_t)> lambda)
void SetNActiveThreads(int32_t n)
int32_t getNKernelHostThreads(bool splitCores)
const GPUDefParameters & getGPUParameters(bool doGPU) const override
void SetNActiveThreadsOuterLoop(uint32_t f)
void AllocateRegisteredForeignMemory(int16_t res, GPUReconstruction *rec, GPUOutputControl *control=nullptr)
void ComputeReuseMax(GPUProcessor *proc)
RecoStepField GetRecoStepsGPU() const
void UnblockStackedMemory()
void PopNonPersistentMemory(RecoStep step, uint64_t tag, const GPUProcessor *proc=nullptr)
uint32_t NStreams() const
const GPUParam & GetParam() const
void PushNonPersistentMemory(uint64_t tag)
InOutTypeField GetRecoStepsOutputs() const
GPUMemorySizeScalers * MemoryScalers()
static void setGlobalOffsetsAndAllocate(GPUTPCClusterFinder &, GPUTPCLinearLabels &)
void DumpDigits(std::ostream &out)
void SetMaxData(const GPUTrackingInOutPointers &io)
CfChargePos * mPpeakPositions
void DumpClusters(std::ostream &out)
void SetNMaxDigits(size_t nDigits, size_t nPages, size_t nDigitsFragment, size_t nDigitsEndpointMax)
void DumpSuppressedPeaks(std::ostream &out)
uint32_t mNMaxClusterPerRow
HIPTailDescriptor * mPhipTailsByRow
void DumpPeakMap(std::ostream &out, std::string_view)
o2::dataformats::ConstMCTruthContainerView< o2::MCCompLabel > const * mPinputLabels
void InitMCBuffersForFragment()
uint32_t * mPclusterInRow
void DumpChargeMap(std::ostream &out, std::string_view)
uint32_t getNSteps(size_t items) const
CfChargePos * mPpositions
CfChargePos * mPfilteredPeakPositions
void DumpSuppressedPeaksCompacted(std::ostream &out)
void DumpPeaksCompacted(std::ostream &out)
tpc::ClusterNative * mPclusterByRow
void DumpPeaks(std::ostream &out)
o2::ml::OrtModel mModelReg1
o2::ml::OrtModel mModelClass
o2::ml::OrtModel mModelReg2
void init(const GPUSettingsProcessingNNclusterizer &, bool=false)
void initClusterizer(const GPUSettingsProcessingNNclusterizer &, GPUTPCNNClusterizer &, int32_t=-1, int32_t=-1)
float * mOutputDataReg2_32
OrtDataType::Float16_t * mInputData_16
int32_t mNnClusterizerBatchedMode
int32_t mNnClusterizerTotalClusters
OrtDataType::Float16_t * mOutputDataReg2_16
float * mModelProbabilities_32
int32_t mNnClusterizerUseCfRegression
int32_t mNnInferenceInputDType
int32_t mNnInferenceOutputDType
float * mOutputDataReg1_32
uint32_t mNnClusterizerRowTimeSizeThreads
OrtDataType::Float16_t * mModelProbabilities_16
int8_t mNnClusterizerSetDeconvolutionFlags
OrtDataType::Float16_t * mOutputDataReg1_16
int8_t mNnClusterizerUseClassification
void setIntraOpNumThreads(int threads)
std::vector< std::vector< int64_t > > getNumOutputNodes() const
#define TPC_REAL_PADS_IN_SECTOR
#define TPC_CLUSTERER_STRIDED_PAD_COUNT
GLboolean GLboolean GLboolean b
GLboolean GLboolean GLboolean GLboolean a
uint8_t itsSharedClusterMap uint8_t
@ TPCClustererSuppressedPeaks
@ TPCClustererZeroedCharges
@ TPCClustererChargeMapSplit
void dumpBuffer(gsl::span< const std::byte > buffer, std::ostream &out=std::cout, size_t maxbytes=std::numeric_limits< size_t >::max())
std::unique_ptr< const o2::dataformats::MCTruthContainer< MCLabel > > getLabels(framework::ProcessingContext &pc, std::string_view dataBind, EventType eventType=EventType::Standard)
Global TPC definitions and constants.
@ ZSVersionDenseLinkBased
@ ZSVersionLinkBasedWithMeta
@ ZSVersionRowBased10BitADC
@ ZSVersionRowBased12BitADC
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
constexpr T qStr2Tag(const char(&str)[N])
S< o2::tpc::ORTRootSerializer >::type * nnClusterizerNetworks[3]
std::condition_variable cond
std::unique_ptr< o2::dataformats::ConstMCTruthContainerView< o2::MCCompLabel > > clusterNativeMCView
std::unique_ptr< o2::dataformats::ConstMCTruthContainer< o2::MCCompLabel > > clusterNativeMCBuffer
deviceEvent stream[constants::GPU_MAX_STREAMS]
GPUCalibObjectsConst calibObjects
GPUTPCClusterFinder tpcClusterer[GPUTPCGeometry::NSECTORS]
GPUTrackingInOutPointers ioPtrs
size_t NTPCClusters(size_t tpcDigits, bool perSector=false)
std::function< void *(size_t)> allocator
tpccf::SizeT nDigitsInFragment
struct o2::gpu::GPUTPCClusterFinder::Memory::counters_t counters
std::vector< o2::MCCompLabel > data
std::vector< o2::dataformats::MCTruthHeaderElement > header
size_t nTPCDigits[NSECTORS]
const GPUTPCDigitsMCInput * tpcDigitsMC
const o2::tpc::ClusterNativeAccess * clustersNative
const GPUSettingsTF * settingsTF
const GPUTrackingInOutZS * tpcZS
const GPUTrackingInOutDigits * tpcPackedDigits
const void *const * zsPtr[NENDPOINTS]
uint32_t count[NENDPOINTS]
const uint32_t * nZSPtr[NENDPOINTS]
GPUTrackingInOutZSSector sector[NSECTORS]
GPUOutputControl clustersNative
size_t getIndex(const GPUOutputControl &v)
GPUOutputControl clusterLabels
GPUOutputControl tpcTriggerWords
static constexpr int getVersion()
get numeric version of the RDH
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const o2::dataformats::ConstMCTruthContainerView< o2::MCCompLabel > * clustersMCTruth
std::pair< ConstMCLabelContainer, ConstMCLabelContainerView > ConstMCLabelContainerViewWithBuffer
unsigned int nClustersTotal
unsigned int clusterOffset[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const ClusterNative * clustersLinear
unsigned char nTimeBinSpan
unsigned short timeOffset
unsigned short nADCsamples
Trigger info including the orbit.
uint32_t orbit
orbit of the trigger word
TriggerWordDLBZS triggerWord
trigger Word information
bool isValid(int entry=0) const
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
std::vector< Cluster > clusters
std::vector< Digit > digits
typename std::vector< T, vecpod_allocator< T > > vecpod