Peano
Loading...
Searching...
No Matches
EnclaveDataRepository.cpp
Go to the documentation of this file.
1// This file is part of the ExaHyPE2 project. For conditions of distribution and
2// use, please see the copyright notice at www.peano-framework.org
4
5#include "DataRepository.h"
6#include "tarch/accelerator/accelerator.h"
7
10 static EnclaveDataRepository instance;
11 return instance;
12 }
13
15 _isReady(false),
16 _numberOfEnclaveCells(0),
17 _QDevice(nullptr),
18 _QReconstructedDevice(nullptr),
19 _cellCentresDevice(nullptr),
20 _cellSizesDevice(nullptr),
21 _globalFacePoolDevice(nullptr) {}
22
24
28 _uniqueFaceMap.clear();
29 _isReady = false;
31 _minVolumeH = std::numeric_limits<double>::max();
32 _maxVolumeH = std::numeric_limits<double>::min();
33 }
34
36 const tarch::la::Vector<DIMENSIONS, double>& cellCentre,
37 const tarch::la::Vector<DIMENSIONS, double>& cellSize
38 ) {
39 _bookmarkedCellCentres.push_back(cellCentre);
41 }
42
44 if (_bookmarkedCellCentres.empty()) {
45 return;
46 }
47
48 clear();
49
52 const auto qCardinality = hostRepo.getCellQCardinality();
53 const auto qReconstructedCardinality = hostRepo.getCellQReconstructedCardinality();
54 const auto faceCardinality = hostRepo.getFaceCardinality();
55
56 // --- 1. Allocate non-face GPU Memory ---
57 const size_t qSize = static_cast<size_t>(_numberOfEnclaveCells) * static_cast<size_t>(qCardinality);
58 const size_t qReconstructedSize = static_cast<size_t>(_numberOfEnclaveCells)
59 * static_cast<size_t>(qReconstructedCardinality);
60 const size_t totalQSize = qSize + qReconstructedSize;
61
62 _combinedQBlockDevice = tarch::allocateMemory<double>(totalQSize, tarch::MemoryLocation::Device);
65
66 // --- 2. Copy non-face data directly (per-cell) ---
67 for (int i = 0; i < _numberOfEnclaveCells; ++i) {
68 const auto& cellCentre = _bookmarkedCellCentres[i];
69 const auto& cellSize = _bookmarkedCellSizes[i];
70 _minVolumeH = std::min(_minVolumeH, tarch::la::min(cellSize));
71 _maxVolumeH = std::max(_maxVolumeH, tarch::la::max(cellSize));
72
73 tarch::copyTo(
74 _QDevice + i * qCardinality,
75 hostRepo.getCellQ(cellCentre, cellSize),
76 qCardinality,
77 tarch::MemoryLocation::Device
78 );
79 tarch::copyTo(
80 _QReconstructedDevice + i * qReconstructedCardinality,
81 hostRepo.getCellQReconstructed(cellCentre, cellSize),
82 qReconstructedCardinality,
83 tarch::MemoryLocation::Device
84 );
85 }
86
87 // --- 3. Build Unique Face Pool on Host ---
88 // This map will store a unique key for each face and map it to its dense index (0, 1, 2...)
89 // in our new global pool.
90 std::vector<double> hostGlobalFacePool;
91 std::vector<uint64_t> indicesOfBoundaryFacesIntoGlobalFacePool;
92 std::vector<uint8_t> hostBoundaryFaceNumbers;
93 std::vector<uint64_t> hostBoundaryCellIndices;
94 hostGlobalFacePool.reserve(_numberOfEnclaveCells * 2 * faceCardinality); // Pre-allocate rough estimate
95
96 for (int i = 0; i < _numberOfEnclaveCells; ++i) {
97 const auto& cellCentre = _bookmarkedCellCentres[i];
98 const auto& cellSize = _bookmarkedCellSizes[i];
99 for (int f = 0; f < TWO_TIMES_D; ++f) {
100 // 1. Calculate Key to check uniqueness
101 const double ratio = DomainSize[0] / cellSize[0];
102 const int depth = static_cast<int>(std::round(std::log(ratio) / std::log(3.0)));
103 FaceKey faceKey = std::
104 make_tuple(DataRepository::Indexing::getFaceIndex(cellCentre, cellSize, f), depth, f % DIMENSIONS);
105
106 // 2. Find or Insert into Map
107 uint64_t globalFaceIndex;
108 if (_uniqueFaceMap.find(faceKey) == _uniqueFaceMap.end()) {
109 // New face
110 globalFaceIndex = _uniqueFaceMap.size();
111 _uniqueFaceMap[faceKey] = globalFaceIndex;
112
113 double* srcFaceData = hostRepo.getFaceQNew(std::get<0>(faceKey), std::get<1>(faceKey), std::get<2>(faceKey));
114 hostGlobalFacePool.insert(hostGlobalFacePool.end(), srcFaceData, srcFaceData + faceCardinality);
115 } else {
116 // Existing face
117 globalFaceIndex = _uniqueFaceMap[faceKey];
118 }
119
120 // 3. Check if Boundary Face
121 tarch::la::Vector<DIMENSIONS, double> faceCentre(cellCentre);
122 int normal = f % DIMENSIONS;
123 faceCentre(normal) += f >= DIMENSIONS ? cellSize(normal) / 2.0 : -cellSize(normal) / 2.0;
124 bool isBoundary = false;
125 isBoundary |= tarch::la::equals(faceCentre(normal), DomainOffset(normal));
126 isBoundary |= tarch::la::equals(faceCentre(normal), DomainOffset(normal) + DomainSize(normal));
127
128 if (isBoundary) {
129 indicesOfBoundaryFacesIntoGlobalFacePool.push_back(globalFaceIndex);
130 hostBoundaryFaceNumbers.push_back(f);
131 hostBoundaryCellIndices.push_back(i);
132 }
133 }
134 }
135
136 // --- 4. Allocate and Copy Global Face Pool to Device ---
137 _globalFacePoolDevice = tarch::allocateMemory<double>(hostGlobalFacePool.size(), tarch::MemoryLocation::Device);
138 _indicesOfBoundaryFacesDevice = tarch::allocateMemory<uint64_t>(
139 indicesOfBoundaryFacesIntoGlobalFacePool.size(),
140 tarch::MemoryLocation::Device
141 );
142 _boundaryFaceNumbersDevice = tarch::allocateMemory<uint8_t>(
143 hostBoundaryFaceNumbers.size(),
144 tarch::MemoryLocation::Device
145 );
146 _boundaryCellIndicesDevice = tarch::allocateMemory<uint64_t>(
147 hostBoundaryCellIndices.size(),
148 tarch::MemoryLocation::Device
149 );
150
151 tarch::copyTo(
153 hostGlobalFacePool.data(),
154 hostGlobalFacePool.size(),
155 tarch::MemoryLocation::Device
156 );
157
158 // --- Copy boundary faces to Device
159 tarch::copyTo(
161 indicesOfBoundaryFacesIntoGlobalFacePool.data(),
162 indicesOfBoundaryFacesIntoGlobalFacePool.size(),
163 tarch::MemoryLocation::Device
164 );
165 tarch::copyTo(
167 hostBoundaryFaceNumbers.data(),
168 hostBoundaryFaceNumbers.size(),
169 tarch::MemoryLocation::Device
170 );
171 tarch::copyTo(
173 hostBoundaryCellIndices.data(),
174 hostBoundaryCellIndices.size(),
175 tarch::MemoryLocation::Device
176 );
177 _numberOfBoundaryFaces = indicesOfBoundaryFacesIntoGlobalFacePool.size();
178
179 // --- 5. Build Host-side Face Index Array ---
180 uint64_t* indicesOfFacesHost = tarch::allocateMemory<uint64_t>(
181 _numberOfEnclaveCells * TWO_TIMES_D,
182 tarch::MemoryLocation::Heap
183 );
184 _indicesOfFacesDevice = tarch::allocateMemory<uint64_t>(
185 _numberOfEnclaveCells * TWO_TIMES_D,
186 tarch::MemoryLocation::Device
187 );
188
189 for (int i = 0; i < _numberOfEnclaveCells; ++i) {
190 const auto& cellCentre = _bookmarkedCellCentres[i];
191 const auto& cellSize = _bookmarkedCellSizes[i];
192 for (int f = 0; f < TWO_TIMES_D; ++f) {
193 // faceIndex, axis
194 const double ratio = DomainSize[0] / cellSize[0];
195 const int depth = static_cast<int>(std::round(std::log(ratio) / std::log(3.0)));
196 FaceKey faceKey = std::
197 make_tuple(DataRepository::Indexing::getFaceIndex(cellCentre, cellSize, f), depth, f % DIMENSIONS);
198 uint64_t globalFaceIndex = _uniqueFaceMap.at(faceKey);
199 indicesOfFacesHost[f + i * TWO_TIMES_D] = globalFaceIndex;
200 }
201 }
202
203 tarch::copyTo(
205 indicesOfFacesHost,
206 _numberOfEnclaveCells * TWO_TIMES_D,
207 tarch::MemoryLocation::Device
208 );
209
210 // --- 6. Copy Geometric Data (can be done in bulk) ---
211 _cellCentresDevice = tarch::allocateMemory<tarch::la::Vector<DIMENSIONS, double>>(
213 tarch::MemoryLocation::Device
214 );
215 _cellSizesDevice = tarch::allocateMemory<tarch::la::Vector<DIMENSIONS, double>>(
217 tarch::MemoryLocation::Device
218 );
219 tarch::copyTo(
223 tarch::MemoryLocation::Device
224 );
225 tarch::
226 copyTo(_cellSizesDevice, _bookmarkedCellSizes.data(), _bookmarkedCellSizes.size(), tarch::MemoryLocation::Device);
227
228 tarch::freeMemory(indicesOfFacesHost, tarch::MemoryLocation::Heap);
229
230 _isReady = true;
231 }
232
234 tarch::freeMemory(_combinedQBlockDevice, tarch::MemoryLocation::Device);
235 _combinedQBlockDevice = nullptr;
236
237 tarch::freeMemory(_indicesOfBoundaryFacesDevice, tarch::MemoryLocation::Device);
238 tarch::freeMemory(_indicesOfFacesDevice, tarch::MemoryLocation::Device);
239
240 tarch::freeMemory(_cellCentresDevice, tarch::MemoryLocation::Device);
241 tarch::freeMemory(_cellSizesDevice, tarch::MemoryLocation::Device);
242
243 // Clear face data
244 tarch::freeMemory(_globalFacePoolDevice, tarch::MemoryLocation::Device);
245
246 // Clear boundary data
247 tarch::freeMemory(_boundaryFaceNumbersDevice, tarch::MemoryLocation::Device);
248 tarch::freeMemory(_boundaryCellIndicesDevice, tarch::MemoryLocation::Device);
249
250 _QDevice = nullptr;
251 _QReconstructedDevice = nullptr;
252 _cellCentresDevice = nullptr;
253 _cellSizesDevice = nullptr;
254 _globalFacePoolDevice = nullptr;
255
257 _indicesOfFacesDevice = nullptr;
260 _isReady = false;
263 }
264
266 if (!_isReady) {
267 return;
268 }
269
271 const auto qCardinality = hostRepo.getCellQCardinality();
272
273 for (int i = 0; i < _numberOfEnclaveCells; ++i) {
274 const auto& cellCentre = _bookmarkedCellCentres[i];
275 const auto& cellSize = _bookmarkedCellSizes[i];
276 tarch::copyFrom(
277 _QDevice + i * qCardinality,
278 hostRepo.getCellQ(cellCentre, cellSize),
279 qCardinality,
280 tarch::MemoryLocation::Device
281 );
282 }
283 }
284
286 if (!_isReady) {
287 return;
288 }
289
291 const auto faceCardinality = hostRepo.getFaceCardinality();
292
293 for (auto face : _uniqueFaceMap) {
294 // faceIndex, axis
295 FaceKey faceKey = face.first;
296 uint64_t globalFaceIndex = face.second;
297 tarch::copyFrom(
298 _globalFacePoolDevice + globalFaceIndex * faceCardinality,
299 hostRepo.getFaceQNew(std::get<0>(faceKey), std::get<1>(faceKey), std::get<2>(faceKey)),
300 faceCardinality,
301 tarch::MemoryLocation::Device
302 );
303 }
304 }
305
307 if (!_isReady) {
308 return;
309 }
310
312 const auto qCardinality = hostRepo.getCellQCardinality();
313
314 for (int i = 0; i < _numberOfEnclaveCells; ++i) {
315 const auto& cellCentre = _bookmarkedCellCentres[i];
316 const auto& cellSize = _bookmarkedCellSizes[i];
317 tarch::copyTo(
318 _QDevice + i * qCardinality,
319 hostRepo.getCellQ(cellCentre, cellSize),
320 qCardinality,
321 tarch::MemoryLocation::Device
322 );
323 }
324 }
325
327 if (!_isReady) {
328 return;
329 }
330
331 const auto faceCardinality = DataRepository::getInstance().getFaceCardinality();
333 for (auto face : _uniqueFaceMap) {
334 // faceIndex, axis
335 FaceKey faceKey = face.first;
336 uint64_t globalFaceIndex = face.second;
337 tarch::copyTo(
338 _globalFacePoolDevice + globalFaceIndex * faceCardinality,
339 hostRepo.getFaceQNew(std::get<0>(faceKey), std::get<1>(faceKey), std::get<2>(faceKey)),
340 faceCardinality,
341 tarch::MemoryLocation::Device
342 );
343 }
344 }
345
346 // --- GPU Data Accessors ---
354 tarch::la::Vector<DIMENSIONS, double>* EnclaveDataRepository::getCellCentres() { return _cellCentresDevice; }
355 tarch::la::Vector<DIMENSIONS, double>* EnclaveDataRepository::getCellSizes() { return _cellSizesDevice; }
361} // namespace benchmarks::exahype2::kernelbenchmarks
const tarch::la::Vector< DIMENSIONS, double > cellSize
A singleton repository to manage and provide access to grid cell and face data.
double * getFaceQNew(int index, int depth, int axis)
double * getCellQReconstructed(const tarch::la::Vector< DIMENSIONS, double > &cellCentre, const tarch::la::Vector< DIMENSIONS, double > &cellSize)
double * getCellQ(const tarch::la::Vector< DIMENSIONS, double > &cellCentre, const tarch::la::Vector< DIMENSIONS, double > &cellSize)
Manages GPU data for a sparse subset of active leaf cells.
void bookmarkCell(const tarch::la::Vector< DIMENSIONS, double > &cellCentre, const tarch::la::Vector< DIMENSIONS, double > &cellSize)
double * _globalFacePoolDevice
A single, contiguous block of memory holding all unique face data.
std::vector< tarch::la::Vector< DIMENSIONS, double > > _bookmarkedCellSizes
std::vector< tarch::la::Vector< DIMENSIONS, double > > _bookmarkedCellCentres
static int getFaceIndex(const tarch::la::Vector< DIMENSIONS, double > &cellCentre, const tarch::la::Vector< DIMENSIONS, double > &cellSize, int axis)