Salome HOME
SALOMEHPContainer getNumberOfFreePlace and allocateFor
[modules/yacs.git] / src / engine / PlayGround.cxx
1 // Copyright (C) 2006-2019  CEA/DEN, EDF R&D
2 //
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.
7 //
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.
12 //
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
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "PlayGround.hxx"
21 #include "Runtime.hxx"
22
23 #include <set>
24 #include <map>
25 #include <sstream>
26 #include <iomanip>
27 #include <numeric>
28 #include <algorithm>
29
30 using namespace YACS::ENGINE;
31
32 std::size_t Resource::getNumberOfFreePlace(int nbCoresPerCont) const
33 {
34   std::size_t ret(0),pos(0);
35   while( pos < _occupied.size() )
36     {
37       bool isChunckFree(true);
38       int posInChunck(0);
39       for( ; ( posInChunck < nbCoresPerCont ) && ( pos < _occupied.size() ) ; ++posInChunck, ++pos)
40         if(_occupied[pos])
41           isChunckFree = false;
42       if( isChunckFree && (posInChunck == nbCoresPerCont) )
43         ret++;
44     }
45   return ret;
46 }
47
48 std::vector<std::size_t> Resource::allocateFor(std::size_t& nbOfPlacesToTake, int nbCoresPerCont) const
49 {
50   std::vector<std::size_t> ret;
51   std::size_t pos(0),curWorkerId(0);
52   while( ( pos < _occupied.size() ) && ( nbOfPlacesToTake > 0 ) )
53     {
54       bool isChunckFree(true);
55       int posInChunck(0);
56       for( ; ( posInChunck < nbCoresPerCont ) && ( pos < _occupied.size() ) ; ++posInChunck, ++pos)
57         if(_occupied[pos])
58           isChunckFree = false;
59       if( isChunckFree && (posInChunck == nbCoresPerCont) )
60         {
61           for(int i = 0 ; i < nbCoresPerCont ; ++i)
62             _occupied[pos-nbCoresPerCont+i] = true;
63           ret.push_back(curWorkerId);
64           --nbOfPlacesToTake;
65         }
66       ++curWorkerId;
67     }
68   return ret;
69 }
70
71 std::string PlayGround::printSelf() const
72 {
73   std::ostringstream oss;
74   std::size_t sz(0);
75   for(auto it : _data)
76     sz=std::max(sz,it.name().length());
77   for(auto it : _data)
78     {
79       oss << " - " << std::setw(10) << it.name() << " : " << it.nbCores() << std::endl;
80     }
81   return oss.str();
82 }
83
84 void PlayGround::loadFromKernelCatalog()
85 {
86   Runtime *r(getRuntime());
87   if(!r)
88     throw Exception("PlayGround::loadFromKernelCatalog : no runtime  !");
89   std::vector< std::pair<std::string,int> > data(r->getCatalogOfComputeNodes());
90   setData(data);
91 }
92
93 void PlayGround::setData(const std::vector< std::pair<std::string,int> >& defOfRes)
94 {
95   _data=std::vector<Resource>(defOfRes.begin(),defOfRes.end());
96   checkCoherentInfo();
97 }
98
99 int PlayGround::getNumberOfCoresAvailable() const
100 {
101   int ret(0);
102   for(auto it : _data)
103     ret+=it.nbCores();
104   return ret;
105 }
106
107 int PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap(int nbCoresPerCont) const
108 {
109   if(nbCoresPerCont<1)
110     throw Exception("PlayGround::getMaxNumberOfContainersCanBeHostedWithoutOverlap : invalid nbCoresPerCont. Must be >=1 !");
111   int ret(0);
112   for(auto it : _data)
113     ret+=it.nbCores()/nbCoresPerCont;
114   return ret;
115 }
116
117 std::vector<int> PlayGround::computeOffsets() const
118 {
119   std::size_t sz(_data.size()),i(0);
120   std::vector<int> ret(sz+1); ret[0]=0;
121   for(auto it=_data.begin();it!=_data.end();it++,i++)
122     ret[i+1]=ret[i]+it->nbCores();
123   return ret;
124 }
125
126 void PlayGround::checkCoherentInfo() const
127 {
128   std::set<std::string> s;
129   for(auto it : _data)
130     {
131       s.insert(it.name());
132       if(it.nbCores()<0)
133         throw Exception("Presence of negative int value !");
134     }
135   if(s.size()!=_data.size())
136     throw Exception("host names entries must be different each other !");
137 }
138
139 std::vector<int> PlayGround::GetIdsMatching(const std::vector<bool>& bigArr, const std::vector<bool>& pat)
140 {
141   std::vector<int> ret;
142   std::size_t szp(pat.size());
143   std::size_t sz(bigArr.size()/szp);
144   for(std::size_t i=0;i<sz;i++)
145     {
146       std::vector<bool> t(bigArr.begin()+i*szp,bigArr.begin()+(i+1)*szp);
147       if(t==pat)
148         ret.push_back(i);
149     }
150   return ret;
151 }
152
153 std::size_t PlayGround::getNumberOfFreePlace(int nbCoresPerCont) const
154 {
155   std::size_t ret(0);
156   for(auto res : _data)
157     {
158       ret += res.getNumberOfFreePlace(nbCoresPerCont);
159     }
160   return ret;
161 }
162
163 std::vector<std::size_t> PlayGround::allocateFor(std::size_t nbOfPlacesToTake, int nbCoresPerCont) const
164 {
165   std::vector<std::size_t> ret;
166   std::size_t nbOfPlacesToTakeCpy(nbOfPlacesToTake),offset(0);
167   for(auto res : _data)
168     {
169       std::vector<std::size_t> contIdsInRes(res.allocateFor(nbOfPlacesToTakeCpy,nbCoresPerCont));
170       std::for_each(contIdsInRes.begin(),contIdsInRes.end(),[offset](std::size_t& val) { val += offset; });
171       ret.insert(ret.end(),contIdsInRes.begin(),contIdsInRes.end());
172       offset += static_cast<std::size_t>(res.nbCores()/nbCoresPerCont);
173     }
174   if( ( nbOfPlacesToTakeCpy!=0 ) || ( ret.size()!=nbOfPlacesToTake ) )
175     throw Exception("PlayGround::allocateFor : internal error ! Promised place is not existing !");
176   return ret;
177 }
178
179 std::vector<int> PlayGround::BuildVectOfIdsFromVecBool(const std::vector<bool>& v)
180 {
181   std::size_t sz(std::count(v.begin(),v.end(),true)),i(0);
182   std::vector<int> ret(sz);
183   std::vector<bool>::const_iterator it(v.begin());
184   while(i<sz)
185     {
186       it=std::find(it,v.end(),true);
187       ret[i++]=std::distance(v.begin(),it);
188       it++;
189     }
190   return ret;
191 }
192
193 void PlayGround::highlightOnIds(const std::vector<int>& coreIds, std::vector<bool>& v) const
194 {
195   if(v.size()!=getNumberOfCoresAvailable())
196     throw Exception("PlayGround::highlightOnIds : oops ! invalid size !");
197   for(std::vector<int>::const_iterator it=coreIds.begin();it!=coreIds.end();it++)
198     v[*it]=true;
199 }
200
201 /*! 
202  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
203  */
204 // std::vector<bool> PlayGround::getFetchedCores(int nbCoresPerWorker) const
205 // {
206 //   int nbCores(getNumberOfCoresAvailable());
207 //   std::vector<bool> ret(nbCores,false);
208 //   if(nbCoresPerWorker==1)
209 //     std::fill(ret.begin(),ret.end(),true);
210 //   else
211 //     {
212 //       std::size_t posBg(0);
213 //       for(std::vector< std::pair<std::string,int> >::const_iterator it=_data.begin();it!=_data.end();it++)
214 //         {
215 //           int nbElemsToPutOn(((*it).second/nbCoresPerWorker)*nbCoresPerWorker);
216 //           std::fill(ret.begin()+posBg,ret.begin()+posBg+nbElemsToPutOn,true);
217 //           posBg+=(*it).second;
218 //         }
219 //     }
220 //   return ret;
221 //}
222 /*!
223  * follow getMaxNumberOfContainersCanBeHostedWithoutOverlap method
224  */
225 std::vector<std::size_t> PlayGround::getWorkerIdsFullyFetchedBy(int nbCoresPerComp, const std::vector<bool>& coreFlags) const
226 {
227   std::size_t posBg(0),posWorker(0);
228   std::vector<std::size_t> ret;
229   for(auto it : _data)
230     {
231       int nbWorker(it.nbCores()/nbCoresPerComp);
232       for(int j=0;j<nbWorker;j++,posWorker++)
233         {
234           std::vector<bool>::const_iterator it2(std::find(coreFlags.begin()+posBg+j*nbCoresPerComp,coreFlags.begin()+posBg+(j+1)*nbCoresPerComp,false));
235           if(it2==coreFlags.begin()+posBg+(j+1)*nbCoresPerComp)
236             ret.push_back(posWorker);
237         }
238       posBg+=it.nbCores();
239     }
240   return ret;
241 }
242
243 std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PlayGround::partition(const std::vector< std::pair<const PartDefinition *, const ComplexWeight *> >& parts, const std::vector< int>& nbCoresPerShot) const
244 {
245   std::size_t sz(parts.size()),szs(getNumberOfCoresAvailable());
246   if (sz!=nbCoresPerShot.size())
247     throw Exception("PlayGround::partition : incoherent vector size !");
248   if(sz==0)
249     return std::vector< YACS::BASES::AutoRefCnt<PartDefinition> >();
250   if(sz==1)
251     {
252       const PartDefinition *pd(parts[0].first);
253       if(!pd)
254         throw Exception("Presence of null pointer as part def  0 !");
255       YACS::BASES::AutoRefCnt<PartDefinition> ret(pd->copy());
256       std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret2(1,ret);
257       return ret2;
258     }
259   if(sz>31)
260     throw Exception("PlayGround::partition : not implemented yet for more than 31 ! You need to pay for it :)");
261   std::vector<bool> zeArr(szs*sz,false);
262   std::size_t i(0);
263   for(std::vector< std::pair<const PartDefinition *, const ComplexWeight *> >::const_iterator it=parts.begin();it!=parts.end();it++,i++)
264     {
265       const PartDefinition *pd((*it).first);
266       if(!pd)
267         throw Exception("Presence of null pointer as part def !");
268       if(pd->getPlayGround()!=this)
269         throw Exception("Presence of non homogeneous playground !");
270       std::vector<bool> bs(pd->getCoresOn()); // tab of length nbCores, with True or False for each Core
271       for(std::size_t j=0;j<szs;j++)
272         zeArr[j*sz+i]=bs[j]; // remplis une table avec les valeurs de bs. La table est [nb part] * [nb cores]
273     }
274   std::vector< std::vector<int> > retIds(sz);
275   for(std::size_t i=0;i<szs;i++)
276     {
277       std::vector<bool> code(zeArr.begin()+i*sz,zeArr.begin()+(i+1)*sz);// vecteur contenant le true/false d'un coeur pour ttes les partitions
278       std::vector<int> locIds(GetIdsMatching(zeArr,code)); // liste des coeurs qui peuvent correspondre au pattern code
279       std::vector<int> partsIds(BuildVectOfIdsFromVecBool(code));// pour chaque partition retourne l'id de la premiere partition Ã  true
280       if(partsIds.empty())
281         continue;
282       std::vector<std::pair <const ComplexWeight *, int> > wg;
283       for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++)
284         {
285           wg.push_back(std::pair <const ComplexWeight *, int> (parts[*it].second, nbCoresPerShot[*it]));
286         }
287       std::vector< std::vector<int> > ress(splitIntoParts(locIds,wg));
288       std::size_t k(0);
289       for(std::vector<int>::const_iterator it=partsIds.begin();it!=partsIds.end();it++,k++)
290         {
291           retIds[*it].insert(retIds[*it].end(),ress[k].begin(),ress[k].end());
292         }
293     }
294   //
295   std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > ret(sz);
296   for(std::size_t i=0;i<sz;i++)
297     {
298       std::set<int> s(retIds[i].begin(),retIds[i].end());
299       std::vector<int> v(s.begin(),s.end());
300       ret[i]=PartDefinition::BuildFrom(this,v);
301     }
302   return ret;
303 }
304
305 std::vector< std::vector<int> > PlayGround::splitIntoParts(const std::vector<int>& coreIds, const std::vector< std::pair <const ComplexWeight *, int> >& weights) const
306 {
307   std::size_t sz(weights.size());
308   if(sz==0)
309     return std::vector< std::vector<int> >();
310   std::vector< std::vector<int> > ret;
311   std::vector< std::vector<int> > disorderRet(sz);
312   std::vector<bool> zeArr(getNumberOfCoresAvailable(),false);
313   highlightOnIds(coreIds,zeArr);
314   int nbOfCoresToSplit(coreIds.size());
315   int totalSpace(coreIds.size());
316   int remainingSpace(totalSpace);
317   std::vector<int> nbOfCoresAllocated(sz);
318   std::vector<int> nbCoresPerShot(sz,-1);  
319   // first every other branchs take its minimal part of the cake
320   // and remove branch without valid weight
321   int i(0);
322   std::map<int,int> saveOrder;
323   const std::vector< std::pair <const ComplexWeight *, int> > sortedWeights(bigToTiny(weights, saveOrder));
324   for(std::vector<std::pair <const ComplexWeight *, int> >::const_iterator it=sortedWeights.begin();it!=sortedWeights.end();it++,i++)
325     {
326       nbCoresPerShot[i]=(*it).second;
327       if ((*it).first->isUnsetLoopWeight())
328         {
329           nbOfCoresAllocated[i]=nbCoresPerShot[i]; // branch with only elementary nodes
330         }
331       else if (!(*it).first->hasValidLoopWeight())
332         {
333           nbOfCoresAllocated[i]=std::max((int)((double)totalSpace/(double)(sz)), nbCoresPerShot[i]); // branch with undefined weight, takes his part proportionnally to the number of branchs
334         }
335       else
336         {
337           nbOfCoresAllocated[i]=nbCoresPerShot[i];
338         }
339     }
340   remainingSpace-=std::accumulate(nbOfCoresAllocated.begin(), nbOfCoresAllocated.end(), 0);
341   //get critical path (between path with loopWeight)
342   int criticalPathRank=getCriticalPath(sortedWeights, nbOfCoresAllocated);
343   if (criticalPathRank!=-1)
344     {
345       // add cores to critical path while enough cores are availables
346           while (remainingSpace >= nbCoresPerShot[criticalPathRank])
347             {
348               nbOfCoresAllocated[criticalPathRank]+=nbCoresPerShot[criticalPathRank];
349               remainingSpace-=nbCoresPerShot[criticalPathRank];
350               criticalPathRank=getCriticalPath(sortedWeights, nbOfCoresAllocated);
351             }
352           //fill other paths with remaining cores (if possible) (reuse fromBigToTiny here?)
353           // and takePlace
354           int coresToAdd;
355           int j(0);
356           for(std::vector<int>::iterator it=nbOfCoresAllocated.begin();it!=nbOfCoresAllocated.end();it++,j++)
357             {
358               coresToAdd=((int)(remainingSpace/nbCoresPerShot[j]))*nbCoresPerShot[j];
359               *it+=coresToAdd;
360               remainingSpace-=coresToAdd;
361             }
362     }
363   int k(0);
364   for(std::vector<int>::iterator it=nbOfCoresAllocated.begin();it!=nbOfCoresAllocated.end();it++,k++)
365     {
366       disorderRet[k]=takePlace(*it,nbCoresPerShot[k],zeArr,k==(sz-1));
367     }   
368   ret=backToOriginalOrder(disorderRet, saveOrder);
369   return ret;
370 }
371
372 std::vector< std::pair <const ComplexWeight *, int> > PlayGround::bigToTiny(const std::vector< std::pair <const ComplexWeight *, int> > &weights, std::map<int,int> &saveOrder) const
373 {
374   int maxCoresPerShot(0), rankMax(0);
375   int i(0);
376   std::vector< std::pair <const ComplexWeight *, int> > ret;
377   std::size_t sz(weights.size());
378   while (ret.size()<sz)
379     {
380       for(std::vector<std::pair <const ComplexWeight *, int> >::const_iterator it=weights.begin();it!=weights.end();it++,i++)
381         {
382           if ((maxCoresPerShot<(*it).second) && (saveOrder.find(i)==saveOrder.end()))
383             {
384               maxCoresPerShot=(*it).second;
385               rankMax=i;
386             }
387         }
388       ret.push_back(std::pair <const ComplexWeight *, int>(weights[rankMax].first,weights[rankMax].second));
389       saveOrder[rankMax]=ret.size()-1;
390       maxCoresPerShot=0;
391       i=0;
392     }
393   return ret;   
394 }
395
396 std::vector< std::vector<int> > PlayGround::backToOriginalOrder(const std::vector< std::vector<int> > &disorderVec, const std::map<int,int> &saveOrder) const
397 {
398   std::vector< std::vector<int> > ret;
399   std::size_t sz(disorderVec.size());
400   if (disorderVec.size()!=saveOrder.size())
401     throw Exception("PlayGround::backToOriginalOrder : incoherent vector size !");
402   for (int i=0; i<sz; i++)
403       ret.push_back(disorderVec[saveOrder.at(i)]);
404   return ret;
405 }
406
407 int PlayGround::getCriticalPath(const std::vector<std::pair <const ComplexWeight *, int > >& weights, const std::vector<int>& nbOfCoresAllocated) const
408 {
409   double maxWeight(0.);
410   double pathWeight(0.);
411   int rankMaxPath(-1);
412   if ((weights.size()!=nbOfCoresAllocated.size()) || (weights.size()==0))
413     throw Exception("PlayGround::getCriticalPath : internal error !");
414   int i=0;
415   for(std::vector<std::pair <const ComplexWeight *, int> >::const_iterator it=weights.begin();it!=weights.end();it++,i++)
416     {
417       if (nbOfCoresAllocated[i]==0)
418         throw Exception("PlayGround::getCriticalPath : nbOfCoresAllocated is null! error !");
419       if (!(*it).first->isDefaultValue())
420         {
421               pathWeight=(*it).first->calculateTotalLength(nbOfCoresAllocated[i]);
422               if (pathWeight > maxWeight)
423                 {
424                   maxWeight=pathWeight;
425                   rankMaxPath=i;
426                 }
427         }         
428     }
429   return rankMaxPath;
430
431
432 std::vector<int> PlayGround::takePlace(int maxNbOfCoresToAlloc, int nbCoresPerShot, std::vector<bool>& distributionOfCores, bool lastOne) const
433 {
434   if(maxNbOfCoresToAlloc<1)
435     throw Exception("PlayGround::takePlace : internal error ! no space to alloc !");
436   int tmpMaxNbOfCoresToAlloc(maxNbOfCoresToAlloc);
437   if(lastOne)
438     tmpMaxNbOfCoresToAlloc=std::max(tmpMaxNbOfCoresToAlloc,(int)std::count(distributionOfCores.begin(),distributionOfCores.end(),true));
439   std::vector<int> ret;
440   std::vector<int> offsets(computeOffsets());
441   int nbFullItem(0);
442   std::size_t sz(offsets.size()-1);
443   for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;i++)
444     {
445       int d(offsets[i+1]-offsets[i]);
446       if(nbCoresPerShot>d)
447         continue;
448       std::vector<bool> target(nbCoresPerShot,true);
449       for(int j=0;j<=d-nbCoresPerShot && tmpMaxNbOfCoresToAlloc>=nbCoresPerShot;)
450         {
451           std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot);
452           if(t==target)
453             {
454               nbFullItem++;
455               tmpMaxNbOfCoresToAlloc-=nbCoresPerShot;
456               std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+nbCoresPerShot,false);
457               for(int k=offsets[i]+j;k<offsets[i]+j+nbCoresPerShot;k++)
458                 ret.push_back(k);
459               j+=nbCoresPerShot;
460             }
461           else
462             j++;
463         }
464     }
465   if(nbFullItem>0)
466     return ret;
467   if(nbCoresPerShot<=1)
468     throw Exception("PlayGround::takePlace : internal error !");
469   // not enough contiguous place. Find the first wider contiguous place
470   for(int kk=std::min(nbCoresPerShot-1,tmpMaxNbOfCoresToAlloc);kk>=1;kk--)
471     {
472       for(std::size_t i=0;i<sz && tmpMaxNbOfCoresToAlloc>=kk;i++)
473         {
474           int d(offsets[i+1]-offsets[i]);
475           if(kk>d)
476             continue;
477           std::vector<bool> target(kk,true);
478           for(int j=0;j<=d-kk && tmpMaxNbOfCoresToAlloc>=kk;)
479             {
480               std::vector<bool> t(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk);
481               if(t==target)
482                 {
483                   nbFullItem++;
484                   tmpMaxNbOfCoresToAlloc-=kk;
485                   std::fill(distributionOfCores.begin()+offsets[i]+j,distributionOfCores.begin()+offsets[i]+j+kk,false);
486                   for(int k=offsets[i]+j;k<offsets[i]+j+kk;k++)
487                     ret.push_back(k);
488                   return ret;
489                 }
490               else
491                 j++;
492             }
493         }
494     }
495   throw Exception("PlayGround::takePlace : internal error ! All cores are occupied !");
496 }
497
498 int PlayGround::fromWorkerIdToResId(int workerId, int nbProcPerNode) const
499 {
500   std::size_t sz2(_data.size());
501   std::vector<int> deltas(sz2+1); deltas[0]=0;
502   for(std::size_t i=0;i<sz2;i++)
503     deltas[i+1]=deltas[i]+(_data[i].nbCores())/nbProcPerNode;
504   int zePos(0);
505   while(zePos<sz2 && (workerId<deltas[zePos] || workerId>=deltas[zePos+1]))
506     zePos++;
507   if(zePos==sz2)
508     zePos=workerId%sz2;
509   return zePos;
510 }
511
512 /*! 
513  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
514  */
515 std::string PlayGround::deduceMachineFrom(int workerId, int nbProcPerNode) const
516 {
517   int zePos(fromWorkerIdToResId(workerId,nbProcPerNode));
518   return _data[zePos].name();
519 }
520
521 /*! 
522  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, PlayGround::getFetchedCores and PartDefinition::computeWorkerIdsCovered
523  */
524 int PlayGround::getNumberOfWorkers(int nbCoresPerWorker) const
525 {
526   return getMaxNumberOfContainersCanBeHostedWithoutOverlap(nbCoresPerWorker);
527 }
528
529 PlayGround::~PlayGround()
530 {
531 }
532
533 //////////////////////
534
535 PartDefinition::PartDefinition(const PlayGround *pg)
536 {
537   _pg.takeRef(pg);
538 }
539
540 PartDefinition::PartDefinition(const PartDefinition& other):_pg(other._pg)
541 {
542 }
543
544 PartDefinition::~PartDefinition()
545 {
546 }
547
548 // std::vector< YACS::BASES::AutoRefCnt<PartDefinition> > PartDefinition::partition(const std::vector< const ComplexWeight *>& wgs) const
549 // {
550 //   std::size_t sz(wgs.size());
551 //   std::vector< std::pair<const PartDefinition *, const ComplexWeight *> > elts(sz);
552 //   for(std::size_t i=0;i<sz;i++)
553 //     elts[i]=std::pair<const PartDefinition *, const ComplexWeight *>(this,wgs[i]);
554 //   return getPlayGround()->partition(elts);
555 // }
556
557 YACS::BASES::AutoRefCnt<PartDefinition> PartDefinition::BuildFrom(const PlayGround *pg, const std::vector<int>& coreIds)
558 {
559   int spaceSz(pg->getNumberOfCoresAvailable()),sz(coreIds.size());
560   if(sz>spaceSz)
561     throw Exception("PartDefinition::BuildFrom : error 1 !");
562   if(sz==0)
563     throw Exception("PartDefinition::BuildFrom : error 2 !");
564   int zeStart(coreIds.front()),zeEnd(coreIds.back());
565   if(zeStart<0 || zeEnd<zeStart)
566     throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK !");
567   for(std::size_t i=0;i<sz-1;i++)
568     if(coreIds[i+1]<coreIds[i])
569       throw Exception("PartDefinition::BuildFrom : error ! The content of core Ids is not OK 2 !");
570   if(zeEnd-zeStart+1!=sz)
571     {
572       YACS::BASES::AutoRefCnt<PartDefinition> pd(new NonContigPartDefinition(pg,coreIds));
573       return pd;
574     }
575   if(sz==spaceSz)
576     {
577       YACS::BASES::AutoRefCnt<PartDefinition> pd(new AllPartDefinition(pg));
578       return pd;
579     }
580   YACS::BASES::AutoRefCnt<PartDefinition> pd(new ContigPartDefinition(pg,zeStart,zeEnd+1));
581   return pd;
582 }
583
584 void PartDefinition::stashPart(int nbCoresStashed, double weightOfRemain, YACS::BASES::AutoRefCnt<PartDefinition>& pdStashed, YACS::BASES::AutoRefCnt<PartDefinition>& pdRemain) const
585 {
586   if(nbCoresStashed<=0)
587     throw Exception("stashPart : Invalid nbCoresStashed value !");
588   if(weightOfRemain<=0.)
589     throw Exception("stashPart : Invalid weight !");
590   std::vector<bool> coresOn(getCoresOn());
591   int nbCoresAvailable(std::count(coresOn.begin(),coresOn.end(),true));
592   std::vector<int> ids(PlayGround::BuildVectOfIdsFromVecBool(coresOn));
593   if(nbCoresAvailable==0)
594     throw Exception("PartDefinition::stashPart : no available cores !");
595   if(nbCoresAvailable<=nbCoresStashed)
596     {
597       int n0((int)(1./(1.+weightOfRemain)*nbCoresAvailable)); n0=std::max(n0,1);
598       int n1(nbCoresAvailable-n0);
599       if(n1<=0)
600         {
601           pdStashed=PartDefinition::BuildFrom(getPlayGround(),ids);
602           pdRemain=PartDefinition::BuildFrom(getPlayGround(),ids);
603         }
604       else
605         {
606           std::vector<int> ids0(ids.begin(),ids.begin()+n0),ids1(ids.begin()+n0,ids.end());
607           pdStashed=PartDefinition::BuildFrom(getPlayGround(),ids0);
608           pdRemain=PartDefinition::BuildFrom(getPlayGround(),ids1);
609         }
610     }
611   else
612     {
613       std::vector<int> ids0(ids.begin(),ids.begin()+nbCoresStashed),ids1(ids.begin()+nbCoresStashed,ids.end());
614       pdStashed=PartDefinition::BuildFrom(getPlayGround(),ids0);
615       pdRemain=PartDefinition::BuildFrom(getPlayGround(),ids1);
616     }
617 }
618
619 /*! 
620  * you must garantee coherence between PlayGround::deduceMachineFrom, PlayGround::getNumberOfWorkers, and PartDefinition::computeWorkerIdsCovered
621  */
622 std::vector<std::size_t> PartDefinition::computeWorkerIdsCovered(int nbCoresPerComp) const
623 {
624   std::vector<bool> coresOn(getCoresOn());
625   return _pg->getWorkerIdsFullyFetchedBy(nbCoresPerComp,coresOn);
626 }
627
628 //////////////////////
629
630 ContigPartDefinition::ContigPartDefinition(const PlayGround *pg, int zeStart, int zeStop):PartDefinition(pg),_start(zeStart),_stop(zeStop)
631 {
632   if(_start<0 || _stop<_start || _stop>getSpaceSize())
633     throw Exception("ContigPartDefinition constructor : Invalid input values");
634 }
635
636 ContigPartDefinition::ContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other),_start(other._start),_stop(other._stop)
637 {
638 }
639
640 std::string ContigPartDefinition::printSelf() const
641 {
642   std::ostringstream oss;
643   oss << "Contiguous : start=" << _start << " stop=" << _stop;
644   return oss.str();
645 }
646
647 std::vector<bool> ContigPartDefinition::getCoresOn() const
648 {
649   std::vector<bool> ret(getSpaceSize(),false);
650   for(int i=_start;i<_stop;i++)
651     ret[i]=true;
652   return ret;
653 }
654
655 ContigPartDefinition *ContigPartDefinition::copy() const
656 {
657   return new ContigPartDefinition(*this);
658 }
659
660 int ContigPartDefinition::getNumberOfCoresConsumed() const
661 {
662   return _stop-_start;
663 }
664
665 //////////////////////
666
667 NonContigPartDefinition::NonContigPartDefinition(const PlayGround *pg, const std::vector<int>& ids):PartDefinition(pg),_ids(ids)
668 {
669   checkOKIds();
670 }
671
672 NonContigPartDefinition::NonContigPartDefinition(const ContigPartDefinition& other):PartDefinition(other)
673 {
674 }
675
676 std::string NonContigPartDefinition::printSelf() const
677 {
678   std::ostringstream oss;
679   oss << "Non contiguous : ";
680   for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
681     oss << *it << ", ";
682   return oss.str();
683 }
684
685 std::vector<bool> NonContigPartDefinition::getCoresOn() const
686 {
687   std::vector<bool> ret(getSpaceSize(),false);
688   for(std::vector<int>::const_iterator it=_ids.begin();it!=_ids.end();it++)
689     ret[*it]=true;
690   return ret;
691 }
692
693 NonContigPartDefinition *NonContigPartDefinition::copy() const
694 {
695   return new NonContigPartDefinition(*this);
696 }
697
698 int NonContigPartDefinition::getNumberOfCoresConsumed() const
699 {
700   return _ids.size();
701 }
702
703 void NonContigPartDefinition::checkOKIds() const
704 {
705   int maxVal(getSpaceSize());
706   if(_ids.empty())
707     return;
708   int val(_ids.front());
709   if(val<0 || val>=maxVal)
710     throw Exception("checkOKIds : error 2 !");
711   std::size_t sz(_ids.size());
712   for(std::size_t i=0;i<sz-1;i++)
713     {
714       if(_ids[i+1]<=_ids[i])
715         throw Exception("checkOKIds : error 1 !");
716       if(_ids[i+1]>=maxVal)
717         throw Exception("checkOKIds : error 3 !");
718     }
719 }
720
721 //////////////////////
722
723 AllPartDefinition::AllPartDefinition(const AllPartDefinition& other):PartDefinition(other)
724 {
725 }
726
727 std::string AllPartDefinition::printSelf() const
728 {
729   std::ostringstream oss;
730   oss << "All";
731   return oss.str();
732 }
733
734 std::vector<bool> AllPartDefinition::getCoresOn() const
735 {
736   std::vector<bool> ret(getSpaceSize(),true);
737   return ret;
738 }
739
740 AllPartDefinition *AllPartDefinition::copy() const
741 {
742   return new AllPartDefinition(*this);
743 }
744
745 int AllPartDefinition::getNumberOfCoresConsumed() const
746 {
747   return getSpaceSize();
748 }
749
750 //////////////////////
751  
752  std::vector<int> ForTestOmlyHPContCls::getIDS() const
753  {
754    std::size_t sz(_ids.size());
755    std::vector<int> ret(sz);
756    for(std::size_t i=0;i<sz;i++)
757      ret[i]=_ids[i];
758    return ret;
759  }