Skip to content

Commit e8795d0

Browse files
committed
POD version of TPCFastSpaceChargeCorrection
Created from the TPCFastTransform using: std::vector<char> buff; // can be also pmr::vector from DPL make(..) const o2::gpu::TPCFastTransformPOD& pod = o2::gpu::TPCFastTransformPOD::create(buff, tpc_fast_transform); The buff vector will be expanded during creation and can be sent over DPL. On the receiving side, it should be cast as: const auto& podTransform = o2::gpu::TPCFastTransformPOD::get(pc.inputs().get<gsl::span<char>>(ref)); No initialization is needed, the transform methods (at the moment all methods of TPCFastSpaceChargeCorrection are implemented) can be directly queried from the object received over sh.memory. Add perfmormance test for pod map
1 parent 1511172 commit e8795d0

File tree

5 files changed

+579
-0
lines changed

5 files changed

+579
-0
lines changed

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

0 commit comments

Comments
 (0)