71 auto& clusterer = processors.tpcClusterer[sector];
72 auto& clustererNN = processors.tpcNNClusterer[sector];
75 if (glo_idx + batchStart >= clusterer.mPmemory->counters.nClusters || glo_idx >= (uint32_t)clustererNN.mNnClusterizerBatchedMode) {
79 uint32_t write_idx = glo_idx * clustererNN.mNnClusterizerElementSize;
83 CfChargePos peak = clusterer.mPfilteredPeakPositions[CAMath::Min(glo_idx + batchStart, (uint32_t)(clusterer.mPmemory->counters.nClusters - 1))];
84 const int32_t
row =
static_cast<int>(peak.row());
85 const int32_t pad =
static_cast<int>(peak.pad());
86 const int32_t
time =
static_cast<int>(peak.time());
87 const float central_charge =
static_cast<float>(chargeMap[peak].unpack());
88 const float inverse_charge = 1.f / central_charge;
90 const int32_t row_offset = GPUTPCNNClusterizerKernels::rowOffset(
row, clustererNN.mNnClusterizerSizeInputRow);
91 const int32_t iroc_row = 63 + clustererNN.mNnClusterizerSizeInputRow;
92 const int32_t maxrow = o2::tpc::constants::MAXGLOBALPADROW + clustererNN.mNnClusterizerSizeInputRow;
93 const int32_t npads_row = GPUTPCGeometry::NPads(
row);
94 float output_value = clustererNN.mNnClusterizerBoundaryFillValue;
96 for (int32_t target_row = -clustererNN.mNnClusterizerSizeInputRow +
row; target_row <= clustererNN.mNnClusterizerSizeInputRow +
row; ++target_row) {
97 uint8_t is_boundary = (target_row < 0) || (target_row >= o2::tpc::constants::MAXGLOBALPADROW);
98 const int32_t p_local = pad + (is_boundary ? 0 : GPUTPCNNClusterizerKernels::padOffset(
row, target_row));
99 const int32_t npads_reference = is_boundary ? 0 : GPUTPCGeometry::NPads(target_row - row_offset);
101 for (int32_t target_pad = -clustererNN.mNnClusterizerSizeInputPad + p_local; target_pad <= clustererNN.mNnClusterizerSizeInputPad + p_local; ++target_pad) {
102 is_boundary = is_boundary || GPUTPCNNClusterizerKernels::isBoundary(target_row + row_offset, target_pad, maxrow, iroc_row, npads_row, npads_reference);
104 for (int32_t target_time = -clustererNN.mNnClusterizerSizeInputTime +
time; target_time <= clustererNN.mNnClusterizerSizeInputTime +
time; ++target_time) {
105 if (is_boundary || target_time < 0 || target_time >= clustererNN.maxAllowedTimebin) {
107 output_value = clustererNN.mNnClusterizerBoundaryFillValue;
109 clustererNN.mInputData_32[write_idx] = output_value;
111 clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)output_value;
114 CfChargePos tmp_pos(target_row, target_pad, target_time);
115 output_value = chargeMap[tmp_pos].unpack() * inverse_charge;
117 clustererNN.mInputData_32[write_idx] = output_value;
119 clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)output_value;
131 if (clustererNN.mNnClusterizerAddIndexData) {
133 clustererNN.mInputData_32[write_idx] =
static_cast<float>(sector) / o2::tpc::constants::MAXSECTOR;
134 clustererNN.mInputData_32[write_idx + 1] =
static_cast<float>(
row) / o2::tpc::constants::MAXGLOBALPADROW;
135 clustererNN.mInputData_32[write_idx + 2] =
static_cast<float>(pad) / npads_row;
137 clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)(
static_cast<float>(sector) / o2::tpc::constants::MAXSECTOR);
138 clustererNN.mInputData_16[write_idx + 1] = (OrtDataType::Float16_t)(
static_cast<float>(
row) / o2::tpc::constants::MAXGLOBALPADROW);
139 clustererNN.mInputData_16[write_idx + 2] = (OrtDataType::Float16_t)(
static_cast<float>(pad) / npads_row);
143 if (!clustererNN.mNnClusterizerSetDeconvolutionFlags) {
144 clustererNN.mClusterFlags[2 * glo_idx] = 0;
145 clustererNN.mClusterFlags[2 * glo_idx + 1] = 0;
147 for (uint16_t
i = 0;
i < 8; ++
i) {
148 Delta2 d = cfconsts::InnerNeighbors[
i];
150 clustererNN.mClusterFlags[2 * glo_idx] += CfUtils::isPeak(isPeakMap[tmp_pos]);
152 clustererNN.mClusterFlags[2 * glo_idx + 1] = clustererNN.mClusterFlags[2 * glo_idx];
164 auto& clusterer = processors.tpcClusterer[sector];
165 auto& clustererNN = processors.tpcNNClusterer[sector];
167 if (glo_idx >= (uint32_t)clustererNN.mNnClusterizerBatchedMode * clustererNN.mNnClusterizerRowTimeSizeThreads) {
171 const uint32_t base_idx = glo_idx / clustererNN.mNnClusterizerRowTimeSizeThreads;
172 const uint32_t transient_index = glo_idx - (base_idx * clustererNN.mNnClusterizerRowTimeSizeThreads);
175 if (base_idx + batchStart >= clusterer.mPmemory->counters.nClusters) {
183 CfChargePos peak = clusterer.mPfilteredPeakPositions[CAMath::Min(base_idx + batchStart, (uint32_t)(clusterer.mPmemory->counters.nClusters - 1))];
184 const float central_charge = chargeMap[peak].unpack();
185 const int32_t
row =
static_cast<int>(peak.row());
186 const int32_t pad =
static_cast<int>(peak.pad());
187 const int32_t
time =
static_cast<int>(peak.time());
190 if (clustererNN.mNnClusterizerAddIndexData && transient_index >= clustererNN.mNnClusterizerRowTimeSize) {
191 uint32_t write_idx = base_idx * clustererNN.mNnClusterizerElementSize + clustererNN.mNnClusterizerChargeArraySize;
192 const int32_t npads = GPUTPCGeometry::NPads(
row);
194 clustererNN.mInputData_32[write_idx] =
static_cast<float>(sector) / o2::tpc::constants::MAXSECTOR;
195 clustererNN.mInputData_32[write_idx + 1] =
static_cast<float>(
row) / o2::tpc::constants::MAXGLOBALPADROW;
196 clustererNN.mInputData_32[write_idx + 2] =
static_cast<float>(pad) / npads;
198 clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)(
static_cast<float>(sector) / o2::tpc::constants::MAXSECTOR);
199 clustererNN.mInputData_16[write_idx + 1] = (OrtDataType::Float16_t)(
static_cast<float>(
row) / o2::tpc::constants::MAXGLOBALPADROW);
200 clustererNN.mInputData_16[write_idx + 2] = (OrtDataType::Float16_t)(
static_cast<float>(pad) / npads);
205 if (transient_index < clustererNN.mNnClusterizerRowTimeSize) {
207 const int32_t row_idx = transient_index / clustererNN.mNnClusterizerFullTimeSize;
208 const int32_t time_idx = transient_index - row_idx * clustererNN.mNnClusterizerFullTimeSize;
209 int32_t write_idx = base_idx * clustererNN.mNnClusterizerElementSize + row_idx * clustererNN.mNnClusterizerPadTimeSize + time_idx;
212 const int32_t target_row =
row + row_idx - clustererNN.mNnClusterizerSizeInputRow;
213 float output_value = clustererNN.mNnClusterizerBoundaryFillValue;
215 if ((row < 63 && target_row > 62) || (target_row < 0) || (
row > 62 && target_row < 63) || (target_row >= o2::tpc::constants::MAXGLOBALPADROW)) {
216 for (uint32_t target_pad = 0; target_pad < clustererNN.mNnClusterizerFullPadSize; ++target_pad) {
218 clustererNN.mInputData_32[write_idx] = output_value;
220 clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)output_value;
222 write_idx += clustererNN.mNnClusterizerFullTimeSize;
227 const int32_t target_time =
time + time_idx - clustererNN.mNnClusterizerSizeInputTime;
228 const uint8_t is_time_boundary = (target_time < 0) || (target_time >= clustererNN.maxAllowedTimebin);
229 const float inverse_central_charge = 1.f / central_charge;
230 const int32_t p_local = pad + GPUTPCNNClusterizerKernels::padOffset(
row, target_row);
231 const int32_t npads = GPUTPCGeometry::NPads(target_row);
233 const int32_t start_pad = -clustererNN.mNnClusterizerSizeInputPad + p_local;
234 const int32_t end_pad = clustererNN.mNnClusterizerSizeInputPad + p_local;
236 for (int32_t target_pad = start_pad; target_pad <= end_pad; ++target_pad) {
237 if (target_pad >= npads || target_pad < 0 || is_time_boundary) {
238 output_value = clustererNN.mNnClusterizerBoundaryFillValue;
242 output_value = chargeMap[
pos].unpack() * inverse_central_charge;
245 clustererNN.mInputData_32[write_idx] = output_value;
247 clustererNN.mInputData_16[write_idx] = (OrtDataType::Float16_t)output_value;
249 write_idx += clustererNN.mNnClusterizerFullTimeSize;
280 auto& clusterer = processors.tpcClusterer[sector];
281 auto& clustererNN = processors.tpcNNClusterer[sector];
282 if (glo_idx + batchStart >= clusterer.mPmemory->counters.nClusters || glo_idx >= (uint32_t)clustererNN.mNnClusterizerBatchedMode) {
285 if (clustererNN.mNnClusterizerUseClassification) {
286 uint32_t elem_iterator = glo_idx * clustererNN.mNnClusterizerModelClassNumOutputNodes;
287 float current_max_prob = 0.f;
288 uint32_t class_label = 0;
289 for (uint32_t pIdx = elem_iterator; pIdx < elem_iterator + clustererNN.mNnClusterizerModelClassNumOutputNodes; pIdx++) {
290 if (pIdx == elem_iterator) {
292 current_max_prob = clustererNN.mModelProbabilities_32[pIdx];
294 current_max_prob =
static_cast<float>(clustererNN.mModelProbabilities_16[pIdx]);
298 current_max_prob = CAMath::Max(current_max_prob, clustererNN.mModelProbabilities_32[pIdx]);
300 current_max_prob = CAMath::Max(current_max_prob, clustererNN.mModelProbabilities_16[pIdx].ToFloat());
305 clustererNN.mOutputDataClass[glo_idx + batchStart] = class_label;
306 if (class_label > 1) {
307 clustererNN.mClusterFlags[2 * glo_idx] = 1;
308 clustererNN.mClusterFlags[2 * glo_idx + 1] = 1;
311 clustererNN.mOutputDataClass[glo_idx + batchStart] = 1;
319 auto& clusterer = processors.tpcClusterer[sector];
320 auto& clustererNN = processors.tpcNNClusterer[sector];
321 if (glo_idx >= (uint32_t)clustererNN.mNnClusterizerBatchedMode) {
325 uint32_t maxClusterNum = clusterer.mPmemory->counters.nClusters;
326 uint32_t full_glo_idx = glo_idx + batchStart;
327 int32_t model_output_index = glo_idx * clustererNN.mNnClusterizerModelReg1NumOutputNodes;
330 uint32_t peakIndex = CAMath::Min(full_glo_idx, maxClusterNum - 1);
331 CfChargePos peak = clusterer.mPfilteredPeakPositions[peakIndex];
332 float central_charge =
static_cast<float>(chargeMap[peak].unpack());
337 if (full_glo_idx >= maxClusterNum) {
341 GPUTPCCFClusterizer::buildCluster(
342 clusterer.Param().rec,
347 smem.innerAboveThreshold,
361 GPUTPCCFClusterizer::buildCluster(
362 clusterer.Param().rec,
367 smem.innerAboveThreshold,
371 if ((clusterer.mPmemory->frag).isOverlap(peak.time())) {
372 if (clusterer.mPclusterPosInRow) {
373 clusterer.mPclusterPosInRow[full_glo_idx] = clusterer.mNMaxClusterPerRow;
378 bool notSinglePad =
false, notSingleTime =
false;
379 for (uint16_t
i = 0;
i < 8;
i++) {
380 Delta2 d = cfconsts::InnerNeighbors[
i];
382 float v =
static_cast<float>(chargeMap[tmp_pos].unpack());
383 notSinglePad |= (d.
x != 0) && (
v > 0.f);
384 notSingleTime |= (d.
y != 0) && (
v > 0.f);
387 float publishPadPosition = 0.f, publishTimePosition = 0.f;
389 publishPadPosition =
static_cast<float>(peak.pad()) + clustererNN.mOutputDataReg1_32[model_output_index];
390 publishTimePosition =
static_cast<float>(peak.time()) + clustererNN.mOutputDataReg1_32[model_output_index + 1];
391 isBoundaryPublish(full_glo_idx,
static_cast<int32_t
>(peak.row()), publishPadPosition, publishTimePosition);
392 pc.setFull(central_charge * clustererNN.mOutputDataReg1_32[model_output_index + 4],
394 notSinglePad ? clustererNN.mOutputDataReg1_32[model_output_index + 2] : 0.f,
395 (clusterer.mPmemory->frag).
start + publishTimePosition,
396 notSingleTime ? clustererNN.mOutputDataReg1_32[model_output_index + 3] : 0.f,
397 clustererNN.mClusterFlags[2 * glo_idx],
398 clustererNN.mClusterFlags[2 * glo_idx + 1]);
400 publishPadPosition =
static_cast<float>(peak.pad()) + clustererNN.mOutputDataReg1_16[model_output_index].ToFloat();
401 publishTimePosition =
static_cast<float>(peak.time()) + clustererNN.mOutputDataReg1_16[model_output_index + 1].ToFloat();
402 isBoundaryPublish(full_glo_idx,
static_cast<int32_t
>(peak.row()), publishPadPosition, publishTimePosition);
403 pc.setFull(central_charge * clustererNN.mOutputDataReg1_16[model_output_index + 4].ToFloat(),
405 notSinglePad ? clustererNN.mOutputDataReg1_16[model_output_index + 2].ToFloat() : 0.f,
406 (clusterer.mPmemory->frag).
start + publishTimePosition,
407 notSingleTime ? clustererNN.mOutputDataReg1_16[model_output_index + 3].ToFloat() : 0.f,
408 clustererNN.mClusterFlags[2 * glo_idx],
409 clustererNN.mClusterFlags[2 * glo_idx + 1]);
482 bool rejectCluster = !pc.toNative(peak, central_charge, myCluster, clusterer.Param(), chargeMap);
483 if (clustererNN.mNnClusterizerUseClassification) {
484 rejectCluster |= (clustererNN.mOutputDataClass[peakIndex] <= 0);
487 if (clusterer.mPclusterPosInRow) {
488 clusterer.mPclusterPosInRow[full_glo_idx] = clusterer.mNMaxClusterPerRow;
493 uint32_t rowIndex = 0;
494 if (clusterOut !=
nullptr) {
495 rowIndex = GPUTPCCFClusterizer::sortIntoBuckets(
499 clusterer.mNMaxClusterPerRow,
500 clusterer.mPclusterInRow,
502 if (clusterer.mPclusterPosInRow !=
nullptr) {
503 clusterer.mPclusterPosInRow[full_glo_idx] = rowIndex;
505 }
else if (clusterer.mPclusterPosInRow) {
506 rowIndex = clusterer.mPclusterPosInRow[full_glo_idx];
508 CPU_ONLY(labelAcc->
commit(peak.row(), rowIndex, clusterer.mNMaxClusterPerRow));
515 auto& clusterer = processors.tpcClusterer[sector];
516 auto& clustererNN = processors.tpcNNClusterer[sector];
517 if (glo_idx >= (uint32_t)clustererNN.mNnClusterizerBatchedMode) {
521 uint32_t maxClusterNum = clusterer.mPmemory->counters.nClusters;
523 CfChargePos peak = clusterer.mPfilteredPeakPositions[CAMath::Min(glo_idx + batchStart, (uint32_t)(clusterer.mPmemory->counters.nClusters - 1))];
524 float central_charge =
static_cast<float>(chargeMap[peak].unpack());
529 uint32_t full_glo_idx = glo_idx + batchStart;
531 if (full_glo_idx >= maxClusterNum) {
535 GPUTPCCFClusterizer::buildCluster(
536 clusterer.Param().rec,
541 smem.innerAboveThreshold,
548 uint32_t model_output_index = glo_idx * clustererNN.mNnClusterizerModelReg2NumOutputNodes;
555 GPUTPCCFClusterizer::buildCluster(
556 clusterer.Param().rec,
561 smem.innerAboveThreshold,
565 if ((clusterer.mPmemory->frag).isOverlap(peak.time())) {
566 if (clusterer.mPclusterPosInRow) {
567 clusterer.mPclusterPosInRow[full_glo_idx] = clusterer.mNMaxClusterPerRow;
573 float publishPadPosition = 0.f, publishTimePosition = 0.f;
575 publishPadPosition =
static_cast<float>(peak.pad()) + clustererNN.mOutputDataReg2_32[model_output_index];
576 publishTimePosition =
static_cast<float>(peak.time()) + clustererNN.mOutputDataReg2_32[model_output_index + 1];
577 isBoundaryPublish(full_glo_idx,
static_cast<int32_t
>(peak.row()), publishPadPosition, publishTimePosition);
578 pc.setFull(central_charge * clustererNN.mOutputDataReg2_32[model_output_index + 8],
580 clustererNN.mOutputDataReg2_32[model_output_index + 4],
581 (clusterer.mPmemory->frag).start + publishTimePosition,
582 clustererNN.mOutputDataReg2_32[model_output_index + 6],
583 clustererNN.mClusterFlags[2 * glo_idx],
584 clustererNN.mClusterFlags[2 * glo_idx + 1]);
586 publishPadPosition =
static_cast<float>(peak.pad()) + clustererNN.mOutputDataReg2_16[model_output_index].ToFloat();
587 publishTimePosition =
static_cast<float>(peak.time()) + clustererNN.mOutputDataReg2_16[model_output_index + 1].ToFloat();
588 isBoundaryPublish(full_glo_idx,
static_cast<int32_t
>(peak.row()), publishPadPosition, publishTimePosition);
589 pc.setFull(central_charge * clustererNN.mOutputDataReg2_16[model_output_index + 8].ToFloat(),
591 clustererNN.mOutputDataReg2_16[model_output_index + 4].ToFloat(),
592 (clusterer.mPmemory->frag).start + publishTimePosition,
593 clustererNN.mOutputDataReg2_16[model_output_index + 6].ToFloat(),
594 clustererNN.mClusterFlags[2 * glo_idx],
595 clustererNN.mClusterFlags[2 * glo_idx + 1]);
599 bool rejectCluster = !pc.toNative(peak, central_charge, myCluster, clusterer.Param(), chargeMap);
600 if (clustererNN.mNnClusterizerUseClassification) {
601 rejectCluster |= (clustererNN.mOutputDataClass[CAMath::Min(full_glo_idx, (uint32_t)clusterer.mPmemory->counters.nClusters - 1)] <= 0);
604 if (clusterer.mPclusterPosInRow) {
605 clusterer.mPclusterPosInRow[full_glo_idx] = clusterer.mNMaxClusterPerRow;
610 uint32_t rowIndex = 0;
611 if (clusterOut !=
nullptr) {
612 rowIndex = GPUTPCCFClusterizer::sortIntoBuckets(
616 clusterer.mNMaxClusterPerRow,
617 clusterer.mPclusterInRow,
619 if (clusterer.mPclusterPosInRow !=
nullptr) {
620 clusterer.mPclusterPosInRow[full_glo_idx] = rowIndex;
622 }
else if (clusterer.mPclusterPosInRow) {
623 rowIndex = clusterer.mPclusterPosInRow[full_glo_idx];
625 CPU_ONLY(labelAcc->
commit(peak.row(), rowIndex, clusterer.mNMaxClusterPerRow));
629 publishPadPosition =
static_cast<float>(peak.pad()) + clustererNN.mOutputDataReg2_32[model_output_index + 1];
630 publishTimePosition =
static_cast<float>(peak.time()) + clustererNN.mOutputDataReg2_32[model_output_index + 3];
631 isBoundaryPublish(full_glo_idx,
static_cast<int32_t
>(peak.row()), publishPadPosition, publishTimePosition);
632 pc.setFull(central_charge * clustererNN.mOutputDataReg2_32[model_output_index + 9],
634 clustererNN.mOutputDataReg2_32[model_output_index + 5],
635 (clusterer.mPmemory->frag).start + publishTimePosition,
636 clustererNN.mOutputDataReg2_32[model_output_index + 7],
637 clustererNN.mClusterFlags[2 * glo_idx],
638 clustererNN.mClusterFlags[2 * glo_idx + 1]);
640 publishPadPosition =
static_cast<float>(peak.pad()) + clustererNN.mOutputDataReg2_16[model_output_index + 1].ToFloat();
641 publishTimePosition =
static_cast<float>(peak.time()) + clustererNN.mOutputDataReg2_16[model_output_index + 3].ToFloat();
642 isBoundaryPublish(full_glo_idx,
static_cast<int32_t
>(peak.row()), publishPadPosition, publishTimePosition);
643 pc.setFull(central_charge * clustererNN.mOutputDataReg2_16[model_output_index + 9].ToFloat(),
645 clustererNN.mOutputDataReg2_16[model_output_index + 5].ToFloat(),
646 (clusterer.mPmemory->frag).start + publishTimePosition,
647 clustererNN.mOutputDataReg2_16[model_output_index + 7].ToFloat(),
648 clustererNN.mClusterFlags[2 * glo_idx],
649 clustererNN.mClusterFlags[2 * glo_idx + 1]);
652 rejectCluster = !pc.toNative(peak, central_charge, myCluster, clusterer.Param(), chargeMap);
653 if (clustererNN.mNnClusterizerUseClassification) {
654 rejectCluster |= (clustererNN.mOutputDataClass[CAMath::Min(full_glo_idx, (uint32_t)clusterer.mPmemory->counters.nClusters - 1)] <= 0);
657 if (clusterer.mPclusterPosInRow) {
658 clusterer.mPclusterPosInRow[full_glo_idx] = clusterer.mNMaxClusterPerRow;
663 if (clusterOut !=
nullptr) {
664 rowIndex = GPUTPCCFClusterizer::sortIntoBuckets(
668 clusterer.mNMaxClusterPerRow,
669 clusterer.mPclusterInRow,
671 if (clusterer.mPclusterPosInRow !=
nullptr) {
672 clusterer.mPclusterPosInRow[full_glo_idx] = rowIndex;
674 }
else if (clusterer.mPclusterPosInRow) {
675 rowIndex = clusterer.mPclusterPosInRow[full_glo_idx];