1 #ifndef DIY_IO_BLOCK_HPP
2 #define DIY_IO_BLOCK_HPP
13 #include "../assigner.hpp"
14 #include "../master.hpp"
15 #include "../storage.hpp"
25 typedef mpi::io::offset offset_t;
30 gid(-1), offset(0), count(0) {}
33 gid(gid_), offset(offset_), count(count_) {}
35 bool operator<(
const GidOffsetCount& other)
const {
return gid < other.gid; }
78 Master::SaveBlock
save = 0)
82 typedef detail::offset_t offset_t;
85 unsigned size = master.
size(),
92 truncate(outfilename.c_str(), 0);
94 mpi::io::file f(comm, outfilename, mpi::io::file::wronly | mpi::io::file::create);
96 offset_t start = 0, shift;
97 std::vector<GidOffsetCount> offset_counts;
99 for (i = 0; i < max_size; ++i)
106 const void* block = master.
get(i);
108 LinkFactory::save(bb, master.link(i));
110 count = bb.buffer.size();
111 mpi::scan(comm, count, offset, std::plus<offset_t>());
112 offset += start - count;
117 f.write_at_all(offset, bb.buffer);
119 f.write_at(offset, bb.buffer);
121 offset_counts.push_back(GidOffsetCount(master.
gid(i), offset, count));
125 mpi::scan(comm, count, offset, std::plus<offset_t>());
129 offset_counts.push_back(GidOffsetCount(-1, offset, count));
133 if (comm.rank() == 0)
136 std::vector< std::vector<char> > gathered_offset_count_buffers;
138 mpi::gather(comm, oc_buffer.buffer, gathered_offset_count_buffers, 0);
140 std::vector<GidOffsetCount> all_offset_counts;
141 for (
unsigned i = 0; i < gathered_offset_count_buffers.size(); ++i)
143 MemoryBuffer oc_buffer; oc_buffer.buffer.swap(gathered_offset_count_buffers[i]);
144 std::vector<GidOffsetCount> offset_counts;
146 for (
unsigned j = 0; j < offset_counts.size(); ++j)
147 if (offset_counts[j].gid != -1)
148 all_offset_counts.push_back(offset_counts[j]);
150 std::sort(all_offset_counts.begin(), all_offset_counts.end());
155 size_t footer_size = bb.size();
159 offset_t footer_offset = 0;
160 for (
unsigned i = 0; i < all_offset_counts.size(); ++i)
162 offset_t end = all_offset_counts[i].offset + all_offset_counts[i].count;
163 if (end > footer_offset)
166 f.write_at(footer_offset, bb.buffer);
185 Master::LoadBlock
load = 0)
189 typedef detail::offset_t offset_t;
194 offset_t footer_offset = f.size() -
sizeof(size_t);
198 f.read_at_all(footer_offset, (
char*) &footer_size,
sizeof(footer_size));
201 footer_offset -= footer_size;
203 footer.buffer.resize(footer_size);
204 f.read_at_all(footer_offset, footer.buffer);
206 std::vector<GidOffsetCount> all_offset_counts;
212 size_t size = all_offset_counts.size();
214 std::vector<int> gids;
217 for (
unsigned i = 0; i < gids.size(); ++i)
219 if (gids[i] != all_offset_counts[gids[i]].gid)
220 get_logger()->warn(
"gids don't match in diy::io::read_blocks(), {} vs {}",
221 gids[i], all_offset_counts[gids[i]].gid);
223 offset_t offset = all_offset_counts[gids[i]].offset,
224 count = all_offset_counts[gids[i]].count;
226 bb.buffer.resize(count);
227 f.read_at(offset, bb.buffer);
228 Link* l = LinkFactory::load(bb);
230 void* b = master.create();
232 master.
add(gids[i], b, l);
243 Master::SaveBlock
save)
252 const mpi::communicator& comm,
255 Master::LoadBlock
load = 0)
273 Master::SaveBlock
save = 0)
277 bool proceed =
false;
279 if (comm.rank() == 0)
282 if (stat(outfilename.c_str(), &s) == 0)
284 if (S_ISDIR(s.st_mode))
286 }
else if (mkdir(outfilename.c_str(), 0755) == 0)
289 mpi::reduce(comm, (
size_t) master.
size(), size, 0, std::plus<size_t>());
297 throw std::runtime_error(
"Cannot access or create directory: " + outfilename);
299 for (
int i = 0; i < (int)master.
size(); ++i)
301 const void* block = master.
get(i);
303 std::string filename = fmt::format(
"{}/{}", outfilename, master.
gid(i));
305 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"w"));
313 if (comm.rank() == 0)
316 std::string filename = outfilename +
"/extra";
317 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"w"));
335 Master::LoadBlock
load = 0)
341 std::string filename = infilename +
"/extra";
342 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"r"));
350 std::vector<int> gids;
354 for (
unsigned i = 0; i < gids.size(); ++i)
356 std::string filename = fmt::format(
"{}/{}", infilename, gids[i]);
358 ::diy::detail::FileBuffer bb(fopen(filename.c_str(),
"r"));
361 void* b = master.create();
363 master.
add(gids[i], b, l);
375 Master::SaveBlock
save)
387 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:330
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 set_nblocks(int nblocks)
sets the total number of global blocks
Definition: assigner.hpp:28
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
void reduce(const communicator &comm, const T &in, T &out, int root, const Op &op)
reduce
Definition: collectives.hpp:286
Definition: assigner.hpp:11
void scan(const communicator &comm, const T &in, T &out, const Op &op)
scan
Definition: collectives.hpp:314
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:16
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:300
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:269
void broadcast(const communicator &comm, T &x, int root)
Broadcast to all processes in comm.
Definition: collectives.hpp:219
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:242
unsigned size() const
return the number of local blocks
Definition: master.hpp:233
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