Project
Loading...
Searching...
No Matches
GPUTPCCFCheckPadBaseline.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
16#include "CfArray2D.h"
17#include "PackedCharge.h"
18#include "GPUTPCGeometry.h"
19#include "clusterFinderDefs.h"
20
21#ifndef GPUCA_GPUCODE
22#include "utils/VcShim.h"
23#endif
24
25using namespace o2::gpu;
26using namespace o2::gpu::tpccf;
27
28template <>
29GPUd() void GPUTPCCFCheckPadBaseline::Thread<0>(int32_t nBlocks, int32_t nThreads, int32_t iBlock, int32_t iThread, GPUSharedMemory& smem, processorType& clusterer)
30{
31 const CfFragment& fragment = clusterer.mPmemory->fragment;
32 CfArray2D<PackedCharge> chargeMap(reinterpret_cast<PackedCharge*>(clusterer.mPchargeMap));
33
34 int32_t basePad = iBlock * PadsPerCacheline;
35 CfChargePos basePos = padToCfChargePos(basePad, clusterer);
36
37 if (not basePos.valid()) {
38 return;
39 }
40
41#ifdef GPUCA_GPUCODE
42 static_assert(TPC_MAX_FRAGMENT_LEN_GPU % NumOfCachedTimebins == 0);
43
44 int32_t totalCharges = 0;
45 int32_t consecCharges = 0;
46 int32_t maxConsecCharges = 0;
47 Charge maxCharge = 0;
48
49 int16_t localPadId = iThread / NumOfCachedTimebins;
50 int16_t localTimeBin = iThread % NumOfCachedTimebins;
51 bool handlePad = localTimeBin == 0;
52
53 for (tpccf::TPCFragmentTime t = fragment.firstNonOverlapTimeBin(); t < fragment.lastNonOverlapTimeBin(); t += NumOfCachedTimebins) {
54 const CfChargePos pos = basePos.delta({localPadId, int16_t(t + localTimeBin)});
55 smem.charges[localPadId][localTimeBin] = (pos.valid()) ? chargeMap[pos].unpack() : 0;
56 GPUbarrier();
57 if (handlePad) {
58 for (int32_t i = 0; i < NumOfCachedTimebins; i++) {
59 const Charge q = smem.charges[localPadId][i];
60 totalCharges += (q > 0);
61 consecCharges = (q > 0) ? consecCharges + 1 : 0;
62 maxConsecCharges = CAMath::Max(consecCharges, maxConsecCharges);
63 maxCharge = CAMath::Max<Charge>(q, maxCharge);
64 }
65 }
66 GPUbarrier();
67 }
68
69 GPUbarrier();
70
71 if (handlePad) {
72 updatePadBaseline(basePad + localPadId, clusterer, totalCharges, maxConsecCharges, maxCharge);
73 }
74
75#else // CPU CODE
76
77 constexpr size_t ElemsInTileRow = (size_t)TilingLayout<GridSize<2>>::WidthInTiles * TimebinsPerCacheline * PadsPerCacheline;
78
79 using UShort8 = Vc::fixed_size_simd<uint16_t, PadsPerCacheline>;
80 using Charge8 = Vc::fixed_size_simd<float, PadsPerCacheline>;
81
82 UShort8 totalCharges{Vc::Zero};
83 UShort8 consecCharges{Vc::Zero};
84 UShort8 maxConsecCharges{Vc::Zero};
85 Charge8 maxCharge{Vc::Zero};
86
87 tpccf::TPCFragmentTime t = fragment.firstNonOverlapTimeBin();
88
89 // Access packed charges as raw integers. We throw away the PackedCharge type here to simplify vectorization.
90 const uint16_t* packedChargeStart = reinterpret_cast<uint16_t*>(&chargeMap[basePos.delta({0, t})]);
91
92 for (; t < fragment.lastNonOverlapTimeBin(); t += TimebinsPerCacheline) {
93 for (tpccf::TPCFragmentTime localtime = 0; localtime < TimebinsPerCacheline; localtime++) {
94 const UShort8 packedCharges{packedChargeStart + PadsPerCacheline * localtime, Vc::Aligned};
95 const UShort8::mask_type isCharge = packedCharges != 0;
96
97 if (isCharge.isNotEmpty()) {
98 totalCharges(isCharge)++;
99 consecCharges += 1;
100 consecCharges(not isCharge) = 0;
101 maxConsecCharges = Vc::max(consecCharges, maxConsecCharges);
102
103 // Manually unpack charges to float.
104 // Duplicated from PackedCharge::unpack to generate vectorized code:
105 // Charge unpack() const { return Charge(mVal & ChargeMask) / Charge(1 << DecimalBits); }
106 // Note that PackedCharge has to cut off the highest 2 bits via ChargeMask as they are used for flags by the cluster finder
107 // and are not part of the charge value. We can skip this step because the cluster finder hasn't run yet
108 // and thus these bits are guarenteed to be zero.
109 const Charge8 unpackedCharges = Charge8(packedCharges) / Charge(1 << PackedCharge::DecimalBits);
110 maxCharge = Vc::max(maxCharge, unpackedCharges);
111 } else {
112 consecCharges = 0;
113 }
114 }
115
116 packedChargeStart += ElemsInTileRow;
117 }
118
119 for (tpccf::Pad localpad = 0; localpad < PadsPerCacheline; localpad++) {
120 updatePadBaseline(basePad + localpad, clusterer, totalCharges[localpad], maxConsecCharges[localpad], maxCharge[localpad]);
121 }
122#endif
123}
124
125GPUd() CfChargePos GPUTPCCFCheckPadBaseline::padToCfChargePos(int32_t& pad, const GPUTPCClusterFinder& clusterer)
126{
127 constexpr GPUTPCGeometry geo;
128
129 int32_t padOffset = 0;
130 for (Row r = 0; r < GPUCA_ROW_COUNT; r++) {
131 int32_t npads = geo.NPads(r);
132 int32_t padInRow = pad - padOffset;
133 if (0 <= padInRow && padInRow < CAMath::nextMultipleOf<PadsPerCacheline, int32_t>(npads)) {
134 int32_t cachelineOffset = padInRow % PadsPerCacheline;
135 pad -= cachelineOffset;
136 return CfChargePos{r, Pad(padInRow - cachelineOffset), 0};
137 }
138 padOffset += npads;
139 }
140
141 return CfChargePos{0, 0, INVALID_TIME_BIN};
142}
143
144GPUd() void GPUTPCCFCheckPadBaseline::updatePadBaseline(int32_t pad, const GPUTPCClusterFinder& clusterer, int32_t totalCharges, int32_t consecCharges, Charge maxCharge)
145{
146 const CfFragment& fragment = clusterer.mPmemory->fragment;
147 const int32_t totalChargesBaseline = clusterer.Param().rec.tpc.maxTimeBinAboveThresholdIn1000Bin * fragment.lengthWithoutOverlap() / 1000;
148 const int32_t consecChargesBaseline = clusterer.Param().rec.tpc.maxConsecTimeBinAboveThreshold;
149 const uint16_t saturationThreshold = clusterer.Param().rec.tpc.noisyPadSaturationThreshold;
150 const bool isNoisy = (!saturationThreshold || maxCharge < saturationThreshold) && ((totalChargesBaseline > 0 && totalCharges >= totalChargesBaseline) || (consecChargesBaseline > 0 && consecCharges >= consecChargesBaseline));
151
152 if (isNoisy) {
153 clusterer.mPpadIsNoisy[pad] = true;
154 }
155}
#define INVALID_TIME_BIN
Definition CfChargePos.h:23
int32_t i
#define GPUbarrier()
GPUd() void GPUTPCCFCheckPadBaseline
#define GPUCA_ROW_COUNT
uint16_t pos
Definition RawData.h:3
Provides a basic fallback implementation for Vc.
#define TPC_MAX_FRAGMENT_LEN_GPU
typedef void(APIENTRYP PFNGLCULLFACEPROC)(GLenum mode)
GLboolean r
Definition glcorearb.h:1233