forked from openPMD/openPMD-api
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy path4_read_parallel.cpp
More file actions
114 lines (97 loc) · 3.95 KB
/
4_read_parallel.cpp
File metadata and controls
114 lines (97 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* Copyright 2017-2021 Fabian Koller
*
* This file is part of openPMD-api.
*
* openPMD-api is free software: you can redistribute it and/or modify
* it under the terms of of either the GNU General Public License or
* the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* openPMD-api is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License and the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU General Public License
* and the GNU Lesser General Public License along with openPMD-api.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <openPMD/openPMD.hpp>
#include <mpi.h>
#include <cstddef>
#include <iostream>
#include <memory>
using std::cout;
using namespace openPMD;
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
int mpi_size;
int mpi_rank;
MPI_Comm_size(MPI_COMM_WORLD, &mpi_size);
MPI_Comm_rank(MPI_COMM_WORLD, &mpi_rank);
Series series = Series(
"../samples/git-sample/data%T.h5",
Access::READ_ONLY,
MPI_COMM_WORLD,
R"({"defer_iteration_parsing": true})");
if (0 == mpi_rank)
cout << "Read a series in parallel with " << mpi_size << " MPI ranks\n";
// with defer_iteration_parsing, open() must be called explicitly
// explicit Iteration opening is recommended in general for parallel
// applications
MeshRecordComponent E_x = series.snapshots()[100].open().meshes["E"]["x"];
Offset chunk_offset = {static_cast<long unsigned int>(mpi_rank) + 1, 1, 1};
Extent chunk_extent = {2, 2, 1};
// If you know the datatype, use `loadChunk<double>(...)` instead.
auto chunk_data = E_x.loadChunkVariant(chunk_offset, chunk_extent);
if (0 == mpi_rank)
cout << "Queued the loading of a single chunk per MPI rank from "
"disk, "
"ready to execute\n";
// The iteration can be closed in order to help free up resources.
// The iteration's content will be flushed automatically.
series.snapshots()[100].close();
if (0 == mpi_rank)
cout << "Chunks have been read from disk\n";
for (int i = 0; i < mpi_size; ++i)
{
if (i == mpi_rank)
{
cout << "Rank " << mpi_rank << " - Read chunk contains:\n";
for (size_t row = 0; row < chunk_extent[0]; ++row)
{
for (size_t col = 0; col < chunk_extent[1]; ++col)
{
cout << "\t" << '(' << row + chunk_offset[0] << '|'
<< col + chunk_offset[1] << '|' << 1 << ")\t";
/*
* For hot loops, the std::visit(...) call should be moved
* further up.
*/
std::visit(
[row, col, &chunk_extent](auto &shared_ptr) {
cout << shared_ptr
.get()[row * chunk_extent[1] + col];
},
chunk_data);
}
cout << std::endl;
}
}
// this barrier is not necessary but structures the example output
MPI_Barrier(MPI_COMM_WORLD);
}
// The files in 'series' are still open until the series is closed, at which
// time it cleanly flushes and closes all open file handles.
// One can close the object explicitly to trigger this.
// Alternatively, this will automatically happen once the garbage collector
// claims (every copy of) the series object.
// In any case, this must happen before MPI_Finalize() is called
series.close();
// openPMD::Series MUST be destructed or closed at this point
MPI_Finalize();
return 0;
}