From: Timo Heister Date: Thu, 7 Jul 2022 17:59:27 +0000 (-0400) Subject: implement read_whole_parallel_file() X-Git-Tag: v9.5.0-rc1~1100^2~8 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f23d2f45c7f47daa3feb51861ecac26202dc4b56;p=dealii.git implement read_whole_parallel_file() fixup fixup --- diff --git a/include/deal.II/base/data_out_base.h b/include/deal.II/base/data_out_base.h index 1db8385a99..9050acc217 100644 --- a/include/deal.II/base/data_out_base.h +++ b/include/deal.II/base/data_out_base.h @@ -2349,7 +2349,7 @@ namespace DataOutBase * into a single file with name @p name. Compression using zlib is optional and controlled * using @p compression. * - * The files typically have the extension .d2_par_patches. + * The files typically have the extension .pd2. */ template void @@ -3222,6 +3222,14 @@ public: void read(std::istream &in); + /** + * Read all data previously written using + * DataOutBase::write_deal_II_intermediate_in_parallel() from all + * MPI ranks into this data structure. + */ + void + read_whole_parallel_file(std::istream &in); + /** * This function can be used to merge the patches read by the other object * into the patches that this present object stores. This is sometimes handy diff --git a/source/base/data_out_base.cc b/source/base/data_out_base.cc index 9e566d75a5..1e4339bb02 100644 --- a/source/base/data_out_base.cc +++ b/source/base/data_out_base.cc @@ -63,6 +63,7 @@ # include #endif +#include #include #include @@ -170,6 +171,22 @@ namespace } } #endif + + + /** + * The header in binary format that the parallel intermediate files + * start with. + */ + struct ParallelIntermediateHeaderType + { + std::uint64_t magic; + std::uint64_t version; + std::uint64_t compression; + std::uint64_t dimension; + std::uint64_t space_dimension; + std::uint64_t num_ranks; + std::uint64_t num_patches; + }; } // namespace @@ -7563,6 +7580,20 @@ namespace DataOutBase (void)comm; #else + + // We write a simple format based on the text format of + // write_deal_II_intermediate() on each MPI rank. The text format + // is quite verbose and we should probably change this to a more + // efficient binary representation at some point. The file layout + // is as follows: + // + // 1. A binary header with layout struct + // ParallelIntermediateHeaderType. + // 2. A list of uint64_t with one value per rank denoting the + // compressed size of the chunks of the next step. + // 3. The (potentially compressed) chunks as generated by + // write_deal_II_intermediate() on each MPI rank. + // First generate my data by writing (optionally compressed) data into // my_buffer: std::vector my_buffer; @@ -7585,24 +7616,14 @@ namespace DataOutBase const std::uint64_t num_ranks = Utilities::MPI::n_mpi_processes(comm); const std::uint64_t num_patches = Utilities::MPI::sum(patches.size(), comm); - struct HeaderType - { - std::uint64_t magic; - std::uint64_t version; - std::uint64_t compression; - std::uint64_t dimension; - std::uint64_t space_dimension; - std::uint64_t num_ranks; - std::uint64_t num_patches; - }; - - const HeaderType header{0x00dea111, - Deal_II_IntermediateFlags::format_version, - compression, - dim, - spacedim, - num_ranks, - num_patches}; + const ParallelIntermediateHeaderType header{ + 0x00dea111, + Deal_II_IntermediateFlags::format_version, + compression, + dim, + spacedim, + num_ranks, + num_patches}; // rank 0 also collects and writes the size of the data from each rank in // bytes: @@ -9226,6 +9247,53 @@ DataOutReader::read(std::istream &in) +template +void +DataOutReader::read_whole_parallel_file(std::istream &in) +{ + AssertThrow(in.fail() == false, ExcIO()); + + ParallelIntermediateHeaderType header; + in.read(reinterpret_cast(&header), sizeof(header)); + + std::vector chunk_sizes(header.num_ranks); + in.read(reinterpret_cast(chunk_sizes.data()), + header.num_ranks * sizeof(std::uint64_t)); + + for (unsigned int n = 0; n < header.num_ranks; ++n) + { + // First read the compressed data into temp_buffer and then + // decompress and put into datastream + std::vector temp_buffer(chunk_sizes[n]); + in.read(temp_buffer.data(), chunk_sizes[n]); + + boost::iostreams::filtering_istreambuf f; + if (header.compression) + f.push(boost::iostreams::zlib_decompressor()); + + boost::iostreams::basic_array_source source(temp_buffer.data(), + temp_buffer.size()); + f.push(source); + + std::stringstream datastream; + boost::iostreams::copy(f, datastream); + + // Now we can load the data and merge this chunk into *this + if (n == 0) + { + read(datastream); + } + else + { + DataOutReader temp_reader; + temp_reader.read(datastream); + merge(temp_reader); + } + } +} + + + template void DataOutReader::merge(const DataOutReader &source) diff --git a/tests/data_out/data_out_intermediate_parallel_01.cc b/tests/data_out/data_out_intermediate_parallel_01.cc index 6c3b24674f..da66e311bb 100644 --- a/tests/data_out/data_out_intermediate_parallel_01.cc +++ b/tests/data_out/data_out_intermediate_parallel_01.cc @@ -13,7 +13,8 @@ // // --------------------------------------------------------------------- -// Test DataOut::write_deal_II_intermediate_in_parallel() +// Test DataOut::write_deal_II_intermediate_in_parallel() and +// DataOutReader::read_whole_parallel_file() #include @@ -63,19 +64,18 @@ check() data_out.build_patches(); data_out.write_deal_II_intermediate_in_parallel( - "test.d2p", MPI_COMM_WORLD, DataOutBase::VtkFlags::no_compression); + "test.pd2", MPI_COMM_WORLD, DataOutBase::VtkFlags::no_compression); const unsigned int my_rank = dealii::Utilities::MPI::this_mpi_process(MPI_COMM_WORLD); if (my_rank == 0) { - // can't checksum as the file contains "[written by deal.II - // 9.5.0-pre]" which would change often, so we just look at the - // size for now. This will of course fail once we go to - // 10.0. :-) - std::ifstream in("test.d2p", std::ifstream::ate | std::ifstream::binary); + // Read the data back in and dump it into the deallog: + std::ifstream in("test.pd2"); Assert(in, dealii::ExcIO()); - deallog << "size: " << in.tellg() << std::endl; + DataOutReader reader; + reader.read_whole_parallel_file(in); + reader.write_deal_II_intermediate(deallog.get_file_stream()); } deallog << "OK" << std::endl; diff --git a/tests/data_out/data_out_intermediate_parallel_01.mpirun=2.output b/tests/data_out/data_out_intermediate_parallel_01.mpirun=2.output index 6a193c2262..5bd7169e4e 100644 --- a/tests/data_out/data_out_intermediate_parallel_01.mpirun=2.output +++ b/tests/data_out/data_out_intermediate_parallel_01.mpirun=2.output @@ -1,5 +1,94 @@ -DEAL:0::size: 1244 +2 2 +[deal.II intermediate format graphics data] +[written by deal.II x.y.z] +[Version: 4] +2 +solution +cell_data +8 +[deal.II intermediate Patch<2,2>] +3 +0.00000 0.00000 0.500000 0.00000 0.00000 0.500000 0.500000 0.500000 +4294967295 1 4294967295 2 +0 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 + + +[deal.II intermediate Patch<2,2>] +3 +0.500000 0.00000 1.00000 0.00000 0.500000 0.500000 1.00000 0.500000 +0 4294967295 4294967295 3 +1 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 1.00000 1.00000 1.00000 1.00000 + + +[deal.II intermediate Patch<2,2>] +3 +0.00000 0.500000 0.500000 0.500000 0.00000 1.00000 0.500000 1.00000 +4294967295 3 0 4294967295 +2 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 2.00000 2.00000 2.00000 2.00000 + + +[deal.II intermediate Patch<2,2>] +3 +0.500000 0.500000 1.00000 0.500000 0.500000 1.00000 1.00000 1.00000 +2 4294967295 1 4294967295 +3 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 3.00000 3.00000 3.00000 3.00000 + + +[deal.II intermediate Patch<2,2>] +3 +0.00000 0.00000 0.500000 0.00000 0.00000 0.500000 0.500000 0.500000 +4294967295 5 4294967295 6 +4 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 0.00000 + + +[deal.II intermediate Patch<2,2>] +3 +0.500000 0.00000 1.00000 0.00000 0.500000 0.500000 1.00000 0.500000 +4 4294967295 4294967295 7 +5 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 1.00000 1.00000 1.00000 1.00000 + + +[deal.II intermediate Patch<2,2>] +3 +0.00000 0.500000 0.500000 0.500000 0.00000 1.00000 0.500000 1.00000 +4294967295 7 4 4294967295 +6 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 2.00000 2.00000 2.00000 2.00000 + + +[deal.II intermediate Patch<2,2>] +3 +0.500000 0.500000 1.00000 0.500000 0.500000 1.00000 1.00000 1.00000 +6 4294967295 5 4294967295 +7 1 +0 +2 4 +0.00000 0.00000 0.00000 0.00000 3.00000 3.00000 3.00000 3.00000 + + +0 + DEAL:0::OK DEAL:1::OK