source: XIOS3/branches/xios-3.0-beta/src/transport/context_client.cpp @ 2527

Last change on this file since 2527 was 2343, checked in by ymipsl, 2 years ago
  • Implement new infrastructure for transfert protocol.
  • new purelly one sided protocol is now available, the previous protocol (legacy, mix send/recv and one sided) is still available. Other specific protocol could be implemented more easilly in future.
  • switch can be operate with "transport_protocol" variable in XIOS context :

ex:
<variable id="transport_protocol" type="string">one_sided</variable>

Available protocols are : one_sided, legacy or default. The default protocol is "legacy".

YM

  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 5.5 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 "legacy_context_client.hpp"
20
21namespace xios
22{
23    /*!
24    \param [in] parent Pointer to context on client side
25    \param [in] intraComm_ communicator of group client
26    \param [in] interComm_ communicator of group server
27    \cxtSer [in] cxtSer Pointer to context of server side. (It is only used in case of attached mode).
28    */
29    CContextClient::CContextClient(CContext* parent, MPI_Comm intraComm_, MPI_Comm interComm_, CContext* cxtSer)
30     : parentServer(cxtSer),  associatedServer_(nullptr)
31    {
32     
33      context_ = parent;
34      intraComm = intraComm_;
35      interComm = interComm_;
36      MPI_Comm_rank(intraComm, &clientRank);
37      MPI_Comm_size(intraComm, &clientSize);
38
39      int flag;
40      MPI_Comm_test_inter(interComm, &flag);
41      if (flag) isAttached_=false ;
42      else  isAttached_=true ;
43
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=="legacy") return getNew<CContextClient::legacy>(parent, intraComm, interComm) ;
63      else if  (defaultProtocol=="default") return getNew<CContextClient::legacy>(parent, intraComm, interComm) ;
64      else ERROR("CContextClient* CContextClient::getNew<CContextClient::generic>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)",
65                <<"Protocol name <"<<defaultProtocol<<"> is undefined,  must be <default>, <one_sided> or <legacy>" ) ; 
66    }
67
68    template<>
69    CContextClient* CContextClient::getNew<CContextClient::oneSided>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
70    { 
71      return new COneSidedContextClient(parent, intraComm, interComm, parentServer); 
72    }
73
74    template<>
75    CContextClient* CContextClient::getNew<CContextClient::legacy>(CContext* parent, MPI_Comm intraComm, MPI_Comm interComm, CContext* parentServer)
76    { 
77      return new CLegacyContextClient(parent, intraComm, interComm, parentServer); 
78    }
79
80    void CContextClient::computeLeader(int clientRank, int clientSize, int serverSize,
81                                       std::list<int>& rankRecvLeader,
82                                       std::list<int>& rankRecvNotLeader)
83    {
84      if ((0 == clientSize) || (0 == serverSize)) return;
85
86      if (clientSize < serverSize)
87      {
88        int serverByClient = serverSize / clientSize;
89        int remain = serverSize % clientSize;
90        int rankStart = serverByClient * clientRank;
91
92        if (clientRank < remain)
93        {
94          serverByClient++;
95          rankStart += clientRank;
96        }
97        else
98          rankStart += remain;
99
100        for (int i = 0; i < serverByClient; i++)
101          rankRecvLeader.push_back(rankStart + i);
102
103        rankRecvNotLeader.resize(0);
104      }
105      else
106      {
107        int clientByServer = clientSize / serverSize;
108        int remain = clientSize % serverSize;
109
110        if (clientRank < (clientByServer + 1) * remain)
111        {
112          if (clientRank % (clientByServer + 1) == 0)
113            rankRecvLeader.push_back(clientRank / (clientByServer + 1));
114          else
115            rankRecvNotLeader.push_back(clientRank / (clientByServer + 1));
116        }
117        else
118        {
119          int rank = clientRank - (clientByServer + 1) * remain;
120          if (rank % clientByServer == 0)
121            rankRecvLeader.push_back(remain + rank / clientByServer);
122          else
123            rankRecvNotLeader.push_back(remain + rank / clientByServer);
124        }
125      }
126    }
127
128  /*!
129  Get leading server in the group of connected server
130  \return ranks of leading servers
131  */
132  const std::list<int>& CContextClient::getRanksServerNotLeader(void) const
133  {
134    return ranksServerNotLeader;
135  }
136
137  /*!
138  Check if client connects to leading server
139  \return connected(true), not connected (false)
140  */
141  bool CContextClient::isServerNotLeader(void) const
142  {
143    return !ranksServerNotLeader.empty();
144  }
145
146  /*!
147  Get leading server in the group of connected server
148  \return ranks of leading servers
149  */
150  const std::list<int>& CContextClient::getRanksServerLeader(void) const
151  {
152    return ranksServerLeader;
153  }
154
155  /*!
156  Check if client connects to leading server
157  \return connected(true), not connected (false)
158  */
159  bool CContextClient::isServerLeader(void) const
160  {
161    return !ranksServerLeader.empty();
162  }
163
164
165
166}
Note: See TracBrowser for help on using the repository browser.