1 // Copyright (C) 2006-2017 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "PlayGround.hxx"
21 #include "Runtime.hxx"
30 using namespace YACS::ENGINE;
32 std::string PlayGround::printSelf() const
34 std::ostringstream oss;
36 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
37 sz=std::max(sz,(*it).first.length());
38 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
40 oss << " - " << std::setw(10) << (*it).first << " : " << (*it).second << std::endl;
45 void PlayGround::loadFromKernelCatalog()
47 Runtime *r(getRuntime());
49 throw Exception("PlayGround::loadFromKernelCatalog : no runtime !");
50 std::vector< std::pair<std::string,int> > data(r->getCatalogOfComputeNodes());
54 void PlayGround::setData(const std::vector< std::pair<std::string,int> >& defOfRes)
60 int PlayGround::getNumberOfCoresAvailable() const
63 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
68 int PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap(int nbCoresPerCont) const
71 throw Exception("PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap : invalid nbCoresPerCont. Must be >=1 !");
73 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
74 ret+=(*it).second/nbCoresPerCont;
78 std::vector<int> PlayGround::computeOffsets() const
80 std::size_t sz(_data.size()),i(0);
81 std::vector<int> ret(sz+1); ret[0]=0;
82 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++,i++)
83 ret[i+1]=ret[i]+(*it).second;
87 void PlayGround::checkCoherentInfo() const
89 std::set<std::string> s;
90 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
92 s.insert((*it).first);
94 throw Exception("Presence of negative int value !");
96 if(s.size()!=_data.size())
97 throw Exception("host names entries must be different each other !");
100 std::vector<bool> PlayGround::FromUItoVB(unsigned int sz, unsigned int v)
102 std::vector<bool> ret(sz);
104 for(std::size_t i=0;i<sz;i++)
112 unsigned int PlayGround::FromVBtoUI(const std::vector<bool>& v)
114 std::size_t sz(v.size());
116 for(std::size_t i=0;i<sz;i++)
124 std::vector<int> PlayGround::GetIdsMatching(const std::vector<bool>& bigArr, const std::vector<bool>& pat)
126 std::vector<int> ret;
127 std::size_t szp(pat.size());
128 std::size_t sz(bigArr.size()/szp);
129 for(std::size_t i=0;i<sz;i++)
131 std::vector<bool> t(bigArr.begin()+i*szp,bigArr.begin()+(i+1)*szp);
138 std::vector<int> PlayGround::BuildVectOfIdsFromVecBool(const std::vector<bool>& v)
140 std::size_t sz(std::count(v.begin(),v.end(),true)),i(0);
141 std::vector<int> ret(sz);
142 std::vector<bool>::const_iterator it(v.begin());
145 it=std::find(it,v.end(),true);
146 ret[i++]=std::distance(v.begin(),it);
152 void PlayGround::highlightOnIds(const std::vector<int>& coreIds, std::vector<bool>& v) const
154 if(v.size()!=getNumberOfCoresAvailable())
155 throw Exception("PlayGround::highlightOnIds : oops ! invalid size !");
156 for(std::vector<int>::const_iterator it=coreIds.begin();it!=coreIds.end();it++)
161 * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
163 std::vector<bool> PlayGround::getFetchedCores(int nbCoresPerWorker) const
165 int nbCores(getNumberOfCoresAvailable());
166 std::vector<bool> ret(nbCores,false);
167 if(nbCoresPerWorker==1)
168 std::fill(ret.begin(),ret.end(),true);
171 std::size_t posBg(0);
172 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
174 int nbElemsToPutOn(((*it).second/nbCoresPerWorker)*nbCoresPerWorker);
175 std::fill(ret.begin()+posBg,ret.begin()+posBg+nbElemsToPutOn,true);
182 * follow getMaxNumberOfContainersCanBeHostedWithoutOverlap method
184 std::vector<std::size_t> PlayGround::getWorkerIdsFullyFetchedBy(int nbCoresPerComp, const std::vector<bool>& coreFlags) const
186 std::size_t posBg(0),posWorker(0);
187 std::vector<std::size_t> ret;
188 for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
190 int nbWorker((*it).second/nbCoresPerComp);
191 for(int j=0;j<nbWorker;j++,posWorker++)
193 std::vector<bool>::const_iterator it2(std::find(coreFlags.begin()+posBg+j*nbCoresPerComp,coreFlags.begin()+posBg+(j+1)*nbCoresPerComp,false));
194 if(it2==coreFlags.begin()+posBg+(j+1)*nbCoresPerComp)
195 ret.push_back(posWorker);
202 std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PlayGround::partition(const std::vector< std::pair<const PartDefinition *,double> >& parts) const
204 std::size_t sz(parts.size()),szs(getNumberOfCoresAvailable());
206 return std::vector< YACS::BASES::AutoRefCnt<PartDefinition> >();
209 const PartDefinition *pd(parts[0].first);
211 throw Exception("Presence of null pointer as part def 0 !");
212 YACS::BASES::AutoRefCnt<PartDefinition> ret(pd->copy());
213 std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret2(1,ret);
217 throw Exception("PlayGround::partition : not implemented yet for more than 31 ! You need to pay for it :)");
218 std::vector<bool> zeArr(szs*sz,false);
220 for(std::vector< std::pair<const PartDefinition *,double> >::const_iterator it=parts.begin();it!=parts.end();it++,i++)
222 const PartDefinition *pd((*it).first);
224 throw Exception("Presence of null pointer as part def !");
225 if(pd->getPlayGround()!=this)
226 throw Exception("Presence of non homogeneous playground !");
228 throw Exception("Invalid weight !");
229 std::vector<bool> bs(pd->getCoresOn());
230 for(std::size_t j=0;j<szs;j++)
233 std::set<unsigned int> ss;
234 for(std::size_t i=0;i<szs;i++)
236 std::vector<bool> vb(zeArr.begin()+i*sz,zeArr.begin()+(i+1)*sz);
237 ss.insert(FromVBtoUI(vb));
239 std::vector< std::vector<int> > retIds(sz);
240 for(std::set<unsigned int>::const_iterator i=ss.begin();i!=ss.end();i++)
242 std::vector<bool> code(FromUItoVB(sz,*i));// for this configuration which parts are considered
243 std::vector<int> locIds(GetIdsMatching(zeArr,code));
244 std::vector<int> partsIds(BuildVectOfIdsFromVecBool(code));
247 std::vector<double> wg;
248 std::vector<int> nbCores2;
249 for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++)
251 wg.push_back(parts[*it].second);
252 nbCores2.push_back(parts[*it].first->getNbCoresPerCompo());
254 std::vector< std::vector<int> > ress(splitIntoParts(locIds,nbCores2,wg));
256 for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++,k++)
258 retIds[*it].insert(retIds[*it].end(),ress[k].begin(),ress[k].end());
262 std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret(sz);
263 for(std::size_t i=0;i<sz;i++)
265 std::set<int> s(retIds[i].begin(),retIds[i].end());
266 std::vector<int> v(s.begin(),s.end());
267 ret[i]=PartDefinition::BuildFrom(this,(parts[i].first)->getNbCoresPerCompo(),v);
272 std::vector<int> sortArr(const std::vector<int>& v)
274 std::multimap<int,int> m;
276 for(std::vector<int>::const_reverse_iterator it=v.rbegin();it!=v.rend();it++)
277 m.insert(std::pair<int,int>(*it,i--));
278 std::vector<int> ret(m.size());
280 for(std::multimap<int,int>::const_reverse_iterator it=m.rbegin();it!=m.rend();it++)// reverse -> sort from biggest to the finest
281 ret[i++]=(*it).second;
285 std::vector< std::vector<int> > PlayGround::splitIntoParts(const std::vector<int>& coreIds, const std::vector<int>& nbCoresConso, const std::vector<double>& weights) const
287 double wgs(std::accumulate(weights.begin(),weights.end(),0.));
288 std::size_t sz(nbCoresConso.size());
289 if(sz!=weights.size())
290 throw Exception("PlayGround::splitIntoParts : internal error !");
292 return std::vector< std::vector<int> >();
293 int totalSpace(coreIds.size());
294 std::vector< std::vector<int> > ret(sz);
295 std::vector<int> fromBigToTiny(sortArr(nbCoresConso));// start to treat the coarse grain to finish with fine grain
296 std::vector<bool> zeArr(getNumberOfCoresAvailable(),false);
297 highlightOnIds(coreIds,zeArr);
298 int nbOfCoresToSplit(coreIds.size());
299 std::size_t ii(fromBigToTiny.size());
300 for(std::vector<int>::const_iterator it=fromBigToTiny.begin();it!=fromBigToTiny.end();it++,ii--)
302 int maxNbOfCores((int)(totalSpace*weights[*it]/wgs));// now try to find in zeArr at most maxNbOfCores cores
303 ret[*it]=takePlace(maxNbOfCores,nbCoresConso[*it],zeArr,ii==1);
308 std::vector<int> PlayGround::takePlace(int maxNbOfCoresToAlloc, int nbCoresPerShot, std::vector<bool>& distributionOfCores, bool lastOne) const
310 if(maxNbOfCoresToAlloc<1)
311 throw Exception("PlayGround::takePlace : internal error ! no space to alloc !");
312 int tmpMaxNbOfCoresToAlloc(maxNbOfCoresToAlloc);
314 tmpMaxNbOfCoresToAlloc=std::max(tmpMaxNbOfCoresToAlloc,(int)std::count(distributionOfCores.begin(),distributionOfCores.end(),true));
315 std::vector<int> ret;
316 std::vector<int> offsets(computeOffsets());
318 std::size_t sz(offsets.size()-1);
319 for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;i++)
321 int d(offsets[i+1]-offsets[i]);
324 std::vector<bool> target(nbCoresPerShot,true);
325 for(int j=0;j<=d-nbCoresPerShot && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;)
327 std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot);
331 tmpMaxNbOfCoresToAlloc-=nbCoresPerShot;
332 std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot,false);
333 for(int k=offsets[i]+j;k<offsets[i]+j+nbCoresPerShot;k++)
343 if(nbCoresPerShot<=1)
344 throw Exception("PlayGround::takePlace : internal error !");
345 // not enough contiguous place. Find the first wider contiguous place
346 for(int kk=std::min(nbCoresPerShot-1,tmpMaxNbOfCoresToAlloc);kk>=1;kk--)
348 for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=kk;i++)
350 int d(offsets[i+1]-offsets[i]);
353 std::vector<bool> target(kk,true);
354 for(int j=0;j<=d-kk && tmpMaxNbOfCoresToAlloc>=kk;)
356 std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk);
360 tmpMaxNbOfCoresToAlloc-=kk;
361 std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk,false);
362 for(int k=offsets[i]+j;k<offsets[i]+j+kk;k++)
371 throw Exception("PlayGround::takePlace : internal error ! All cores are occupied !");
374 int PlayGround::fromWorkerIdToResId(int workerId, int nbProcPerNode) const
376 std::size_t sz2(_data.size());
377 std::vector<int> deltas(sz2+1); deltas[0]=0;
378 for(std::size_t i=0;i<sz2;i++)
379 deltas[i+1]=deltas[i]+(_data[i].second)/nbProcPerNode;
381 while(zePos<sz2 && (workerId<deltas[zePos] || workerId>=deltas[zePos+1]))
389 * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
391 std::string PlayGround::deduceMachineFrom(int workerId, int nbProcPerNode) const
393 int zePos(fromWorkerIdToResId(workerId,nbProcPerNode));
394 return _data[zePos].first;
398 * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, PlayGround::getFetchedCores and PartDefinition::computeWorkerIdsCovered
400 int PlayGround::getNumberOfWorkers(int nbCoresPerWorker) const
402 return getMaxNumberOfContainersCanBeHostedWithoutOverlap(nbCoresPerWorker);
405 PlayGround::~PlayGround()
409 //////////////////////
411 PartDefinition::PartDefinition(const PlayGround *pg, int nbOfCoresPerComp):_nbOfCoresPerComp(nbOfCoresPerComp)
416 PartDefinition::PartDefinition(const PartDefinition& other):_pg(other._pg),_nbOfCoresPerComp(other._nbOfCoresPerComp)
420 PartDefinition::~PartDefinition()
424 std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PartDefinition::partition(const std::vector< double >& wgs) const
426 std::size_t sz(wgs.size());
427 std::vector< std::pair<const PartDefinition *,double> > elts(sz);
428 for(std::size_t i=0;i<sz;i++)
429 elts[i]=std::pair<const PartDefinition *,double>(this,wgs[i]);
430 return getPlayGround()->partition(elts);
433 YACS::BASES::AutoRefCnt<PartDefinition> PartDefinition::BuildFrom(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& coreIds)
435 int spaceSz(pg->getNumberOfCoresAvailable()),sz(coreIds.size());
437 throw Exception("PartDefinition::BuildFrom : error 1 !");
439 throw Exception("PartDefinition::BuildFrom : error 2 !");
440 int zeStart(coreIds.front()),zeEnd(coreIds.back());
441 if(zeStart<0 || zeEnd<zeStart)
442 throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK !");
443 for(std::size_t i=0;i<sz-1;i++)
444 if(coreIds[i+1]<coreIds[i])
445 throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK 2 !");
446 if(zeEnd-zeStart+1!=sz)
448 YACS::BASES::AutoRefCnt<PartDefinition> pd(new NonContigPartDefinition(pg,nbOfCoresPerComp,coreIds));
453 YACS::BASES::AutoRefCnt<PartDefinition> pd(new AllPartDefinition(pg,nbOfCoresPerComp));
456 YACS::BASES::AutoRefCnt<PartDefinition> pd(new ContigPartDefinition(pg,nbOfCoresPerComp,zeStart,zeEnd+1));
460 void PartDefinition::stashPart(int nbCoresStashed, double weightOfRemain, YACS::BASES::AutoRefCnt<PartDefinition>& pdStashed, YACS::BASES::AutoRefCnt<PartDefinition>& pdRemain) const
462 if(nbCoresStashed<=0)
463 throw Exception("stashPart : Invalid nbCoresStashed value !");
464 if(weightOfRemain<=0.)
465 throw Exception("stashPart : Invalid weight !");
466 std::vector<bool> coresOn(getCoresOn());
467 int nbCoresAvailable(std::count(coresOn.begin(),coresOn.end(),true));
468 std::vector<int> ids(PlayGround::BuildVectOfIdsFromVecBool(coresOn));
469 if(nbCoresAvailable==0)
470 throw Exception("PartDefinition::stashPart : no available cores !");
471 if(nbCoresAvailable<=nbCoresStashed)
473 int n0((int)(1./(1.+weightOfRemain)*nbCoresAvailable)); n0=std::max(n0,1);
474 int n1(nbCoresAvailable-n0);
477 pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids);
478 pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids);
482 std::vector<int> ids0(ids.begin(),ids.begin()+n0),ids1(ids.begin()+n0,ids.end());
483 pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids0);
484 pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids1);
489 std::vector<int> ids0(ids.begin(),ids.begin()+nbCoresStashed),ids1(ids.begin()+nbCoresStashed,ids.end());
490 pdStashed=PartDefinition::BuildFrom(getPlayGround(),1,ids0);
491 pdRemain=PartDefinition::BuildFrom(getPlayGround(),1,ids1);
496 * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
498 std::vector<std::size_t> PartDefinition::computeWorkerIdsCovered(int nbCoresPerComp) const
500 std::vector<bool> coresOn(getCoresOn());
501 return _pg->getWorkerIdsFullyFetchedBy(nbCoresPerComp,coresOn);
504 //////////////////////
506 ContigPartDefinition::ContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, int zeStart, int zeStop):PartDefinition(pg,nbOfCoresPerComp),_start(zeStart),_stop(zeStop)
508 if(_start<0 || _stop<_start || _stop>getSpaceSize())
509 throw Exception("ContigPartDefinition constructor : Invalid input values");
512 ContigPartDefinition::ContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other),_start(other._start),_stop(other._stop)
516 std::string ContigPartDefinition::printSelf() const
518 std::ostringstream oss;
519 oss << "Contiguous : start=" << _start << " stop=" << _stop;
523 std::vector<bool> ContigPartDefinition::getCoresOn() const
525 std::vector<bool> ret(getSpaceSize(),false);
526 for(int i=_start;i<_stop;i++)
531 ContigPartDefinition *ContigPartDefinition::copy() const
533 return new ContigPartDefinition(*this);
536 int ContigPartDefinition::getNumberOfCoresConsumed() const
541 //////////////////////
543 NonContigPartDefinition::NonContigPartDefinition(const PlayGround *pg, int nbOfCoresPerComp, const std::vector<int>& ids):PartDefinition(pg,nbOfCoresPerComp),_ids(ids)
548 NonContigPartDefinition::NonContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other)
552 std::string NonContigPartDefinition::printSelf() const
554 std::ostringstream oss;
555 oss << "Non contiguous : ";
556 for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
561 std::vector<bool> NonContigPartDefinition::getCoresOn() const
563 std::vector<bool> ret(getSpaceSize(),false);
564 for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
569 NonContigPartDefinition *NonContigPartDefinition::copy() const
571 return new NonContigPartDefinition(*this);
574 int NonContigPartDefinition::getNumberOfCoresConsumed() const
579 void NonContigPartDefinition::checkOKIds() const
581 int maxVal(getSpaceSize());
584 int val(_ids.front());
585 if(val<0 || val>=maxVal)
586 throw Exception("checkOKIds : error 2 !");
587 std::size_t sz(_ids.size());
588 for(std::size_t i=0;i<sz-1;i++)
590 if(_ids[i+1]<=_ids[i])
591 throw Exception("checkOKIds : error 1 !");
592 if(_ids[i+1]>=maxVal)
593 throw Exception("checkOKIds : error 3 !");
597 //////////////////////
599 AllPartDefinition::AllPartDefinition(const AllPartDefinition& other):PartDefinition(other)
603 std::string AllPartDefinition::printSelf() const
605 std::ostringstream oss;
610 std::vector<bool> AllPartDefinition::getCoresOn() const
612 std::vector<bool> ret(getSpaceSize(),true);
616 AllPartDefinition *AllPartDefinition::copy() const
618 return new AllPartDefinition(*this);
621 int AllPartDefinition::getNumberOfCoresConsumed() const
623 return getSpaceSize();
626 //////////////////////
628 std::vector<int> ForTestOmlyHPContCls::getIDS() const
630 std::size_t sz(_ids.size());
631 std::vector<int> ret(sz);
632 for(std::size_t i=0;i<sz;i++)