Skip to content

Commit fc73bd9

Browse files
committed
Flat LUT structure
1 parent 441800c commit fc73bd9

File tree

2 files changed

+332
-0
lines changed

2 files changed

+332
-0
lines changed

ALICE3/Core/FlatLutEntry.cxx

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
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+
12+
#include "FlatLutEntry.h"
13+
14+
#include <Framework/Logger.h>
15+
16+
#include <cstring>
17+
18+
namespace o2::delphes
19+
{
20+
21+
float map_t::fracPositionWithinBin(float val) const
22+
{
23+
float width = (max - min) / nbins;
24+
int bin;
25+
float returnVal = 0.5f;
26+
if (log) {
27+
bin = static_cast<int>((std::log10(val) - min) / width);
28+
returnVal = ((std::log10(val) - min) / width) - bin;
29+
} else {
30+
bin = static_cast<int>((val - min) / width);
31+
returnVal = val / width - bin;
32+
}
33+
return returnVal;
34+
}
35+
36+
int map_t::find(float val) const
37+
{
38+
float width = (max - min) / nbins;
39+
int bin;
40+
if (log) {
41+
bin = static_cast<int>((std::log10(val) - min) / width);
42+
} else {
43+
bin = static_cast<int>((val - min) / width);
44+
}
45+
if (bin < 0) {
46+
return 0;
47+
}
48+
if (bin > nbins - 1) {
49+
return nbins - 1;
50+
}
51+
return bin;
52+
}
53+
54+
void map_t::print() const
55+
{
56+
LOGF(info, "nbins = %d, min = %f, max = %f, log = %s \n", nbins, min, max, log ? "on" : "off");
57+
}
58+
59+
bool lutHeader_t::check_version() const
60+
{
61+
return (version == LUTCOVM_VERSION);
62+
}
63+
64+
void lutHeader_t::print() const
65+
{
66+
LOGF(info, " version: %d \n", version);
67+
LOGF(info, " pdg: %d \n", pdg);
68+
LOGF(info, " field: %f \n", field);
69+
LOGF(info, " nchmap: ");
70+
nchmap.print();
71+
LOGF(info, " radmap: ");
72+
radmap.print();
73+
LOGF(info, " etamap: ");
74+
etamap.print();
75+
LOGF(info, " ptmap: ");
76+
ptmap.print();
77+
}
78+
79+
void FlatLutData::initialize(const lutHeader_t& header)
80+
{
81+
mNchBins = header.nchmap.nbins;
82+
mRadBins = header.radmap.nbins;
83+
mEtaBins = header.etamap.nbins;
84+
mPtBins = header.ptmap.nbins;
85+
86+
size_t headerSize = sizeof(lutHeader_t);
87+
size_t numEntries = static_cast<size_t>(mNchBins) * mRadBins * mEtaBins * mPtBins;
88+
size_t entriesSize = numEntries * sizeof(lutEntry_t);
89+
size_t totalSize = headerSize + entriesSize;
90+
91+
mData.resize(totalSize);
92+
93+
// Write header at the beginning
94+
std::memcpy(mData.data(), &header, headerSize);
95+
}
96+
97+
size_t FlatLutData::getEntryOffset(int nch_bin, int rad_bin, int eta_bin, int pt_bin) const
98+
{
99+
size_t headerSize = sizeof(lutHeader_t);
100+
101+
// Linear index: nch varies slowest, pt varies fastest
102+
// idx = nch * (rad*eta*pt) + rad * (eta*pt) + eta * pt + pt
103+
size_t linearIdx = static_cast<size_t>(nch_bin) * (mRadBins * mEtaBins * mPtBins) + static_cast<size_t>(rad_bin) * (mEtaBins * mPtBins) + static_cast<size_t>(eta_bin) * mPtBins + static_cast<size_t>(pt_bin);
104+
105+
return headerSize + linearIdx * sizeof(lutEntry_t);
106+
}
107+
108+
lutEntry_t* FlatLutData::getEntry(int nch_bin, int rad_bin, int eta_bin, int pt_bin)
109+
{
110+
size_t offset = getEntryOffset(nch_bin, rad_bin, eta_bin, pt_bin);
111+
return reinterpret_cast<lutEntry_t*>(mData.data() + offset);
112+
}
113+
114+
const lutEntry_t* FlatLutData::getEntry(int nch_bin, int rad_bin, int eta_bin, int pt_bin) const
115+
{
116+
size_t offset = getEntryOffset(nch_bin, rad_bin, eta_bin, pt_bin);
117+
return reinterpret_cast<const lutEntry_t*>(mData.data() + offset);
118+
}
119+
120+
FlatLutData FlatLutData::fromBuffer(const uint8_t* buffer, size_t size)
121+
{
122+
FlatLutData data;
123+
// Validate buffer
124+
if (size < sizeof(lutHeader_t)) {
125+
LOG(fatal) << "Buffer too small for LUT header";
126+
}
127+
128+
const auto* header = reinterpret_cast<const lutHeader_t*>(buffer);
129+
data.mNchBins = header->nchmap.nbins;
130+
data.mRadBins = header->radmap.nbins;
131+
data.mEtaBins = header->etamap.nbins;
132+
data.mPtBins = header->ptmap.nbins;
133+
134+
size_t expectedSize = sizeof(lutHeader_t) + static_cast<size_t>(data.mNchBins) * data.mRadBins * data.mEtaBins * data.mPtBins * sizeof(lutEntry_t);
135+
136+
if (size < expectedSize) {
137+
LOG(fatal) << "Buffer size mismatch: expected " << expectedSize << ", got " << size;
138+
}
139+
140+
// Copy buffer
141+
data.mData.resize(size);
142+
std::memcpy(data.mData.data(), buffer, size);
143+
144+
return data;
145+
}
146+
147+
FlatLutData FlatLutData::fromExternalBuffer(uint8_t* buffer, size_t size)
148+
{
149+
FlatLutData data;
150+
// Validate buffer
151+
if (size < sizeof(lutHeader_t)) {
152+
LOG(fatal) << "Buffer too small for LUT header";
153+
}
154+
155+
const auto* header = reinterpret_cast<const lutHeader_t*>(buffer);
156+
data.mNchBins = header->nchmap.nbins;
157+
data.mRadBins = header->radmap.nbins;
158+
data.mEtaBins = header->etamap.nbins;
159+
data.mPtBins = header->ptmap.nbins;
160+
161+
size_t expectedSize = sizeof(lutHeader_t) + static_cast<size_t>(data.mNchBins) * data.mRadBins * data.mEtaBins * data.mPtBins * sizeof(lutEntry_t);
162+
163+
if (size < expectedSize) {
164+
LOG(fatal) << "Buffer size mismatch: expected " << expectedSize << " got " << size;
165+
}
166+
167+
// Store reference to external buffer (no copy)
168+
// WARNING: Caller must ensure buffer lifetime exceeds FlatLutData usage
169+
data.mData.assign(buffer, buffer + size);
170+
171+
return data;
172+
}
173+
174+
} // namespace o2::delphes

