Skip to content
Snippets Groups Projects
Commit 2be5787b authored by Thomas Steinreiter's avatar Thomas Steinreiter
Browse files

begin to use MPI IO methods instead of own code

parent 57c73023
Branches
No related merge requests found
......@@ -2,6 +2,8 @@
#include <cstddef>
#include <fstream>
#include <iomanip>
#include <sstream>
#include <string>
#include "gsl/gsl"
......@@ -10,18 +12,45 @@
#include "state.hpp"
struct FileIO {
static auto ReadHeader(std::istream& input) {
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)
throw std::logic_error("File header corrupt");
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& headerSize = input.tellg();
return Size{noCols, noRows};
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;
......@@ -41,25 +70,124 @@ struct FileIO {
}
}
static void ReadTile(std::istream& input, Size srcSize, Size gridSize,
std::size_t rank, gsl::span<State> buf,
std::size_t 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;
// 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);
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;
const auto& tileStride = srcSize.Cols + LF;
// StridedRead(input, tileSize.Cols, tileSize.Rows, tileStride, buf,
// bufStride);
StridedRead(input, tileSize.Cols, tileSize.Rows, tileStride, buf,
bufStride);
MPI_Type_free(&tileType);
MPI_Type_free(&bufType);
}
};
\ No newline at end of file
......@@ -35,9 +35,10 @@ class MpiWireworld {
MpiWireworld(const MpiEnvironment& env, const Configuration& cfg)
: _env(env), _cfg(cfg) {
const auto& gridSize = Size{cfg.GridColumns, cfg.GridRows};
std::ifstream input(cfg.InputFilePath);
const auto& _globalSize = FileIO::ReadHeader(input);
const auto& header = FileIO::ReadHeader(cfg.InputFilePath);
const auto& headerLength = header.HeaderLength;
const auto& _globalSize = header.GlobalSize;
_tileSize = FileIO::GetTileSize(_globalSize, gridSize);
_memoryA.resize((_tileSize.Cols + 2) * (_tileSize.Rows + 2));
......@@ -49,11 +50,9 @@ class MpiWireworld {
gsl::as_multi_span(_memoryB.data(), gsl::dim(_tileSize.Rows + 2),
gsl::dim(_tileSize.Cols + 2));
FileIO::ReadTile(
input, _globalSize, gridSize, _env.worldRank(),
gsl::span<State>(_memoryA.data() + _tileSize.Cols + 2 + 1,
_memoryA.size() - 1),
_tileSize.Cols + 2);
FileIO::ReadTile(cfg.InputFilePath, headerLength, _globalSize, gridSize,
_env.worldRank(),
gsl::span<State>(_memoryA.data(), _memoryA.size()));
/*
......@@ -160,7 +159,8 @@ class MpiWireworld {
void Communicate() { _comm.Communicate(_model); }
void simulateStep() {
_comm.Communicate(_model);
_comm.Communicate(_model); // compute the border area first, then comm
// and compute the rest async
for (std::size_t x{1}; x <= _tileSize.Rows; ++x) {
for (std::size_t y{1}; y <= _tileSize.Cols; ++y) {
auto nextState = _model[x][y];
......
......@@ -15,24 +15,19 @@
using namespace std::string_literals;
int main(int argc, char* argv[]) {
static constexpr auto DebugRank = 1;
static constexpr auto DebugRank = 0;
const auto& starttime = std::chrono::system_clock::now();
MpiEnvironment env(argc, argv);
const auto& cfg = Configuration::parseArgs(argc, argv, env);
if (env.worldRank() == DebugRank) {
std::cout << "Config: \n";
std::cout << "col:" << cfg.GridColumns << "\n";
std::cout << "row:" << cfg.GridRows << "\n";
}
MpiWireworld ww(env, cfg);
ww.Communicate();
if (env.worldRank() == DebugRank) { auto err = std::system("clear"); }
//if (env.worldRank() == DebugRank) { auto err = std::system("clear"); }
if (env.worldRank() == DebugRank) std::cout << ww << '\n';
for (std::size_t i{0}; i < 30; ++i) {
for (std::size_t i{0}; i < 0; ++i) {
using namespace std::chrono_literals;
std::this_thread::sleep_for(.5s);
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment