Skip to content

Commit 3894259

Browse files
committed
Add POD version of TPCFastTransform
1 parent c60ed96 commit 3894259

5 files changed

Lines changed: 1112 additions & 0 deletions

File tree

GPU/TPCFastTransformation/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ set(SRCS
2525
TPCFastSpaceChargeCorrection.cxx
2626
TPCFastSpaceChargeCorrectionMap.cxx
2727
TPCFastTransform.cxx
28+
TPCFastTransformPOD.cxx
2829
CorrectionMapsHelper.cxx
2930
)
3031

GPU/TPCFastTransformation/TPCFastSpaceChargeCorrection.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ namespace gpu
3838
///
3939
class TPCFastSpaceChargeCorrection : public FlatObject
4040
{
41+
friend class TPCFastTransformPOD;
42+
4143
public:
4244
// obsolete structure, declared here only for backward compatibility
4345
struct SliceInfo {
Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
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+
/// \file TPCFastTransformPOD.cxx
13+
/// \brief Implementation of POD correction map
14+
///
15+
/// \author ruben.shahoayn@cern.ch
16+
17+
#include "TPCFastTransformPOD.h"
18+
#include "GPUDebugStreamer.h"
19+
#if !defined(GPUCA_GPUCODE)
20+
#include <TRandom.h>
21+
#endif
22+
23+
namespace GPUCA_NAMESPACE
24+
{
25+
namespace gpu
26+
{
27+
28+
#if !defined(GPUCA_GPUCODE)
29+
30+
size_t TPCFastTransformPOD::estimateSize(const TPCFastSpaceChargeCorrection& origCorr)
31+
{
32+
// estimate size of own buffer
33+
const size_t selfSizeFix = sizeof(TPCFastTransformPOD);
34+
size_t nextDynOffs = alignOffset(selfSizeFix);
35+
nextDynOffs = alignOffset(nextDynOffs + origCorr.mNumberOfScenarios * sizeof(size_t)); // spline scenarios start here
36+
// space for splines
37+
for (int isc = 0; isc < origCorr.mNumberOfScenarios; isc++) {
38+
const auto& spline = origCorr.mScenarioPtr[isc];
39+
nextDynOffs = alignOffset(nextDynOffs + sizeof(spline));
40+
}
41+
// space for splines data
42+
for (int is = 0; is < 3; is++) {
43+
for (int sector = 0; sector < origCorr.mGeo.getNumberOfSectors(); sector++) {
44+
for (int row = 0; row < NROWS; row++) {
45+
const auto& spline = origCorr.getSpline(sector, row);
46+
int nPar = spline.getNumberOfParameters();
47+
if (is == 1) {
48+
nPar = nPar / 3;
49+
}
50+
if (is == 2) {
51+
nPar = nPar * 2 / 3;
52+
}
53+
nextDynOffs += nPar * sizeof(float);
54+
}
55+
}
56+
}
57+
nextDynOffs = alignOffset(nextDynOffs);
58+
return nextDynOffs;
59+
}
60+
61+
TPCFastTransformPOD& TPCFastTransformPOD::create(char* buff, size_t buffSize, const TPCFastSpaceChargeCorrection& origCorr)
62+
{
63+
// instantiate object to already created buffer of the right size
64+
assert(buffSize > sizeof(TPCFastTransformPOD));
65+
auto& podMap = getNonConst(buff);
66+
podMap.mApplyCorrections = true; // by default always apply corrections
67+
68+
// copy fixed size data --- start
69+
podMap.mNumberOfScenarios = origCorr.mNumberOfScenarios;
70+
std::memcpy(&podMap.mGeo, &origCorr.mGeo, sizeof(TPCFastTransformGeo)); // copy geometry (fixed size)
71+
/* //RSOLD
72+
for (int row = 0; row < NROWS; row++) {
73+
podMap.mRowInfo[row] = origCorr.getRowInfo(row); // dataOffsetBytes will be modified later
74+
}
75+
*/
76+
for (int sector = 0; sector < TPCFastTransformGeo::getNumberOfSectors(); sector++) {
77+
//RSOLD podMap.mSectorInfo[sector] = origCorr.getSectorInfo(sector);
78+
for (int row = 0; row < NROWS; row++) {
79+
podMap.mSectorRowInfos[NROWS * sector + row] = origCorr.getSectorRowInfo(sector, row);
80+
}
81+
}
82+
podMap.mTimeStamp = origCorr.mTimeStamp;
83+
//
84+
// init data members coming from the TPCFastTrasform
85+
podMap.mVdrift = 0.;
86+
podMap.mT0 = 0.;
87+
// copy fixed size data --- end
88+
89+
size_t nextDynOffs = alignOffset(sizeof(TPCFastTransformPOD));
90+
91+
// copy sector scenarios
92+
podMap.mOffsScenariosOffsets = nextDynOffs; // spline scenarios offsets start here
93+
LOGP(debug, "Set mOffsScenariosOffsets = {}", podMap.mOffsScenariosOffsets);
94+
nextDynOffs = alignOffset(nextDynOffs + podMap.mNumberOfScenarios * sizeof(size_t)); // spline scenarios start here
95+
96+
// copy spline objects
97+
size_t* scenOffs = reinterpret_cast<size_t*>(buff + podMap.mOffsScenariosOffsets);
98+
for (int isc = 0; isc < origCorr.mNumberOfScenarios; isc++) {
99+
scenOffs[isc] = nextDynOffs;
100+
const auto& spline = origCorr.mScenarioPtr[isc];
101+
if (buffSize < nextDynOffs + sizeof(spline)) {
102+
throw std::runtime_error(fmt::format("attempt to copy {} bytes for spline for scenario {} to {}, overflowing the buffer of size {}", sizeof(spline), isc, nextDynOffs + sizeof(spline), buffSize));
103+
}
104+
std::memcpy(buff + scenOffs[isc], &spline, sizeof(spline));
105+
nextDynOffs = alignOffset(nextDynOffs + sizeof(spline));
106+
LOGP(debug, "Copy {} bytes for spline scenario {} (ptr:{}) to offsset {}", sizeof(spline), isc, (void*)&spline, scenOffs[isc]);
107+
}
108+
109+
// copy splines data
110+
for (int is = 0; is < 3; is++) {
111+
float* data = reinterpret_cast<float*>(buff + nextDynOffs);
112+
LOGP(debug, "splinID={} start offset {} -> {}", is, nextDynOffs, (void*)data);
113+
for (int sector = 0; sector < origCorr.mGeo.getNumberOfSectors(); sector++) {
114+
podMap.mSplineDataOffsets[sector][is] = nextDynOffs;
115+
size_t rowDataOffs = 0;
116+
for (int row = 0; row < NROWS; row++) {
117+
const auto& spline = origCorr.getSpline(sector, row);
118+
const float* dataOr = origCorr.getCorrectionData(sector, row, is);
119+
int nPar = spline.getNumberOfParameters();
120+
if (is == 1) {
121+
nPar = nPar / 3;
122+
}
123+
if (is == 2) {
124+
nPar = nPar * 2 / 3;
125+
}
126+
LOGP(debug, "Copying {} floats for spline{} of sector:{} row:{} to offset {}", nPar, is, sector, row, nextDynOffs);
127+
size_t nbcopy = nPar * sizeof(float);
128+
if (buffSize < nextDynOffs + nbcopy) {
129+
throw std::runtime_error(fmt::format("attempt to copy {} bytes of data for spline{} of sector{}/row{} to {}, overflowing the buffer of size {}", nbcopy, is, sector, row, nextDynOffs, buffSize));
130+
}
131+
std::memcpy(data, dataOr, nbcopy);
132+
podMap.getSectorRowInfo(sector, row).dataOffsetBytes[is] = rowDataOffs;
133+
rowDataOffs += nbcopy;
134+
data += nPar;
135+
nextDynOffs += nbcopy;
136+
}
137+
}
138+
}
139+
podMap.mTotalSize = alignOffset(nextDynOffs);
140+
if (buffSize != podMap.mTotalSize) {
141+
throw std::runtime_error(fmt::format("Estimated buffer size {} differs from filled one {}", buffSize, podMap.mTotalSize));
142+
}
143+
return podMap;
144+
}
145+
146+
TPCFastTransformPOD& TPCFastTransformPOD::create(char* buff, size_t buffSize, const TPCFastTransform& src)
147+
{
148+
// instantiate objec to already created buffer of the right size
149+
auto& podMap = create(buff, buffSize, src.getCorrection());
150+
// set data members of TPCFastTransform
151+
podMap.mVdrift = src.getVDrift();
152+
podMap.mT0 = src.getT0();
153+
// copy fixed size data --- end
154+
return podMap;
155+
}
156+
157+
bool TPCFastTransformPOD::test(const TPCFastSpaceChargeCorrection& origCorr, int npoints) const
158+
{
159+
if (npoints < 1) {
160+
return false;
161+
}
162+
std::vector<unsigned char> sector, row;
163+
std::vector<float> u, v, dxO, duO, dvO, dxP, duP, dvP, corrXO, corrXP, nomUO, nomVO, nomUP, nomVP;
164+
sector.reserve(npoints);
165+
row.reserve(npoints);
166+
u.reserve(npoints);
167+
v.reserve(npoints);
168+
dxO.resize(npoints);
169+
duO.resize(npoints);
170+
dvO.resize(npoints);
171+
corrXO.resize(npoints);
172+
nomUO.resize(npoints);
173+
nomVO.resize(npoints);
174+
dxP.resize(npoints);
175+
duP.resize(npoints);
176+
dvP.resize(npoints);
177+
corrXP.resize(npoints);
178+
nomUP.resize(npoints);
179+
nomVP.resize(npoints);
180+
181+
for (int i = 0; i < npoints; i++) {
182+
sector.push_back(gRandom->Integer(NSECTORS));
183+
row.push_back(gRandom->Integer(NROWS));
184+
u.push_back(gRandom->Rndm() * 15);
185+
v.push_back(gRandom->Rndm() * 200);
186+
}
187+
long origStart[3], origEnd[3], thisStart[3], thisEnd[3];
188+
origStart[0] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
189+
for (int i = 0; i < npoints; i++) {
190+
origCorr.getCorrection(sector[i], row[i], u[i], v[i], dxO[i], duO[i], dvO[i]);
191+
}
192+
origEnd[0] = origStart[1] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
193+
for (int i = 0; i < npoints; i++) {
194+
origCorr.getCorrectionInvCorrectedX(sector[i], row[i], u[i], v[i], corrXO[i]);
195+
}
196+
origEnd[1] = origStart[2] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
197+
for (int i = 0; i < npoints; i++) {
198+
origCorr.getCorrectionInvUV(sector[i], row[i], u[i], v[i], nomUO[i], nomVO[i]);
199+
}
200+
origEnd[2] = thisStart[0] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
201+
for (int i = 0; i < npoints; i++) {
202+
this->getCorrection(sector[i], row[i], u[i], v[i], dxP[i], duP[i], dvP[i]);
203+
}
204+
thisEnd[0] = thisStart[1] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
205+
for (int i = 0; i < npoints; i++) {
206+
this->getCorrectionInvCorrectedX(sector[i], row[i], u[i], v[i], corrXP[i]);
207+
}
208+
thisEnd[1] = thisStart[2] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
209+
for (int i = 0; i < npoints; i++) {
210+
this->getCorrectionInvUV(sector[i], row[i], u[i], v[i], nomUP[i], nomVP[i]);
211+
}
212+
thisEnd[2] = std::chrono::time_point_cast<std::chrono::microseconds>(std::chrono::system_clock::now()).time_since_epoch().count();
213+
//
214+
size_t ndiff[3] = {};
215+
for (int i = 0; i < npoints; i++) {
216+
if (dxO[i] != dxP[i] || duO[i] != duP[i] || dvO[i] != dvP[i]) {
217+
ndiff[0]++;
218+
}
219+
if (corrXO[i] != corrXP[i]) {
220+
ndiff[1]++;
221+
}
222+
if (nomUO[i] != nomUP[i] || nomVO[i] != nomVP[i]) {
223+
ndiff[2]++;
224+
}
225+
}
226+
//
227+
LOGP(info, " (ns per call) original this Nmissmatch");
228+
LOGP(info, "getCorrection {:.3e} {:.3e} {}", double(origEnd[0] - origStart[0]) / npoints * 1000., double(thisEnd[0] - thisStart[0]) / npoints * 1000., ndiff[0]);
229+
LOGP(info, "getCorrectionInvCorrectedX {:.3e} {:.3e} {}", double(origEnd[1] - origStart[1]) / npoints * 1000., double(thisEnd[1] - thisStart[1]) / npoints * 1000., ndiff[1]);
230+
LOGP(info, "getCorrectionInvUV {:.3e} {:.3e} {}", double(origEnd[2] - origStart[2]) / npoints * 1000., double(thisEnd[2] - thisStart[2]) / npoints * 1000., ndiff[2]);
231+
return ndiff[0] == 0 && ndiff[1] == 0 && ndiff[2] == 0;
232+
}
233+
234+
#endif
235+
236+
} // namespace gpu
237+
} // namespace GPUCA_NAMESPACE

0 commit comments

Comments
 (0)