1 // Copyright (C) 2020-2021 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
19 #include "DefaultAlgorithm.hxx"
25 namespace WorkloadManager
27 void DefaultAlgorithm::addTask(Task* t)
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);
37 std::list<Task*>::iterator it = _waitingTasks.begin();
38 while(it != _waitingTasks.end() && (*it)->type().neededCores >= newNeedCores)
40 _waitingTasks.insert(it, t);
44 bool DefaultAlgorithm::empty()const
46 return _waitingTasks.empty();
49 void DefaultAlgorithm::addResource(const Resource& r)
51 _resources.emplace_back(r);
54 WorkloadAlgorithm::LaunchInfo DefaultAlgorithm::chooseTask()
57 std::list<Task*>::iterator chosenTaskIt;
58 for( std::list<Task*>::iterator itTask = _waitingTasks.begin();
59 !result.taskFound && itTask != _waitingTasks.end();
62 const ContainerType& ctype = (*itTask)->type();
63 if(ctype.ignoreResources)
64 result.taskFound = true;
67 std::list<ResourceLoadInfo>::iterator best_resource;
68 best_resource = _resources.end();
69 float best_cost = std::numeric_limits<float>::max();
70 bool isSupported = false;
71 for(auto itResource = _resources.begin();
72 itResource != _resources.end();
74 if(itResource->isSupported(ctype)
75 && (*itTask)->isAccepted(itResource->resource()))
78 if(itResource->isAllocPossible(ctype))
80 float thisCost = itResource->cost(ctype);
81 if( best_cost > thisCost)
84 best_resource = itResource;
88 if(best_resource != _resources.end())
90 result.taskFound = true;
91 result.worker.resource = best_resource->resource();
92 result.worker.index = best_resource->alloc(ctype);
94 else if(!isSupported && _resourcesFrozen)
96 // This task can never be run by any available resource.
97 result.taskFound = true;
98 result.worker.isOk = false;
99 result.worker.error_message = "No resource can run this task.";
104 chosenTaskIt = itTask;
105 result.task = (*itTask);
106 result.worker.type = ctype;
110 _waitingTasks.erase(chosenTaskIt);
114 void DefaultAlgorithm::liberate(const LaunchInfo& info)
116 const ContainerType& ctype = info.worker.type;
117 if(!ctype.ignoreResources && info.worker.isOk)
119 const Resource& r = info.worker.resource;
120 unsigned int index = info.worker.index;
121 std::list<ResourceLoadInfo>::iterator it = std::find(_resources.begin(),
124 it->free(ctype, index); // we are sure to find it
128 // ResourceInfoForContainer
130 DefaultAlgorithm::ResourceInfoForContainer::ResourceInfoForContainer
131 (const Resource& r, const ContainerType& ctype)
134 , _runningContainers()
135 , _firstFreeContainer(0)
139 unsigned int DefaultAlgorithm::ResourceInfoForContainer::maxContainers()const
141 return float(_resource.nbCores) / _ctype.neededCores;
144 unsigned int DefaultAlgorithm::ResourceInfoForContainer::alloc()
146 unsigned int result = _firstFreeContainer;
147 _runningContainers.insert(result);
148 _firstFreeContainer++;
149 while(isContainerRunning(_firstFreeContainer))
150 _firstFreeContainer++;
154 void DefaultAlgorithm::ResourceInfoForContainer::free(unsigned int index)
156 _runningContainers.erase(index);
157 if(index < _firstFreeContainer)
158 _firstFreeContainer = index;
161 unsigned int DefaultAlgorithm::ResourceInfoForContainer::nbRunningContainers()const
163 return _runningContainers.size();
166 bool DefaultAlgorithm::ResourceInfoForContainer::isContainerRunning
167 (unsigned int index)const
169 return _runningContainers.find(index)!=_runningContainers.end();
174 DefaultAlgorithm::ResourceLoadInfo::ResourceLoadInfo(const Resource& r)
182 bool DefaultAlgorithm::ResourceLoadInfo::isSupported
183 (const ContainerType& ctype)const
185 return ctype.neededCores <= _resource.nbCores ;
188 bool DefaultAlgorithm::ResourceLoadInfo::isAllocPossible
189 (const ContainerType& ctype)const
191 return ctype.neededCores + _load <= _resource.nbCores;
194 float DefaultAlgorithm::ResourceLoadInfo::cost
195 (const ContainerType& ctype)const
197 return _loadCost * 100.0 / float(_resource.nbCores);
200 unsigned int DefaultAlgorithm::ResourceLoadInfo::alloc
201 (const ContainerType& ctype)
203 std::list<ResourceInfoForContainer>::iterator it = std::find(_ctypes.begin(),
206 // add the type if not found
207 if(it == _ctypes.end())
209 _ctypes.emplace_back(_resource, ctype);
213 _load += ctype.neededCores;
214 if(ctype.neededCores == 0)
215 _loadCost += COST_FOR_0_CORE_TASKS;
217 _loadCost += ctype.neededCores;
221 void DefaultAlgorithm::ResourceLoadInfo::free
222 (const ContainerType& ctype, int index)
224 _load -= ctype.neededCores;
225 if(ctype.neededCores == 0)
226 _loadCost -= COST_FOR_0_CORE_TASKS;
228 _loadCost -= ctype.neededCores;
229 std::list<ResourceInfoForContainer>::iterator it = std::find(_ctypes.begin(),