31typedef std::vector<bool> HuffCode;
32typedef std::map<uint32_t, HuffCode> HuffCodeMap;
39 virtual ~INode() =
default;
42 INode(
double v) :
f(
v) {}
45class InternalNode :
public INode
51 InternalNode(INode* c0, INode* c1) : INode(c0->
f + c1->
f),
left(c0),
right(c1) {}
52 ~InternalNode()
override
59class LeafNode :
public INode
64 LeafNode(
double v, uint32_t
w) : INode(
v), c(
w) {}
68 bool operator()(
const INode* lhs,
const INode* rhs)
const {
return lhs->f >
rhs->f; }
71INode* BuildTree(
const double* frequencies, uint32_t UniqueSymbols)
73 std::priority_queue<INode*, std::vector<INode*>, NodeCmp> trees;
75 for (uint32_t
i = 0;
i < UniqueSymbols;
i++) {
76 if (frequencies[
i] != 0) {
77 trees.push(
new LeafNode(frequencies[
i],
i));
80 while (trees.size() > 1) {
81 INode* childR = trees.top();
84 INode* childL = trees.top();
87 INode* parent =
new InternalNode(childR, childL);
93void GenerateCodes(
const INode*
node,
const HuffCode& prefix, HuffCodeMap& outCodes)
95 if (
const LeafNode* lf =
dynamic_cast<const LeafNode*
>(
node)) {
96 outCodes[lf->c] = prefix;
97 }
else if (
const InternalNode* in =
dynamic_cast<const InternalNode*
>(
node)) {
98 HuffCode leftPrefix = prefix;
99 leftPrefix.push_back(
false);
100 GenerateCodes(in->left, leftPrefix, outCodes);
102 HuffCode rightPrefix = prefix;
103 rightPrefix.push_back(
true);
104 GenerateCodes(in->right, rightPrefix, outCodes);
112 uint32_t decodingErrors = 0;
114 std::vector<o2::tpc::ClusterNative> clusterBuffer;
116 auto allocator = [&clusterBuffer](
size_t size) {clusterBuffer.resize(
size);
return clusterBuffer.data(); };
118 std::vector<o2::tpc::ClusterNative> tmpClusters;
123 GPUError(
"Number of clusters mismatch sector %u row %u: expected %d v.s. decoded %d",
i,
j, clustersNative->
nClusters[
i][
j], clustersNativeDecoded.
nClusters[
i][
j]);
127 tmpClusters.resize(clustersNative->
nClusters[
i][
j]);
128 for (uint32_t k = 0; k < clustersNative->
nClusters[
i][
j]; k++) {
129 tmpClusters[k] = clustersNative->
clusters[
i][
j][k];
131 GPUTPCCompression::truncateSignificantBitsChargeMax(tmpClusters[k].qMax,
param);
132 GPUTPCCompression::truncateSignificantBitsWidth(tmpClusters[k].sigmaPadPacked,
param);
133 if (!tmpClusters[k].isSaturated()) [[likely]] {
134 GPUTPCCompression::truncateSignificantBitsCharge(tmpClusters[k].qTot,
param);
135 GPUTPCCompression::truncateSignificantBitsWidth(tmpClusters[k].sigmaTimePacked,
param);
139 std::sort(tmpClusters.begin(), tmpClusters.end());
140 for (uint32_t k = 0; k < clustersNative->
nClusters[
i][
j]; k++) {
144 if (decodingErrors++ < 100) {
145 GPUWarning(
"Cluster mismatch: sector %2u row %3u hit %5u: %6d %3d %4d %3d %3d %4d %4d",
i,
j, k, (int32_t)c1.getTimePacked(), (int32_t)c1.getFlags(), (int32_t)c1.
padPacked, (int32_t)c1.
sigmaTimePacked, (int32_t)c1.
sigmaPadPacked, (int32_t)c1.
qMax, (int32_t)c1.
qTot);
152 if (decodingErrors) {
154 GPUWarning(
"Errors during cluster decoding %u\n", decodingErrors);
156 GPUInfo(
"Cluster decoding verification: PASSED");
191 std::ofstream csv(
"clusters_raw.csv");
192 csv <<
"sector,row,time,pad,flags,qtot,qmax,sigmatime,sigmapad\n";
195 for (uint32_t k = 0; k < clustersNativeDecoded.
nClusters[
i][
j]; k++) {
196 const auto& cl = clustersNativeDecoded.
clusters[
i][
j][k];
197 csv <<
i <<
',' <<
j <<
',' << cl.getTimePacked() <<
',' << cl.
padPacked <<
',' << (uint32_t)cl.getFlags() <<
',' << cl.qTot <<
',' << cl.qMax <<
',' << (uint32_t)cl.sigmaTimePacked <<
',' << (uint32_t)cl.sigmaPadPacked <<
'\n';
202 csv = std::ofstream(
"attachedCl.csv");
203 csv <<
"qTotA,qMaxA,flagsA,sigmaPadA,sigmaTimeA\n";
205 csv << clustersCompressed->
qTotA[
i] <<
',' << clustersCompressed->
qMaxA[
i] <<
',' << (uint32_t)clustersCompressed->
flagsA[
i] <<
',' << (uint32_t)clustersCompressed->
sigmaPadA[
i] <<
',' << (uint32_t)clustersCompressed->
sigmaTimeA[
i] <<
"\n";
208 csv = std::ofstream(
"attachedClred.csv");
209 csv <<
"rodDiffA,legDiffA,padResA,timeResA\n";
211 csv << (uint32_t)clustersCompressed->
rowDiffA[
i] <<
',' << (uint32_t)clustersCompressed->
sliceLegDiffA[
i] <<
',' << clustersCompressed->
padResA[
i] <<
',' << clustersCompressed->
timeResA[
i] <<
"\n";
214 csv = std::ofstream(
"nClU.csv");
215 csv <<
"sliceRowCl\n";
216 for (uint32_t
i = 0;
i < clustersCompressed->
nSliceRows;
i++) {
220 csv = std::ofstream(
"trk.csv");
221 csv <<
"qPtA,rowA,sliceA,timeA,padA,nCl\n";
222 for (uint32_t
i = 0;
i < clustersCompressed->
nTracks;
i++) {
223 csv << (uint32_t)clustersCompressed->
qPtA[
i] <<
',' << (uint32_t)clustersCompressed->
rowA[
i] <<
',' << (uint32_t)clustersCompressed->
sliceA[
i] <<
',' << clustersCompressed->
timeA[
i] <<
',' << clustersCompressed->
padA[
i] <<
',' << clustersCompressed->
nTrackClusters[
i] <<
"\n";
226 csv = std::ofstream(
"unattachedCl.csv");
227 csv <<
"qTotU,qMaxU,flagsU,padDiffU,timeDiffU,sigmaPadU,sigmaTimeU\n";
229 csv << clustersCompressed->
qTotU[
i] <<
',' << clustersCompressed->
qMaxU[
i] <<
',' << (uint32_t)clustersCompressed->
flagsU[
i] <<
',' << clustersCompressed->
padDiffU[
i] <<
',' << clustersCompressed->
timeDiffU[
i] <<
',' << (uint32_t)clustersCompressed->
sigmaPadU[
i] <<
',' << (uint32_t)clustersCompressed->
sigmaTimeU[
i] <<
"\n";
237 GPUError(
"-----------------------------------------\nERROR - INCORRECT CLUSTER DECODING!\n-----------------------------------------");
243 GPUInfo(
"\nRunning cluster compression entropy statistics");
269 double eQCombined =
Analyze(
mPQA,
"combined Q Attached");
270 eQCombined +=
Analyze(
mPQU,
"combined Q Unattached");
273 GPUInfo(
"Combined Row/Sector: %6.4f --> %6.4f (%6.4f%%)", eRowSector, eRowSectorCombined, eRowSector > 1e-1 ? (100. * (eRowSector - eRowSectorCombined) / eRowSector) : 0.f);
274 GPUInfo(
"Combined Sigma: %6.4f --> %6.4f (%6.4f%%)", eSigma, eSigmaCombined, eSigma > 1e-3 ? (100. * (eSigma - eSigmaCombined) / eSigma) : 0.f);
275 GPUInfo(
"Combined Q: %6.4f --> %6.4f (%6.4f%%)", eQ, eQCombined, eQ > 1e-3 ? (100. * (eQ - eQCombined) / eQ) : 0.f);
283 double huffmanSize = 0;
285 std::vector<double> prob(p.size());
286 double log2 = log(2.);
288 for (uint32_t
i = 0;
i < p.size();
i++) {
292 for (uint32_t
i = 0;
i < prob.size();
i++) {
294 prob[
i] = (double)p[
i] / total;
295 double I = -log(prob[
i]) / log2;
296 double H = I * prob[
i];
302 INode* root = BuildTree(prob.data(), prob.size());
305 GenerateCodes(root, HuffCode(), codes);
308 for (HuffCodeMap::const_iterator it = codes.begin(); it != codes.end(); it++) {
309 huffmanSize += it->second.size() * prob[it->first];
317 GPUInfo(
"Size: %30s: Entropy %7.4f Huffman %7.4f (Count) %9ld",
name, entropy, huffmanSize, (int64_t)total);
321template <
class T,
int32_t I>
324 for (
size_t i = 0;
i <
n;
i++) {
326 if (
val >= p.size()) {
330 GPUError(
"Invalid Value: %d >= %d",
val, (int32_t)p.size());
338template <
class T,
class S,
int32_t I>
341 for (
size_t i = 0;
i <
n;
i++) {
342 uint32_t
val = ptr1[
i] + ptr2[
i] * max1;
343 if (
val >= p.size()) {
347 GPUError(
"Invalid Value: %d >= %d",
val, (int32_t)p.size());
std::unique_ptr< expressions::Node > node
std::vector< int32_t > mPQA
std::vector< int32_t > mPsigmaTimeA
std::vector< int32_t > mPpadResA
static constexpr uint32_t NSECTORS
static constexpr uint32_t P_MAX_QMAX
std::vector< int32_t > mPsigmaTimeU
float Analyze(std::vector< int32_t > &p, const char *name, bool count=true)
std::vector< int32_t > mPsigmaU
std::vector< int32_t > mPflagsU
std::vector< int32_t > mPqMaxU
void RunStatistics(const o2::tpc::ClusterNativeAccess *clustersNative, const o2::tpc::CompressedClusters *clustersCompressed, const GPUParam ¶m, bool dumpCSV)
void FillStatisticCombined(std::vector< int32_t > &p, const T *ptr1, const S *ptr2, size_t n, int32_t max1)
std::vector< int32_t > mPtimeResA
TPCClusterDecompressor mDecoder
std::vector< int32_t > mPtimeDiffU
std::vector< int32_t > mPqPtA
std::vector< int32_t > mPnSectorRowClusters
std::vector< int32_t > mPqTotA
std::vector< int32_t > mPnTrackClusters
std::vector< int32_t > mPtimeA
std::vector< int32_t > mProwA
std::vector< int32_t > mProwDiffA
std::vector< int32_t > mPsigmaPadU
std::vector< int32_t > mPqMaxA
void FillStatistic(std::vector< int32_t > &p, const T *ptr, size_t n)
static constexpr uint32_t P_MAX_SIGMA
std::vector< int32_t > mPflagsA
std::vector< int32_t > mPsigmaA
std::vector< int32_t > mPsectorLegDiffA
std::vector< int32_t > mProwSectorA
std::vector< int32_t > mPqTotU
std::vector< int32_t > mPQU
std::vector< int32_t > mPpadDiffU
std::vector< int32_t > mPsigmaPadA
std::vector< int32_t > mPpadA
std::vector< int32_t > mPsectorA
static constexpr uint32_t NROWS
static int32_t decompress(const o2::tpc::CompressedClustersFlat *clustersCompressed, o2::tpc::ClusterNativeAccess &clustersNative, std::function< o2::tpc::ClusterNative *(size_t)> allocator, const GPUParam ¶m, bool deterministicRec)
GLuint const GLchar * name
GLubyte GLubyte GLubyte GLubyte w
D const SVectorGPU< T, D > & rhs
unsigned int nClusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
const ClusterNative * clusters[constants::MAXSECTOR][constants::MAXGLOBALPADROW]
unsigned int nUnattachedClusters
unsigned int nAttachedClusters
unsigned int nAttachedClustersReduced