7#include <boost/iostreams/device/array.hpp>
8#include <boost/iostreams/device/back_inserter.hpp>
9#include <boost/iostreams/stream.hpp>
13std::ostream& ParallelUtilities::get_random_color(std::ostream& stream,
const int rank) {
15 static std::vector<std::ostream& (*)(std::ostream&)> colors = {
22 termcolor::bright_green,
23 termcolor::bright_yellow,
24 termcolor::bright_blue,
25 termcolor::bright_magenta,
26 termcolor::bright_cyan,
27 termcolor::bright_white
31 return colors[
rank % colors.size()](stream);
35void ParallelUtilities::print_message(
const int rank,
const std::string& message,
const bool log) {
41 std::cout << termcolor::colorize << termcolor::red <<
"S[" <<
rank <<
"] - " << message << termcolor::reset << std::endl;
44 std::cout << termcolor::colorize;
45 get_random_color(std::cout,
rank);
47 std::cout << termcolor::colorize <<
"C[" <<
rank <<
"] - " << message << termcolor::reset << std::endl;
116std::string ParallelUtilities::serialize_object(
const T& obj) {
125 boost::iostreams::stream<boost::iostreams::back_insert_device<std::string>> os(bytes);
126 boost::archive::binary_oarchive oa(os);
139 static constexpr size_t WIRE_LZ4_MAX = size_t(4) << 20;
140 if (bytes.size() <= WIRE_LZ4_MAX) {
141 auto packed =
lz4_compress(bytes.data(),
static_cast<int>(bytes.size()));
142 return std::string(packed.data(), packed.size());
144 std::string framed(
sizeof(int32_t) + bytes.size(),
'\0');
145 const int32_t raw_marker = -
static_cast<int32_t
>(bytes.size());
146 std::memcpy(&framed[0], &raw_marker,
sizeof(int32_t));
147 std::memcpy(&framed[
sizeof(int32_t)], bytes.data(), bytes.size());
150 catch (
const std::exception& ex) {
151 std::cerr <<
"FATAL: serialization failed: " << ex.what() << std::endl;
152 MPI_Abort(MPI_COMM_WORLD, 1);
157void ParallelUtilities::send_bytes(
const std::string& bytes,
const int dest_rank,
const int tag, MPI_Comm comm) {
160 int size =
static_cast<int>(bytes.size());
161 MPI_Send(&
size, 1, MPI_INT, dest_rank, tag, comm);
162 MPI_Send(bytes.data(),
size, MPI_CHAR, dest_rank, tag, comm);
166void ParallelUtilities::send_object(
const T& obj,
int dest_rank,
int tag, MPI_Comm comm) {
167 send_bytes(serialize_object(obj), dest_rank, tag, comm);
171void ParallelUtilities::receive_object(T& obj,
int src_rank,
int tag, MPI_Comm comm) {
174 MPI_Recv(&
size, 1, MPI_INT, src_rank, tag, comm, MPI_STATUS_IGNORE);
178 std::unique_ptr<char[]> buffer(
new char[
static_cast<size_t>(
size)]);
179 MPI_Recv(buffer.get(),
size, MPI_CHAR, src_rank, tag, comm, MPI_STATUS_IGNORE);
186 std::memcpy(&head, buffer.get(),
sizeof(int32_t));
188 const size_t raw_sz =
static_cast<size_t>(-
static_cast<int64_t
>(head));
189 boost::iostreams::stream<boost::iostreams::array_source> is(
190 buffer.get() +
sizeof(int32_t), raw_sz);
191 boost::archive::binary_iarchive ia(is);
196 boost::iostreams::stream<boost::iostreams::array_source> is(raw.data(), raw.size());
197 boost::archive::binary_iarchive ia(is);
201 catch (
const std::exception& ex) {
204 std::cerr <<
"FATAL: deserialization failed (tag " << tag <<
" from rank "
205 << src_rank <<
"): " << ex.what() << std::endl;
211template void ParallelUtilities::send_object<RestartNodeInfo>(
const RestartNodeInfo& obj,
int dest_rank,
int tag, MPI_Comm comm);
212template void ParallelUtilities::send_object<BranchRecord>(
const BranchRecord& obj,
int dest_rank,
int tag, MPI_Comm comm);
213template std::string ParallelUtilities::serialize_object<RestartNodeInfo>(
const RestartNodeInfo& obj);
214template std::string ParallelUtilities::serialize_object<BranchRecord>(
const BranchRecord& obj);
216template void ParallelUtilities::receive_object<RestartNodeInfo>(
RestartNodeInfo& obj,
int src_rank,
int tag, MPI_Comm comm);
217template void ParallelUtilities::receive_object<BranchRecord>(
BranchRecord& obj,
int src_rank,
int tag, MPI_Comm comm);
219template void ParallelUtilities::send_object<SequenceOutputData>(
const SequenceOutputData& obj,
int dest_rank,
int tag, MPI_Comm comm);
220template void ParallelUtilities::receive_object<SequenceOutputData>(
SequenceOutputData& obj,
int src_rank,
int tag, MPI_Comm comm);
std::vector< char > lz4_compress(const char *data, int size)
LZ4-compress a buffer with a 4-byte original-size header.
std::vector< char > lz4_decompress(const char *data, int size)
LZ4-decompress a buffer that has a 4-byte original-size header.
Static MPI utility functions — colored logging, Boost object serialization over MPI.
bool log
Enable/disable rank-specific logging.
int size
Total number of MPI processes.
int rank
MPI rank of this process.
Per-sequence output payload sent from client to server via MPI.