Ignore:
Timestamp:
04/20/21 09:49:47 (3 years ago)
Author:
ymipsl
Message:

New management of client-server buffers.

  • buffers can grow automatically in intialization phase
  • buffers is evaluated after the close context definition phase and fixed at optimal value.

YM

Location:
XIOS/dev/dev_ym/XIOS_COUPLING/src/node
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.cpp

    r2124 r2130  
    292292 
    293293 
    294    void CContext::setClientServerBuffer(vector<CField*>& fields, bool bufferForWriting) 
    295    TRY 
    296    { 
    297       // Estimated minimum event size for small events (20 is an arbitrary constant just for safety) 
    298      const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int); 
    299       // Ensure there is at least some room for 20 of such events in the buffers 
    300      size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize); 
    301  
    302 #define DECLARE_NODE(Name_, name_)    \ 
    303      if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition); 
    304 #define DECLARE_NODE_PAR(Name_, name_) 
    305 #include "node_type.conf" 
    306 #undef DECLARE_NODE 
    307 #undef DECLARE_NODE_PAR 
    308  
    309  
    310      map<CContextClient*,map<int,size_t>> dataSize ; 
    311      map<CContextClient*,map<int,size_t>> maxEventSize ; 
    312      map<CContextClient*,map<int,size_t>> attributesSize ;   
    313  
    314      for(auto field : fields) 
    315      { 
    316        field->setContextClientDataBufferSize(dataSize, maxEventSize, bufferForWriting) ; 
    317        field->setContextClientAttributesBufferSize(attributesSize, maxEventSize, bufferForWriting) ; 
    318      } 
    319       
    320  
    321      for(auto& it : attributesSize) 
    322      { 
    323        auto contextClient = it.first ; 
    324        auto& contextDataSize =  dataSize[contextClient] ; 
    325        auto& contextAttributesSize =  attributesSize[contextClient] ; 
    326        auto& contextMaxEventSize =  maxEventSize[contextClient] ; 
    327     
    328        for (auto& it : contextAttributesSize) 
    329        { 
    330          auto serverRank=it.first ; 
    331          auto& buffer = contextAttributesSize[serverRank] ; 
    332          if (contextDataSize[serverRank] > buffer) buffer=contextDataSize[serverRank] ; 
    333          buffer *= CXios::bufferSizeFactor; 
    334          if (buffer < minBufferSize) buffer = minBufferSize; 
    335          if (buffer > CXios::maxBufferSize ) buffer = CXios::maxBufferSize; 
    336        } 
    337  
    338        // Leaders will have to send some control events so ensure there is some room for those in the buffers 
    339        if (contextClient->isServerLeader()) 
    340          for(auto& rank : contextClient->getRanksServerLeader()) 
    341            if (!contextAttributesSize.count(rank)) 
    342            { 
    343              contextAttributesSize[rank] = minBufferSize; 
    344              contextMaxEventSize[rank] = minEventSize; 
    345            } 
    346        
    347        contextClient->setBufferSize(contextAttributesSize, contextMaxEventSize);     
    348      } 
    349    } 
    350    CATCH_DUMP_ATTR 
    351  
    352  
    353     /*! 
    354     Sets client buffers. 
    355     \param [in] contextClient 
    356     \param [in] bufferForWriting True if buffers are used for sending data for writing 
    357     This flag is only true for client and server-1 for communication with server-2 
    358   */ 
    359   // ym obsolete to be removed 
    360    void CContext::setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting) 
    361    TRY 
    362    { 
    363       // Estimated minimum event size for small events (20 is an arbitrary constant just for safety) 
    364      const size_t minEventSize = CEventClient::headerSize + 20 * sizeof(int); 
    365  
    366       // Ensure there is at least some room for 20 of such events in the buffers 
    367       size_t minBufferSize = std::max(CXios::minBufferSize, 20 * minEventSize); 
    368  
    369 #define DECLARE_NODE(Name_, name_)    \ 
    370      if (minBufferSize < sizeof(C##Name_##Definition)) minBufferSize = sizeof(C##Name_##Definition); 
    371 #define DECLARE_NODE_PAR(Name_, name_) 
    372 #include "node_type.conf" 
    373 #undef DECLARE_NODE 
    374 #undef DECLARE_NODE_PAR 
    375  
    376      // Compute the buffer sizes needed to send the attributes and data corresponding to fields 
    377      std::map<int, StdSize> maxEventSize; 
    378      std::map<int, StdSize> bufferSize = getAttributesBufferSize(maxEventSize, contextClient, bufferForWriting); 
    379      std::map<int, StdSize> dataBufferSize = getDataBufferSize(maxEventSize, contextClient, bufferForWriting); 
    380  
    381      std::map<int, StdSize>::iterator it, ite = dataBufferSize.end(); 
    382      for (it = dataBufferSize.begin(); it != ite; ++it) 
    383        if (it->second > bufferSize[it->first]) bufferSize[it->first] = it->second; 
    384  
    385      // Apply the buffer size factor, check that we are above the minimum buffer size and below the maximum size 
    386      ite = bufferSize.end(); 
    387      for (it = bufferSize.begin(); it != ite; ++it) 
    388      { 
    389        it->second *= CXios::bufferSizeFactor; 
    390        if (it->second < minBufferSize) it->second = minBufferSize; 
    391        if (it->second > CXios::maxBufferSize) it->second = CXios::maxBufferSize; 
    392      } 
    393  
    394      // Leaders will have to send some control events so ensure there is some room for those in the buffers 
    395      if (contextClient->isServerLeader()) 
    396      { 
    397        const std::list<int>& ranks = contextClient->getRanksServerLeader(); 
    398        for (std::list<int>::const_iterator itRank = ranks.begin(), itRankEnd = ranks.end(); itRank != itRankEnd; ++itRank) 
    399        { 
    400          if (!bufferSize.count(*itRank)) 
    401          { 
    402            bufferSize[*itRank] = minBufferSize; 
    403            maxEventSize[*itRank] = minEventSize; 
    404          } 
    405        } 
    406      } 
    407      contextClient->setBufferSize(bufferSize, maxEventSize); 
    408    } 
    409    CATCH_DUMP_ATTR 
    410  
    411294 /*! 
    412295    * Compute the required buffer size to send the fields data. 
     
    716599  CATCH_DUMP_ATTR 
    717600 
     601  void CContext::globalEventLoop(void) 
     602  { 
     603    lockContext() ; 
     604    CXios::getDaemonsManager()->eventLoop() ; 
     605    unlockContext() ; 
     606    setCurrent(getId()) ; 
     607  } 
     608 
    718609  bool CContext::scheduledEventLoop(bool enableEventsProcessing)  
    719610  { 
     
    739630  { 
    740631    bool  finished;  
     632    if (isLockedContext()) return ; 
     633     
    741634    setCurrent(getId()) ; 
    742635 
     
    792685        couplerOutClient_[fullContextId] = client ; 
    793686        couplerOutServer_[fullContextId] = server ; 
    794  
    795 /* 
    796       // for now, we don't now which beffer size must be used for client coupler 
    797       // It will be evaluated later. Fix a constant size for now... 
    798       // set to 10Mb for development 
    799        map<int,size_t> bufferSize, maxEventSize ; 
    800        for(int i=0;i<client->getRemoteSize();i++) 
    801        { 
    802          bufferSize[i]=10000000 ; 
    803          maxEventSize[i]=10000000 ; 
    804        } 
    805  
    806        client->setBufferSize(bufferSize, maxEventSize);     
    807 */ 
    808687      } 
    809688    } 
     
    827706       MPI_Comm_free(&interComm) ; 
    828707 
    829        map<int,size_t> bufferSize, maxEventSize ; 
    830        for(int i=0;i<client->getRemoteSize();i++) 
    831        { 
    832          bufferSize[i]=10000000 ; 
    833          maxEventSize[i]=10000000 ; 
    834        } 
    835  
    836        client->setBufferSize(bufferSize, maxEventSize);     
    837708       couplerInClient_[fullContextId] = client ; 
    838709       couplerInServer_[fullContextId] = server ;         
     
    840711  } 
    841712   
    842   void CContext::globalEventLoop(void) 
    843   { 
    844     CXios::getDaemonsManager()->eventLoop() ; 
    845     setCurrent(getId()) ; 
    846   } 
    847  
    848  
    849713   void CContext::finalize(void) 
    850714   TRY 
     
    1054918        // connect to couplerOut -> to do 
    1055919      } 
    1056       if (first) setClientServerBuffer(couplerOutField, true) ; // set buffer context --> to check 
    1057920 
    1058921      bool couplersReady ; 
     
    1099962        field->connectToFileServer(garbageCollector) ; // connect the field to server filter 
    1100963      } 
    1101       setClientServerBuffer(fileOutField, true) ; // set buffer context --> to review 
    1102964      for(auto field : fileOutField) field->sendFieldToFileServer() ; 
    1103965    } 
     
    12071069      this->scheduledEventLoop() ; 
    12081070    } while (!ok) ; 
     1071 
     1072    // Now evaluate the size of the context client buffers 
     1073    map<CContextClient*,map<int,size_t>> fieldBufferEvaluation ; 
     1074    for(auto field : fileOutField) field->evaluateBufferSize(fieldBufferEvaluation, CXios::isOptPerformance) ; // output to server 
     1075    for(auto field : couplerOutField) field->evaluateBufferSize(fieldBufferEvaluation, CXios::isOptPerformance) ; // output to coupler 
     1076    for(auto field : fieldModelIn) field->evaluateBufferSize(fieldBufferEvaluation, CXios::isOptPerformance) ; // server to client (for io servers) 
     1077     
     1078    // fix size for each context client 
     1079    for(auto& it : fieldBufferEvaluation) it.first->setBufferSize(it.second) ; 
     1080 
    12091081 
    12101082     CTimer::get("Context : close definition").suspend() ; 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/context.hpp

    r2123 r2130  
    150150         std::map<int, StdSize> getAttributesBufferSize(std::map<int, StdSize>& maxEventSize, CContextClient* contextClient, bool bufferForWriting = false); 
    151151         std::map<int, StdSize> getDataBufferSize(std::map<int, StdSize>& maxEventSize, CContextClient* contextClient, bool bufferForWriting = false); 
    152          void setClientServerBuffer(CContextClient* contextClient, bool bufferForWriting = false); // old interface to be removed 
    153          void setClientServerBuffer(vector<CField*>& fields, bool bufferForWriting) ;  
    154152 
    155153         // Distribute files (in write mode) among secondary-server pools according to the estimated data flux 
     
    357355         string contextId_ ; //!< context client id for the servers. For clients this is same as getId()  
    358356         bool isProcessingEvent_ ; 
     357    private:      
    359358         CServerContext* parentServerContext_ ; 
    360  
     359    public: 
     360         CServerContext* getParentServerContext(void) { return parentServerContext_; } 
     361    private:  
     362      bool lockedContext_=false; 
     363    public:  
     364        void lockContext(void) {lockedContext_=true; } 
     365        void unlockContext(void) {lockedContext_=true; } 
     366        bool isLockedContext(void) { return lockedContext_;} 
    361367      public: // Some function maybe removed in the near future 
    362368        // virtual void toBinary  (StdOStream & os) const; 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/field.cpp

    r2022 r2130  
    497497  CATCH_DUMP_ATTR 
    498498 
     499  bool CField::evaluateBufferSize(map<CContextClient*,map<int,size_t>>& evaluateBuffer, bool isOptPerformance) 
     500  { 
     501    CContextClient* client=nullptr ; 
     502 
     503    for(int i=0;i<2;i++) 
     504    { 
     505      map<int,int> dataSize ; 
     506      if (i==0  && clientToServerStoreFilter_) client = clientToServerStoreFilter_-> getTransferedDataSize(dataSize) ; 
     507      if (i==1  && serverToClientStoreFilter_) client = serverToClientStoreFilter_-> getTransferedDataSize(dataSize) ; 
     508 
     509      if (client!=nullptr) 
     510      { 
     511        map<int,size_t> bufferSize ; 
     512    
     513        if (evaluateBuffer.count(client)!=0) bufferSize = evaluateBuffer[client] ; 
     514        if (isOptPerformance) 
     515        { 
     516          for(auto& it : dataSize)  
     517          { 
     518            if (bufferSize.count(it.first)==0) bufferSize[it.first]=it.second ; 
     519            else bufferSize[it.first]+=it.second ; 
     520          } 
     521        } 
     522        else 
     523        { 
     524          for(auto& it : dataSize)  
     525          { 
     526            if (bufferSize.count(it.first)==0) bufferSize[it.first]=it.second ; 
     527            else bufferSize[it.first]=std::max(bufferSize[it.first],(size_t)it.second) ; 
     528          } 
     529        } 
     530        evaluateBuffer[client] = bufferSize ; 
     531        client=nullptr ; 
     532      } 
     533    } 
     534    if (client==nullptr) return false ; 
     535    else return true; 
     536  }   
    499537 
    500538 
  • XIOS/dev/dev_ym/XIOS_COUPLING/src/node/field.hpp

    r2022 r2130  
    110110         // Grid data buffer size for each connection of contextclient 
    111111         std::map<int, StdSize> getGridDataBufferSize(CContextClient* client, bool bufferForWriting = false); 
    112  
     112          
     113         // evaluation the size of the buffer for the field 
     114         bool evaluateBufferSize(map<CContextClient*,map<int,size_t>>& evaluateBuffer, bool isOptPerformance) ; 
    113115       public: 
    114116          void makeGridAliasForCoupling(void) ; 
Note: See TracChangeset for help on using the changeset viewer.