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

Last change on this file since 2547 was 2547, checked in by ymipsl, 9 months ago

Major update :

  • New method to lock and unlock one-sided windows (window_dynamic) to avoid network overhead
  • Introducing multithreading on server sided to manage more efficiently dead-lock occuring (similar to co-routine which will be available and implemented in futur c++ standard), based on c++ threads
  • Suprression of old "attached mode" which is replaced by online writer and reder filters

YM

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