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