]> SALOME platform Git repositories - modules/yacs.git/blob - src/workloadmanager/DefaultAlgorithm.cxx
Salome HOME
Work in progress : workload manager engine test ok
[modules/yacs.git] / src / workloadmanager / DefaultAlgorithm.cxx
1 // Copyright (C) 2020  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 #include "DefaultAlgorithm.hxx"
20 #include "Task.hxx"
21 #include <stdexcept>
22 #include <limits>
23 #include <algorithm>
24
25 namespace WorkloadManager
26 {
27 void DefaultAlgorithm::addTask(Task* t)
28 {
29   // put the tasks which need more cores in front.
30   float newNeedCores = t->type().neededCores;
31   if(_waitingTasks.empty())
32     _waitingTasks.push_back(t);
33   else if(_waitingTasks.back()->type().neededCores >= newNeedCores)
34     _waitingTasks.push_back(t);
35   else
36   {
37     std::list<Task*>::iterator it = _waitingTasks.begin();
38     while(it != _waitingTasks.end() && (*it)->type().neededCores >= newNeedCores)
39       it++;
40     _waitingTasks.insert(it, t);
41   }
42 }
43
44 bool DefaultAlgorithm::empty()const
45 {
46   return _waitingTasks.empty();
47 }
48
49 void DefaultAlgorithm::addResource(const Resource& r)
50 {
51   _resources.emplace_back(r);
52 }
53
54 WorkloadAlgorithm::LaunchInfo DefaultAlgorithm::chooseTask()
55 {
56   LaunchInfo result;
57   std::list<Task*>::iterator chosenTaskIt;
58   for( std::list<Task*>::iterator itTask = _waitingTasks.begin();
59       !result.taskFound && itTask != _waitingTasks.end();
60       itTask ++)
61   {
62     const ContainerType& ctype = (*itTask)->type();
63     std::list<ResourceLoadInfo>::iterator best_resource;
64     best_resource = _resources.end();
65     float best_cost = std::numeric_limits<float>::max();
66     bool isSupported = false;
67     for(auto itResource = _resources.begin();
68         itResource != _resources.end();
69         itResource++)
70       if(itResource->isSupported(ctype))
71       {
72         if(itResource->isAllocPossible(ctype))
73         {
74           float thisCost = itResource->cost(ctype);
75           if( best_cost > thisCost)
76           {
77             best_cost = thisCost;
78             best_resource = itResource;
79           }
80         }
81       }
82     if(best_resource != _resources.end())
83     {
84       chosenTaskIt = itTask;
85       result.task = (*itTask);
86       result.taskFound = true;
87       result.worker.resource = best_resource->resource();
88       result.worker.type = ctype;
89       result.worker.index = best_resource->alloc(ctype);
90     }
91     else if(!isSupported)
92     {
93       // TODO: This task can never be run by any available resource.
94     }
95   }
96   if(result.taskFound)
97     _waitingTasks.erase(chosenTaskIt);
98   return result;
99 }
100
101 void DefaultAlgorithm::liberate(const LaunchInfo& info)
102 {
103   const Resource& r = info.worker.resource;
104   unsigned int index = info.worker.index;
105   const ContainerType& ctype = info.worker.type;
106   std::list<ResourceLoadInfo>::iterator it = std::find(_resources.begin(),
107                                                        _resources.end(),
108                                                        r);
109   it->free(ctype, index); // we are sure to find it
110 }
111
112 // ResourceInfoForContainer
113
114 DefaultAlgorithm::ResourceInfoForContainer::ResourceInfoForContainer
115                                 (const Resource& r, const ContainerType& ctype)
116 : _ctype(ctype)
117 , _resource(r)
118 , _runningContainers()
119 , _firstFreeContainer(0)
120 {
121 }
122
123 unsigned int DefaultAlgorithm::ResourceInfoForContainer::maxContainers()const
124 {
125   return float(_resource.nbCores) / _ctype.neededCores;
126 }
127
128 unsigned int  DefaultAlgorithm::ResourceInfoForContainer::alloc()
129 {
130   unsigned int result = _firstFreeContainer;
131   _runningContainers.insert(result);
132   _firstFreeContainer++;
133   while(isContainerRunning(_firstFreeContainer))
134     _firstFreeContainer++;
135   return result;
136 }
137
138 void DefaultAlgorithm::ResourceInfoForContainer::free(unsigned int index)
139 {
140   _runningContainers.erase(index);
141   if(index < _firstFreeContainer)
142     _firstFreeContainer = index;
143 }
144
145 unsigned int DefaultAlgorithm::ResourceInfoForContainer::nbRunningContainers()const
146 {
147   return _runningContainers.size();
148 }
149
150 bool DefaultAlgorithm::ResourceInfoForContainer::isContainerRunning
151                                 (unsigned int index)const
152 {
153   return _runningContainers.find(index)!=_runningContainers.end();
154 }
155
156 // ResourceLoadInfo
157
158 DefaultAlgorithm::ResourceLoadInfo::ResourceLoadInfo(const Resource& r)
159 : _resource(r)
160 , _load(0.0)
161 , _ctypes()
162 {
163 }
164
165 bool DefaultAlgorithm::ResourceLoadInfo::isSupported
166                                 (const ContainerType& ctype)const
167 {
168   return ctype.neededCores <= _resource.nbCores ;
169 }
170                                           
171 bool DefaultAlgorithm::ResourceLoadInfo::isAllocPossible
172                                 (const ContainerType& ctype)const
173 {
174   return ctype.neededCores + _load <= _resource.nbCores;
175 }
176
177 float DefaultAlgorithm::ResourceLoadInfo::cost
178                                 (const ContainerType& ctype)const
179 {
180   return _load * 100.0 / float(_resource.nbCores);
181 }
182
183 unsigned int DefaultAlgorithm::ResourceLoadInfo::alloc
184                                 (const ContainerType& ctype)
185 {
186   std::list<ResourceInfoForContainer>::iterator it = std::find(_ctypes.begin(),
187                                                                _ctypes.end(),
188                                                                ctype);
189   // add the type if not found
190   if(it == _ctypes.end())
191   {
192     _ctypes.emplace_back(_resource, ctype);
193     it = _ctypes.end();
194     it--;
195   }
196   _load += ctype.neededCores;
197   return it->alloc();
198 }
199
200 void DefaultAlgorithm::ResourceLoadInfo::free
201                                 (const ContainerType& ctype, int index)
202 {
203   _load -= ctype.neededCores;
204   std::list<ResourceInfoForContainer>::iterator it = std::find(_ctypes.begin(),
205                                                                _ctypes.end(),
206                                                                ctype);
207   it->free(index);
208 }
209
210 }