#pragma once #include #include #include #include #include #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 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( 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 buf, std::size_t bufStride) { std::size_t writeOffset{0}; for (size_t i{0}; i < count; ++i) { input.read(reinterpret_cast(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 buf) { static constexpr auto DebugRank = 4; constexpr auto LF = 1; // linefeed chars const auto& tileSize = GetTileSize(srcSize, gridSize); const auto& tileX = rank % gridSize.Cols; const auto& tileY = rank / gridSize.Cols; if (rank == DebugRank) { 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 sizes{static_cast(srcSize.Rows), static_cast(srcSize.Cols + LF)}; const std::array subSizes{static_cast(tileSize.Rows), static_cast(tileSize.Cols)}; const std::array starts{0, 0}; if (rank == DebugRank) { 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 sizes{static_cast(tileSize.Rows + 2), static_cast(tileSize.Cols + 2)}; const std::array subSizes{static_cast(tileSize.Rows), static_cast(tileSize.Cols)}; const std::array starts{1, 1}; if (rank == DebugRank) { 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 dbg; dbg.fill((char)0); MPI_File_read_all(file, buf.data(), 1, bufType, MPI_STATUS_IGNORE); // if (rank == DebugRank) { // 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); } };