ALICE3/Core/FlatLutEntry.h

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
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+
12+
#ifndef ALICE3_CORE_FLATLUTENTRY_H_
13+
#define ALICE3_CORE_FLATLUTENTRY_H_
14+
15+
#include <cmath>
16+
#include <cstdint>
17+
#include <vector>
18+
19+
#define LUTCOVM_VERSION 20260408
20+
21+
namespace o2::delphes
22+
{
23+
24+
/**
25+
* @brief Flat LUT entry structure
26+
*/
27+
struct lutEntry_t {
28+
float nch = 0.f;
29+
float eta = 0.f;
30+
float pt = 0.f;
31+
bool valid = false;
32+
float eff = 0.f;
33+
float eff2 = 0.f;
34+
float itof = 0.f;
35+
float otof = 0.f;
36+
float covm[15] = {0.f};
37+
float eigval[5] = {0.f};
38+
float eigvec[5][5] = {{0.f}};
39+
float eiginv[5][5] = {{0.f}};
40+
41+
void print() const;
42+
};
43+
44+
/**
45+
* @brief Binning map
46+
*/
47+
struct map_t {
48+
int nbins = 1;
49+
float min = 0.f;
50+
float max = 1.e6f;
51+
bool log = false;
52+
53+
float eval(int bin) const
54+
{
55+
float width = (max - min) / nbins;
56+
float val = min + (bin + 0.5f) * width;
57+
if (log)
58+
return std::pow(10.f, val);
59+
return val;
60+
}
61+
62+
float fracPositionWithinBin(float val) const;
63+
int find(float val) const;
64+
void print() const;
65+
};
66+
67+
/**
68+
* @brief LUT header
69+
*/
70+
struct lutHeader_t {
71+
int version = LUTCOVM_VERSION;
72+
int pdg = 0;
73+
float mass = 0.f;
74+
float field = 0.f;
75+
map_t nchmap;
76+
map_t radmap;
77+
map_t etamap;
78+
map_t ptmap;
79+
80+
bool check_version() const;
81+
void print() const;
82+
};
83+
84+
/**
85+
* @brief Flat LUT data container - single contiguous buffer
86+
* Memory layout: [header][entry_0][entry_1]...[entry_N]
87+
*
88+
* All entries stored sequentially in a single allocation.
89+
* Can be directly mapped from file or shared memory without copying.
90+
*/
91+
class FlatLutData
92+
{
93+
public:
94+
FlatLutData() = default;
95+
96+
/**
97+
* @brief Initialize from binning information
98+
* Pre-allocates contiguous memory for all entries
99+
*/
100+
void initialize(const lutHeader_t& header);
101+
102+
/**
103+
* @brief Get LUT entry by bin indices
104+
* O(1) access via linear index calculation
105+
*/
106+
lutEntry_t* getEntry(int nch_bin, int rad_bin, int eta_bin, int pt_bin);
107+
const lutEntry_t* getEntry(int nch_bin, int rad_bin, int eta_bin, int pt_bin) const;
108+
109+
/**
110+
* @brief Get raw data buffer (for serialization/shared memory)
111+
*/
112+
uint8_t* data() { return mData.data(); }
113+
const uint8_t* data() const { return mData.data(); }
114+
115+
/**
116+
* @brief Total size in bytes
117+
*/
118+
size_t bytes() const { return mData.size(); }
119+
120+
/**
121+
* @brief Construct from external buffer (e.g., shared memory or file mapping)
122+
*/
123+
static FlatLutData fromBuffer(const uint8_t* buffer, size_t size);
124+
125+
/**
126+
* @brief Reference-based access without copying
127+
* Useful when data is already in shared memory
128+
*/
129+
static FlatLutData fromExternalBuffer(uint8_t* buffer, size_t size);
130+
131+
const lutHeader_t& header() const
132+
{
133+
return *reinterpret_cast<const lutHeader_t*>(mData.data());
134+
}
135+
136+
lutHeader_t& header()
137+
{
138+
return *reinterpret_cast<lutHeader_t*>(mData.data());
139+
}
140+
141+
private:
142+
/**
143+
* @brief Linear index calculation for entry access
144+
*/
145+
size_t getEntryOffset(int nch_bin, int rad_bin, int eta_bin, int pt_bin) const;
146+
147+
std::vector<uint8_t> mData;
148+
149+
// Cache dimensions for quick access
150+
int mNchBins = 0;
151+
int mRadBins = 0;
152+
int mEtaBins = 0;
153+
int mPtBins = 0;
154+
};
155+
156+
} // namespace o2::delphes
157+
158+
#endif // ALICE3_CORE_FLATLUTENTRY_H_

0 commit comments

Comments
 (0)