1 #ifndef DIY_IO_BLOCK_HPP
2 #define DIY_IO_BLOCK_HPP
9 #include "../assigner.hpp"
10 #include "../master.hpp"
11 #include "../storage.hpp"
22 typedef mpi::io::offset offset_t;
27 gid(-1), offset(0), count(0) {}
30 gid(gid_), offset(offset_), count(count_) {}
32 bool operator<(
const GidOffsetCount& other)
const {
return gid < other.gid; }
75 Master::SaveBlock
save = 0)
79 typedef detail::offset_t offset_t;
82 unsigned size = master.
size(),
89 diy::io::utils::truncate(outfilename.c_str(), 0);
91 mpi::io::file f(comm, outfilename, mpi::io::file::wronly | mpi::io::file::create);
93 offset_t start = 0, shift;
94 std::vector<GidOffsetCount> offset_counts;
95 for (
unsigned i = 0; i < max_size; ++i)
102 const void* block = master.
get(i);
104 LinkFactory::save(bb, master.link(i));
106 count = bb.buffer.size();
107 mpi::scan(comm, count, offset, std::plus<offset_t>());
108 offset += start - count;
113 f.write_at_all(offset, bb.buffer);
115 f.write_at(offset, bb.buffer);
117 offset_counts.push_back(GidOffsetCount(master.
gid(i), offset, count));
121 mpi::scan(comm, count, offset, std::plus<offset_t>());
125 offset_counts.push_back(GidOffsetCount(-1, offset, count));
129 if (comm.rank() == 0)
132 std::vector< std::vector<char> > gathered_offset_count_buffers;
134 mpi::gather(comm, oc_buffer.buffer, gathered_offset_count_buffers, 0);
136 std::vector<GidOffsetCount> all_offset_counts;
137 for (
unsigned i = 0; i < gathered_offset_count_buffers.size(); ++i)
139 MemoryBuffer per_rank_oc_buffer; per_rank_oc_buffer.buffer.swap(gathered_offset_count_buffers[i]);
140 std::vector<GidOffsetCount> per_rank_offset_counts;
141 diy::load(per_rank_oc_buffer, per_rank_offset_counts);
142 for (
unsigned j = 0; j < per_rank_offset_counts.size(); ++j)
143 if (per_rank_offset_counts[j].gid != -1)
144 all_offset_counts.push_back(per_rank_offset_counts[j]);
146 std::sort(all_offset_counts.begin(), all_offset_counts.end());
151 size_t footer_size = bb.size();
155 offset_t footer_offset = 0;
156 for (
unsigned i = 0; i < all_offset_counts.size(); ++i)
158 offset_t end = all_offset_counts[i].offset + all_offset_counts[i].count;
159 if (end > footer_offset)
162 f.write_at(footer_offset, bb.buffer);
181 Master::LoadBlock
load = 0)
185 typedef detail::offset_t offset_t;
190 offset_t footer_offset = f.size() -
sizeof(size_t);
194 f.read_at_all(footer_offset, (
char*) &footer_size,
sizeof(footer_size));
197 footer_offset -= footer_size;
199 footer.buffer.resize(footer_size);
200 f.read_at_all(footer_offset, footer.buffer);
202 std::vector<GidOffsetCount> all_offset_counts;
208 size_t size = all_offset_counts.size();
210 std::vector<int> gids;
213 for (
unsigned i = 0; i < gids.size(); ++i)
215 if (gids[i] != all_offset_counts[gids[i]].gid)
216 get_logger()->warn(
"gids don't match in diy::io::read_blocks(), {} vs {}",
217 gids[i], all_offset_counts[gids[i]].gid);
219 offset_t offset = all_offset_counts[gids[i]].offset,
220 count = all_offset_counts[gids[i]].count;
222 bb.buffer.resize(count);
223 f.read_at(offset, bb.buffer);
224 Link* l = LinkFactory::load(bb);
226 void* b = master.create();
228 master.
add(gids[i], b, l);
239 Master::SaveBlock
save)
248 const mpi::communicator& comm,
251 Master::LoadBlock
load = 0)
269 Master::SaveBlock
save = 0)
273 bool proceed =
false;
275 if (comm.rank() == 0)
277 if (diy::io::utils::is_directory(outfilename))
279 else if (diy::io::utils::make_directory(outfilename))
283 mpi::reduce(comm, (
size_t) master.
size(), size, 0, std::plus<size_t>());
291 throw std::runtime_error(
"Cannot access or create directory: " + outfilename);
293 for (
int i = 0; i < (int)master.
size(); ++i)
295 const void* block = master.
get(i);
297 std::string filename = fmt::format(
"{}/{}", outfilename, master.
gid(i));
299 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"w"));
301 LinkFactory::save(bb, master.link(i));
307 if (comm.rank() == 0)
310 std::string filename = outfilename +
"/extra";
311 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"w"));
329 Master::LoadBlock
load = 0)
336 std::string filename = infilename +
"/extra";
337 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"r"));
346 std::vector<int> gids;
350 for (
unsigned i = 0; i < gids.size(); ++i)
352 std::string filename = fmt::format(
"{}/{}", infilename, gids[i]);
354 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"r"));
355 Link* l = LinkFactory::load(bb);
357 void* b = master.create();
359 master.
add(gids[i], b, l);
371 Master::SaveBlock
save)
383 Master::LoadBlock
load = 0)
Definition: operations.hpp:10
void read_blocks(const std::string &infilename, const mpi::communicator &comm, Assigner &assigner, Master &master, MemoryBuffer &extra, Master::LoadBlock load=0)
Read blocks from storage independently from one file per process.
Definition: block.hpp:324
void load(BinaryBuffer &bb, T &x)
Loads x from bb by calling diy::Serialization<T>::load(bb,x).
Definition: serialization.hpp:106
void * get(int i)
return the i-th block, loading it if necessary
Definition: master.hpp:217
void save(BinaryBuffer &bb, const T &x)
Saves x to bb by calling diy::Serialization<T>::save(bb,x).
Definition: serialization.hpp:102
int gid(int i) const
return gid of the i-th block
Definition: master.hpp:219
Definition: operations.hpp:12
unsigned int size() const
return the number of local blocks
Definition: master.hpp:233
void reduce(const communicator &comm, const T &in, T &out, int root, const Op &op)
reduce
Definition: collectives.hpp:382
Definition: assigner.hpp:11
void scan(const communicator &comm, const T &in, T &out, const Op &op)
scan
Definition: collectives.hpp:410
int add(int gid, void *b, Link *l)
add a block
Definition: master.hpp:658
Definition: master.hpp:35
Wraps MPI file IO.
Definition: io.hpp:18
Simple wrapper around MPI_Comm.
Definition: communicator.hpp:8
Definition: serialization.hpp:26
virtual void local_gids(int rank, std::vector< int > &gids) const =0
gets the local gids for a given process rank
Main interface to serialization, meant to be specialized for the types that require special handling...
Definition: serialization.hpp:90
void all_reduce(const communicator &comm, const T &in, T &out, const Op &op)
all_reduce
Definition: collectives.hpp:396
void set_nblocks(int nblocks__)
sets the total number of global blocks
Definition: assigner.hpp:28
void write_blocks(const std::string &outfilename, const mpi::communicator &comm, Master &master, const MemoryBuffer &extra=MemoryBuffer(), Master::SaveBlock save=0)
Write blocks to storage independently in one file per process.
Definition: block.hpp:265
void broadcast(const communicator &comm, T &x, int root)
Broadcast to all processes in comm.
Definition: collectives.hpp:315
A serialization buffer.
Definition: serialization.hpp:19
void gather(const communicator &comm, const T &in, std::vector< T > &out, int root)
Gather from all processes in comm. On root process, out is resized to comm.size() and filled with ele...
Definition: collectives.hpp:338
void sort(Master &master, const Assigner &assigner, std::vector< T > Block::*values, std::vector< T > Block::*samples, size_t num_samples, const Cmp &cmp, int k=2, bool samples_only=false)
sample sort values of each block, store the boundaries between blocks in samples
Definition: algorithms.hpp:25