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;
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.Rows),
static_cast<int>(srcSize.Cols + LF)};
const std::array<int, 2> subSizes{static_cast<int>(tileSize.Rows),
static_cast<int>(tileSize.Cols)};
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_C, // 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.Rows + 2),
static_cast<int>(tileSize.Cols + 2)};
const std::array<int, 2> subSizes{static_cast<int>(tileSize.Rows),
static_cast<int>(tileSize.Cols)};
const std::array<int, 2> starts{1, 1};
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_C, // 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 +
(srcSize.Cols + LF) * tileSize.Rows * tileY +
tileSize.Cols * tileX;
if (rank == DebugRank) { 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);
// 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);