source: XIOS3/trunk/src/transport/context_client.cpp @ 2556

Last change on this file since 2556 was 2556, checked in by ymipsl, 10 months ago

First version on the point to point transport protocol, activated by the variable : transport_protocol="p2p"

YM

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 6.2 KB
Line 
1#include "xios_spl.hpp"
2#include "context_client.hpp"
3#include "context_server.hpp"
4#include "event_client.hpp"
5#include "buffer_out.hpp"
6#include "buffer_client.hpp"
7#include "type.hpp"
8#include "event_client.hpp"
9#include "context.hpp"
10#include "mpi.hpp"
11#include "timer.hpp"
12#include "cxios.hpp"
13#include "server.hpp"
14#include "services.hpp"
15#include <boost/functional/hash.hpp>
16#include <random>
17#include <chrono>
18#include "one_sided_context_client.hpp"
19#include "p2p_context_client.hpp"
20#include "legacy_context_client.hpp"
21#include "online_context_client.hpp"
22
23
24namespace xios
25{
26    /*!
27    \param [in] parent Pointer to context on client side
28    \param [in] intraComm_ communicator of group client
29    \param [in] interComm_ communicator of group server
30    \cxtSer [in] cxtSer Pointer to context of server side. (It is only used in case of attached mode).
31    */
32    CContextClient::CContextClient(CContext* parent, MPI_Comm intraComm_, MPI_Comm interComm_, CContext* cxtSer)
33     : parentServer(cxtSer),  associatedServer_(nullptr)
34    {
35     
36      context_ = parent;
37      intraComm = intraComm_;
38      interComm = interComm_;
39      MPI_Comm_rank(intraComm, &clientRank);
40      MPI_Comm_size(intraComm, &clientSize);
41
42      int flag;     
43      MPI_Comm_test_inter(interComm, &flag);
44      if (flag) MPI_Comm_remote_size(interComm, &serverSize);
45      else  MPI_Comm_size(interComm, &serverSize);
46     
47      computeLeader(clientRank, clientSize, serverSize, ranksServerLeader, ranksServerNotLeader);
48
49      auto time=chrono::system_clock::now().time_since_epoch().count() ;
50      std::default_random_engine rd(time); // not reproducible from a run to another
51      std::uniform_int_distribution<size_t> dist;
52      hashId_=dist(rd) ;
53      MPI_Bcast(&hashId_,1,MPI_SIZE_T,0,intraComm) ; // Bcast to all server of the context
54
55    }
56
57    template<>
58    CContextClient* CContextClient::getNew<CContextClient::generic>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
59    { 
60      string defaultProtocol = CXios::getin<string>("transport_protocol", "default") ;
61      if (defaultProtocol=="one_sided") return getNew<CContextClient::oneSided>(parent, intraComm, interComm) ;
62      else if  (defaultProtocol=="p2p") return getNew<CContextClient::p2p>(parent, intraComm, interComm) ;
63      else if  (defaultProtocol=="legacy") return getNew<CContextClient::legacy>(parent, intraComm, interComm) ;
64      else if  (defaultProtocol=="online") return getNew<CContextClient::online>(parent, intraComm, interComm) ;
65      else if  (defaultProtocol=="default") return getNew<CContextClient::legacy>(parent, intraComm, interComm) ;
66      else ERROR("CContextClient* CContextClient::getNew<CContextClient::generic>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)",
67                <<"Protocol name <"<<defaultProtocol<<"> is undefined,  must be <default>, <one_sided> or <legacy>" ) ; 
68    }
69
70    template<>
71    CContextClient* CContextClient::getNew<CContextClient::oneSided>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
72    { 
73      return new COneSidedContextClient(parent, intraComm, interComm, parentServer); 
74    }
75
76    template<>
77    CContextClient* CContextClient::getNew<CContextClient::p2p>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
78    { 
79      return new CP2pContextClient(parent, intraComm, interComm, parentServer); 
80    }
81
82    template<>
83    CContextClient* CContextClient::getNew<CContextClient::legacy>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
84    { 
85      return new CLegacyContextClient(parent, intraComm, interComm, parentServer); 
86    }
87
88    template<>
89    CContextClient* CContextClient::getNew<CContextClient::online>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
90    { 
91      return new COnlineContextClient(parent, intraComm, interComm, parentServer); 
92    }
93
94    void CContextClient::computeLeader(int clientRank, int clientSize, int serverSize,
95                                       std::list<int>& rankRecvLeader,
96                                       std::list<int>& rankRecvNotLeader)
97    {
98      if ((0 == clientSize) || (0 == serverSize)) return;
99
100      if (clientSize < serverSize)
101      {
102        int serverByClient = serverSize / clientSize;
103        int remain = serverSize % clientSize;
104        int rankStart = serverByClient * clientRank;
105
106        if (clientRank < remain)
107        {
108          serverByClient++;
109          rankStart += clientRank;
110        }
111        else
112          rankStart += remain;
113
114        for (int i = 0; i < serverByClient; i++)
115          rankRecvLeader.push_back(rankStart + i);
116
117        rankRecvNotLeader.resize(0);
118      }
119      else
120      {
121        int clientByServer = clientSize / serverSize;
122        int remain = clientSize % serverSize;
123
124        if (clientRank < (clientByServer + 1) * remain)
125        {
126          if (clientRank % (clientByServer + 1) == 0)
127            rankRecvLeader.push_back(clientRank / (clientByServer + 1));
128          else
129            rankRecvNotLeader.push_back(clientRank / (clientByServer + 1));
130        }
131        else
132        {
133          int rank = clientRank - (clientByServer + 1) * remain;
134          if (rank % clientByServer == 0)
135            rankRecvLeader.push_back(remain + rank / clientByServer);
136          else
137            rankRecvNotLeader.push_back(remain + rank / clientByServer);
138        }
139      }
140    }
141
142  /*!
143  Get leading server in the group of connected server
144  \return ranks of leading servers
145  */
146  const std::list<int>& CContextClient::getRanksServerNotLeader(void) const
147  {
148    return ranksServerNotLeader;
149  }
150
151  /*!
152  Check if client connects to leading server
153  \return connected(true), not connected (false)
154  */
155  bool CContextClient::isServerNotLeader(void) const
156  {
157    return !ranksServerNotLeader.empty();
158  }
159
160  /*!
161  Get leading server in the group of connected server
162  \return ranks of leading servers
163  */
164  const std::list<int>& CContextClient::getRanksServerLeader(void) const
165  {
166    return ranksServerLeader;
167  }
168
169  /*!
170  Check if client connects to leading server
171  \return connected(true), not connected (false)
172  */
173  bool CContextClient::isServerLeader(void) const
174  {
175    return !ranksServerLeader.empty();
176  }
177
178
179
180}
Note: See TracBrowser for help on using the repository browser.