// Copyright (C) 2010, Guy Barrand. All rights reserved. // See the file tools.license for terms. #ifndef tools_mpi_hmpi #define tools_mpi_hmpi // code to send, receive histos through MPI. #include #include #include #include #include #include #include #include "wrmpi" namespace tools { namespace mpi { class hmpi : public virtual tools::histo::hmpi { typedef tools::histo::hmpi parent; protected: typedef unsigned int num_t; static const std::string& s_class() { static const std::string s_v("tools::mpi::hmpi"); return s_v; } public: virtual bool pack(const tools::histo::h1d& a_h) { if(!m_wrmpi.spack(a_h.s_cls())) return false; if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false; return true; } virtual bool pack(const tools::histo::h2d& a_h) { if(!m_wrmpi.spack(a_h.s_cls())) return false; if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false; return true; } virtual bool pack(const tools::histo::h3d& a_h) { if(!m_wrmpi.spack(a_h.s_cls())) return false; if(!histo_data_duiuid_pack(m_wrmpi,a_h.dac())) return false; return true; } virtual bool pack(const tools::histo::p1d& a_h) { if(!m_wrmpi.spack(a_h.s_cls())) return false; if(!profile_data_duiuidd_pack(m_wrmpi,a_h.get_histo_data())) return false; return true; } virtual bool pack(const tools::histo::p2d& a_h) { if(!m_wrmpi.spack(a_h.s_cls())) return false; if(!profile_data_duiuidd_pack(m_wrmpi,a_h.get_histo_data())) return false; return true; } public: virtual bool beg_send(unsigned int a_nhist) { m_wrmpi.pack_reset(); return m_wrmpi.pack(a_nhist); } virtual bool send(int a_dest) { if(::MPI_Send(m_wrmpi.buffer(),m_wrmpi.ipos(),MPI_CHAR,a_dest,m_tag,m_comm)!=MPI_SUCCESS) { m_out << "tools::mpi::hmpi::send : rank " << m_rank << " : MPI_Send failed." << std::endl; return false; } m_wrmpi.pack_reset(); return true; } public: virtual bool wait_histos(int a_src,std::vector< std::pair >& a_hists) { a_hists.clear(); typedef std::pair class_pointer; MPI_Status status; if(::MPI_Probe(a_src,m_tag,m_comm,&status)!=MPI_SUCCESS) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Probe : failed." << std::endl; return false; } int buffer_size = 0; if(::MPI_Get_count(&status,MPI_CHAR,&buffer_size)!=MPI_SUCCESS) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Get_count : failed." << std::endl; return false; } if(!buffer_size) { m_out << "exlb::mpi::wait_histos : MPI_Get_count returns zero data." << std::endl; return false; } if(m_verbose) m_out << "rank " << m_rank << " : get_count " << buffer_size << std::endl; char* buffer = new char[buffer_size]; if(!buffer) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : can't alloc buffer of size " << buffer_size << std::endl; return false; } if(::MPI_Recv(buffer,buffer_size,MPI_CHAR,a_src,m_tag,m_comm,&status)!=MPI_SUCCESS) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : MPI_Recv : failed." << std::endl; delete [] buffer; return false; } if(m_verbose) m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : unpack data ..." << std::endl; wrmpi _mpi(m_out,m_comm,buffer_size,buffer); //give ownership of buffer to _mpi. num_t nhist; if(!_mpi.unpack(nhist)) return false; if(m_verbose) m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : number of histos to unpack " << nhist << std::endl; {for(num_t ihist=0;ihist hdata; if(!histo_data_duiuid_unpack(_mpi,hdata)) return false; tools::histo::h1d* h = new tools::histo::h1d("",10,0,1); h->copy_from_data(hdata); if(m_verbose) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : got a " << scls << ", title " << h->title() << ", mean_x " << h->mean() << ", rms " << h->rms() << std::endl; } a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h. } else if(scls==tools::histo::h2d::s_class()) { tools::histo::histo_data hdata; if(!histo_data_duiuid_unpack(_mpi,hdata)) return false; tools::histo::h2d* h = new tools::histo::h2d("",10,0,1,10,0,1); h->copy_from_data(hdata); if(m_verbose) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : got a " << scls << ", title " << h->title() << ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x() << ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y() << std::endl; } a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h. } else if(scls==tools::histo::h3d::s_class()) { tools::histo::histo_data hdata; if(!histo_data_duiuid_unpack(_mpi,hdata)) return false; tools::histo::h3d* h = new tools::histo::h3d("",10,0,1,10,0,1,10,0,1); h->copy_from_data(hdata); if(m_verbose) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : got a " << scls << ", title " << h->title() << ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x() << ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y() << ", mean_z " << h->mean_z() << ", rms_z " << h->rms_z() << std::endl; } a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h. } else if(scls==tools::histo::p1d::s_class()) { tools::histo::profile_data pdata; if(!profile_data_duiuidd_unpack(_mpi,pdata)) return false; tools::histo::p1d* h = new tools::histo::p1d("",10,0,1); h->copy_from_data(pdata); if(m_verbose) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : got a " << scls << ", title " << h->title() << ", mean_x " << h->mean() << ", rms " << h->rms() << std::endl; } a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h. } else if(scls==tools::histo::p2d::s_class()) { tools::histo::profile_data pdata; if(!profile_data_duiuidd_unpack(_mpi,pdata)) return false; tools::histo::p2d* h = new tools::histo::p2d("",10,0,1,10,0,1); h->copy_from_data(pdata); if(m_verbose) { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : got a " << scls << ", title " << h->title() << ", mean_x " << h->mean_x() << ", rms_x " << h->rms_x() << ", mean_y " << h->mean_y() << ", rms_y " << h->rms_y() << std::endl; } a_hists.push_back(class_pointer(h->s_cls(),h)); //give ownership of h. } else { m_out << "tools::mpi::hmpi::wait_histos : rank " << m_rank << " : got not treated class " << scls << std::endl; } }} //ihist return true; } public: virtual int rank() const { return m_rank;} virtual bool comm_rank(int& a_rank) const { if(::MPI_Comm_rank(m_comm,&a_rank)!=MPI_SUCCESS) {a_rank=-1;return false;} return true; } virtual bool comm_size(int& a_size) const { if(::MPI_Comm_size(m_comm,&a_size)!=MPI_SUCCESS) {a_size=0;return false;} return true; } public: hmpi(std::ostream& a_out,int a_rank,int a_tag,const MPI_Comm& a_comm,bool a_verbose = false) :m_out(a_out) ,m_rank(a_rank) ,m_tag(a_tag) ,m_comm(a_comm) ,m_verbose(a_verbose) ,m_wrmpi(a_out,a_comm) { #ifdef TOOLS_MEM tools::mem::increment(s_class().c_str()); #endif } virtual ~hmpi(){ #ifdef TOOLS_MEM tools::mem::decrement(s_class().c_str()); #endif } protected: hmpi(const hmpi& a_from) :parent(a_from) ,m_out(a_from.m_out) ,m_rank(a_from.m_rank) ,m_tag(a_from.m_tag) ,m_comm(a_from.m_comm) ,m_verbose(a_from.m_verbose) ,m_wrmpi(a_from.m_out,a_from.m_comm) { #ifdef TOOLS_MEM tools::mem::increment(s_class().c_str()); #endif } hmpi& operator=(const hmpi& a_from){ m_rank = a_from.m_rank; m_tag = a_from.m_tag; m_verbose = a_from.m_verbose; return *this; } protected: std::ostream& m_out; int m_rank; int m_tag; const MPI_Comm& m_comm; bool m_verbose; wrmpi m_wrmpi; }; }} #endif