Files
geant4/source/analysis/g4tools/include/tools/mpi/wrmpi
T
2016-06-10 14:11:04 +02:00

286 lines
8.3 KiB
Plaintext

// Copyright (C) 2010, Guy Barrand. All rights reserved.
// See the file tools.license for terms.
#ifndef tools_mpi_wrmpi
#define tools_mpi_wrmpi
#ifdef TOOLS_USE_NATIVE_MPI
#include <mpi.h>
#else
#include "dummy_mpi.h"
#endif
#include <tools/impi>
#include <tools/vdata>
#include <tools/typedefs>
#include <tools/realloc>
#include <tools/mnmx>
#include <ostream>
#ifdef TOOLS_MEM
#include <tools/mem>
#endif
namespace tools {
namespace mpi {
class wrmpi : public virtual tools::impi {
typedef tools::impi parent;
protected:
typedef unsigned int num_t;
static const std::string& s_class() {
static const std::string s_v("tools::mpi::wrmpi");
return s_v;
}
public: //inlib::mpi::impi
virtual bool pack(unsigned int a_val) {
tools::uint32 sz = tools::uint32(sizeof(unsigned int));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Pack(unsigned int) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool pack(double a_val) {
tools::uint32 sz = tools::uint32(sizeof(double));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
if(::MPI_Pack(&a_val,1,MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Pack(double) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool bpack(bool a_val) {
tools::uint32 sz = tools::uint32(sizeof(unsigned char));
if(m_pos+sz>m_max) {if(!expand2(m_size+sz)) return false;}
unsigned char val = a_val?1:0;
if(::MPI_Pack(&val,1,MPI_UNSIGNED_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Pack(bool) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool spack(const std::string& a_s) {
if(!pack((num_t)a_s.size())) return false;
tools::uint32 sz = (tools::uint32)a_s.size();
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#ifdef TOOLS_USE_MPI_PACK_NOT_CONST
if(::MPI_Pack(const_cast<char*>(a_s.c_str()),a_s.size(),MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(a_s.c_str(),a_s.size(),MPI_CHAR,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "tools::mpi::wrmpi : MPI_Pack(std::string) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool vpack(const std::vector<unsigned int>& a_v) {
if(!pack((num_t)a_v.size())) return false;
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(unsigned int));
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#ifdef TOOLS_USE_MPI_PACK_NOT_CONST
if(::MPI_Pack(const_cast<unsigned int*>(tools::vec_data(a_v)),a_v.size(),
MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_UNSIGNED,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "tools::mpi::wrmpi : MPI_Pack(std::vector<unsigned int>) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
virtual bool vpack(const std::vector<double>& a_v) {
if(!pack((num_t)a_v.size())) return false;
tools::uint32 sz = (tools::uint32)(a_v.size()*sizeof(double));
if((m_pos+sz)>m_max) {if(!expand2(m_size+sz)) return false;}
#ifdef TOOLS_USE_MPI_PACK_NOT_CONST
if(::MPI_Pack(const_cast<double*>(tools::vec_data(a_v)),a_v.size(),
MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#else
if(::MPI_Pack(tools::vec_data(a_v),a_v.size(),MPI_DOUBLE,m_buffer,m_size,&m_ipos,m_comm)!=MPI_SUCCESS) {
#endif
m_out << "tools::mpi::wrmpi : MPI_Pack(std::vector<double>) failed." << std::endl;
return false;
}
m_pos += sz;
return true;
}
public: //inlib::mpi::impi
virtual bool unpack(unsigned int& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_UNSIGNED,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Unpack(unsigned int) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool unpack(double& a_val) {
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&a_val,1,MPI_DOUBLE,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Unpack(double) failed." << std::endl;
a_val = 0;
return false;
}
return true;
}
virtual bool bunpack(bool& a_val) {
typedef unsigned char bool_t;
bool_t val;
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,&val,1,MPI_UNSIGNED_CHAR,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Unpack(bool) failed." << std::endl;
a_val = false;
return false;
}
a_val = val==1?true:false;
return true;
}
virtual bool vunpack(std::vector<unsigned int>& a_v) {
num_t num;
if(!unpack(num)) {a_v.clear();return false;}
a_v.resize(num);
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_UNSIGNED,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Unpack(std::vector<unsigned int>) failed." << std::endl;
a_v.clear();
return false;
}
return true;
}
virtual bool vunpack(std::vector<double>& a_v) {
num_t num;
if(!unpack(num)) {a_v.clear();return false;}
a_v.resize(num);
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,tools::vec_data(a_v),a_v.size(),MPI_DOUBLE,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Unpack(std::vector<double>) failed." << std::endl;
a_v.clear();
return false;
}
return true;
}
virtual bool sunpack(std::string& a_s) {
num_t num;
if(!unpack(num)) {a_s.clear();return false;}
a_s.resize(num);
if(::MPI_Unpack(m_buffer,m_size,&m_ipos,const_cast<char*>(a_s.c_str()),a_s.size(),MPI_CHAR,m_comm)!=MPI_SUCCESS) {
m_out << "tools::mpi::wrmpi : MPI_Unpack(std::string) failed." << std::endl;
a_s.clear();
return false;
}
return true;
}
public:
wrmpi(std::ostream& a_out,const MPI_Comm& a_comm,tools::uint32 a_size = 128) // we expect a_size!=0
:m_out(a_out)
,m_comm(a_comm)
,m_size(0)
,m_buffer(0)
,m_max(0)
,m_pos(0)
,m_ipos(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
m_size = a_size;
m_buffer = new char[m_size];
//if(!m_buffer) {}
m_max = m_buffer+m_size;
m_pos = m_buffer;
}
wrmpi(std::ostream& a_out,const MPI_Comm& a_comm,tools::uint32 a_size,char* a_buffer) //we take ownership of a_buffer.
:m_out(a_out)
,m_comm(a_comm)
,m_size(a_size)
,m_buffer(a_buffer)
,m_max(0)
,m_pos(0)
,m_ipos(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
m_max = m_buffer+m_size;
m_pos = m_buffer;
}
virtual ~wrmpi(){
delete [] m_buffer;
#ifdef TOOLS_MEM
tools::mem::decrement(s_class().c_str());
#endif
}
protected:
wrmpi(const wrmpi& a_from)
:parent(a_from)
,m_out(a_from.m_out)
,m_comm(a_from.m_comm)
,m_size(0)
,m_buffer(0)
,m_max(0)
,m_pos(0)
,m_ipos(0)
{
#ifdef TOOLS_MEM
tools::mem::increment(s_class().c_str());
#endif
}
wrmpi& operator=(const wrmpi&){return *this;}
public:
int ipos() const {return m_ipos;}
#ifdef TOOLS_USE_MPI_PACK_NOT_CONST
char* buffer() {return m_buffer;}
#else
const char* buffer() const {return m_buffer;}
#endif
void pack_reset() {
delete [] m_buffer;
m_size = 128;
m_buffer = new char[m_size];
//if(!m_buffer) {}
m_max = m_buffer+m_size;
m_pos = m_buffer;
m_ipos = 0; //IMPORTANT
}
protected:
bool expand2(tools::uint32 a_new_size) {return expand(tools::mx<tools::uint32>(2*m_size,a_new_size));} //CERN-ROOT logic.
bool expand(tools::uint32 a_new_size) {
tools::diff_pointer_t len = m_pos-m_buffer;
if(!tools::realloc<char>(m_buffer,a_new_size,m_size)) {
m_out << "tools::mpi::wrmpi::expand :"
<< " can't realloc " << a_new_size << " bytes."
<< std::endl;
m_size = 0;
m_max = 0;
m_pos = 0;
//m_wb.set_eob(m_max);
return false;
}
m_size = a_new_size;
m_max = m_buffer + m_size;
m_pos = m_buffer + len;
return true;
}
protected:
std::ostream& m_out;
const MPI_Comm& m_comm;
tools::uint32 m_size;
char* m_buffer;
char* m_max;
char* m_pos;
//
int m_ipos;
};
}}
#endif
//exlib_build_use inlib mpi