Skip to content
FileIO.hpp 2.75 KiB
Newer Older
#pragma once

#include <cstddef>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>

#include "gsl/gsl"

Thomas Steinreiter's avatar
Thomas Steinreiter committed
#include "MpiSubarray.hpp"
#include "Util.hpp"
#include "state.hpp"

struct FileIO {
Thomas Steinreiter's avatar
Thomas Steinreiter committed
	struct HeaderInfo {
		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();
Thomas Steinreiter's avatar
Thomas Steinreiter committed
		return HeaderInfo{
		    {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};
	}

Thomas Steinreiter's avatar
Thomas Steinreiter committed
	// should return a Tile??
	static void ReadTileData(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;

Thomas Steinreiter's avatar
Thomas Steinreiter committed
		const auto& tileType =
		    MpiSubarray({{srcSize.Rows, tileSize.Rows, 0},
		                 {srcSize.Cols + LF, tileSize.Cols, 0}});
		const auto& bufType =
		    MpiSubarray({{tileSize.Rows + 2, tileSize.Rows, 1},
		                 {tileSize.Cols + 2, tileSize.Cols, 1}});

		// 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;
Thomas Steinreiter's avatar
Thomas Steinreiter committed
		MPI_File_set_view(file, displ, MPI_CHAR, tileType.type(), "native",
Thomas Steinreiter's avatar
Thomas Steinreiter committed
		MPI_File_read_all(file, buf.data(), 1, bufType.type(),
		                  MPI_STATUS_IGNORE);