Newer
Older
#pragma once
#include <cstddef>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include "gsl/gsl"
#include "Util.hpp"
#include "state.hpp"
struct FileIO {
struct Header {
Size GlobalSize;
std::size_t HeaderLength;
};
static auto ReadHeader(const std::string& path) {
// read the header into a buf (20 should be sufficient)
MPI_File fh;
MPI_File_open(MPI_COMM_SELF, path.c_str(),
MPI_MODE_RDONLY | MPI_MODE_UNIQUE_OPEN, MPI_INFO_NULL,
&fh);
constexpr auto HeaderBufSize = 20;
std::array<char, HeaderBufSize> buf;
MPI_File_read_all(fh, buf.data(), buf.size(), MPI_CHAR,
MPI_STATUS_IGNORE);
MPI_File_close(&fh);
// make stream out of buf
std::istringstream input;
input.rdbuf()->pubsetbuf(buf.data(), buf.size());
// parse the stream
std::size_t noCols{};
std::size_t noRows{};
input >> noCols >> noRows;
if (noCols < 1 || noRows < 1) {
std::cerr << "File header corrupt\n";
MPI_Abort(MPI_COMM_WORLD, EXIT_FAILURE);
}
std::string dummy; // skip line break
std::getline(input, dummy);
const auto& headerLength = input.tellg();
return Header{
{noCols, noRows},
static_cast<std::size_t>(
headerLength) // should fit (is max HeaderBuf size)
};
// TODO: is not an IO concern
static auto GetTileSize(Size globalSize, Size gridSize) {
const auto& tileSizeCols = globalSize.Cols / gridSize.Cols;
const auto& tileSizeRows = globalSize.Rows / gridSize.Rows;
return Size{tileSizeCols, tileSizeRows};
}
static void StridedRead(std::istream& input, std::size_t inputChunkLength,
std::size_t count, std::size_t inputStride,
gsl::span<State> buf, std::size_t bufStride) {
std::size_t writeOffset{0};
for (size_t i{0}; i < count; ++i) {
input.read(reinterpret_cast<char*>(buf.data()) + writeOffset,
inputChunkLength);
input.seekg(inputStride - inputChunkLength, std::ios::cur);
writeOffset += bufStride;
}
}
static void ReadTile(const std::string& path, std::size_t headerLength,
Size srcSize, Size gridSize, std::size_t rank,
gsl::span<State> buf) {
constexpr auto LF = 1; // linefeed chars
const auto& tileSize = GetTileSize(srcSize, gridSize);
const auto& tileX = rank % gridSize.Cols;
const auto& tileY = rank / gridSize.Cols;
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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
if (rank == 0) {
std::cout << "headerLength:" << headerLength << "\n";
std::cout << "srcSize.Cols:" << srcSize.Cols << "\n";
std::cout << "srcSize.Rows:" << srcSize.Rows << "\n";
std::cout << "tileSize.Cols:" << tileSize.Cols << "\n";
std::cout << "tileSize.Rows:" << tileSize.Rows << "\n";
std::cout << "tileX:" << tileX << "\n";
std::cout << "tileY:" << tileY << "\n";
}
// create tile type
MPI_Datatype tileType;
{
const std::array<int, 2> sizes{static_cast<int>(srcSize.Cols + LF),
static_cast<int>(srcSize.Rows)};
const std::array<int, 2> subSizes{static_cast<int>(tileSize.Cols),
static_cast<int>(tileSize.Rows)};
const std::array<int, 2> starts{static_cast<int>(tileX),
static_cast<int>(tileY)};
if (rank == 0) {
std::cout << "tileType\nsizes:";
for (const auto i : sizes) std::cout << i << ", ";
std::cout << "\nsubSizes:";
for (const auto i : subSizes) std::cout << i << ", ";
std::cout << "\nstarts:";
for (const auto i : starts) std::cout << i << ", ";
std::cout << "\n";
}
MPI_Type_create_subarray(2, // ndims
sizes.data(), // array_of_sizes
subSizes.data(), // array_of_subsizes
starts.data(), // array_of_starts
MPI_ORDER_FORTRAN, // order
MPI_CHAR, // oldtype
&tileType // newtype
);
MPI_Type_commit(&tileType);
}
// create buf type
MPI_Datatype bufType;
{
const std::array<int, 2> sizes{static_cast<int>(tileSize.Cols + 2),
static_cast<int>(tileSize.Rows + 2)};
const std::array<int, 2> subSizes{static_cast<int>(tileSize.Cols),
static_cast<int>(tileSize.Rows)};
const std::array<int, 2> starts{1, 1};
if (rank == 0) {
std::cout << "\nbufType\nsizes:";
for (const auto i : sizes) std::cout << i << ", ";
std::cout << "\nsubSizes:";
for (const auto i : subSizes) std::cout << i << ", ";
std::cout << "\nstarts:";
for (const auto i : starts) std::cout << i << ", ";
std::cout << "\n";
}
MPI_Type_create_subarray(2, // ndims
sizes.data(), // array_of_sizes
subSizes.data(), // array_of_subsizes
starts.data(), // array_of_starts
MPI_ORDER_FORTRAN, // order
MPI_CHAR, // oldtype
&bufType // newtype
);
MPI_Type_commit(&bufType);
}
// read
MPI_File file;
MPI_File_open(MPI_COMM_WORLD, path.c_str(),
MPI_MODE_RDONLY | MPI_MODE_UNIQUE_OPEN, MPI_INFO_NULL,
&file);
const auto displ =
headerLength + (gridSize.Cols + LF) * tileY + tileSize.Cols * tileX;
if (rank == 0) { std::cout << "displ:" << displ << "\n"; }
MPI_File_set_view(file, displ, MPI_CHAR, tileType, "native",
MPI_INFO_NULL);
// std::array<char, 84> dbg; dbg.fill((char)0);
MPI_File_read_all(file, buf.data(), 1, bufType, MPI_STATUS_IGNORE);
// if (rank == 0) {
// std::cout << "dbg:\n";
// std::size_t cnt{};
// for (const auto& i : dbg) {
// if (cnt++ % (tileSize.Cols + 2) == 0) std::cout << "\n";
// std::cout << std::setw(2) << i << ", ";
// }
// std::cout << "\n";
//}
// std::ifstream input(path);
// input.seekg(headerLength);
//// seek to the begin of the tile
// const auto& displacement =
// (srcSize.Cols + LF) * (tileSize.Rows * tileY) +
// (tileSize.Cols * tileX);
// input.seekg(displacement, std::ios::cur);
// const auto& tileStride = srcSize.Cols + LF;
// StridedRead(input, tileSize.Cols, tileSize.Rows, tileStride, buf,
// bufStride);
MPI_Type_free(&tileType);
MPI_Type_free(&bufType);