source: colin/trunk/src/SerialQueueManager.cpp @ 5786

Revision 5786, 7.7 KB checked in by wehart, 5 years ago (diff)

Update of source to include Acro copyright statement

Line 
1/*  _________________________________________________________________________
2 *
3 *  Acro: A Common Repository for Optimizers
4 *  Copyright (c) 2008 Sandia Corporation.
5 *  This software is distributed under the BSD License.
6 *  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
7 *  the U.S. Government retains certain rights in this software.
8 *  For more information, see the README.txt file in the top Acro directory.
9 *  _________________________________________________________________________
10 */
11
12#include <colin/SerialQueueManager.h>
13
14using std::runtime_error;
15using std::map;
16using std::pair;
17using std::cerr;
18using std::endl;
19
20namespace colin
21{
22
23//======================================================================
24// SerialQueueManager member functions
25//======================================================================
26
27SerialQueueManager::SerialQueueManager()
28{
29}
30
31
32//----------------------------------------------------------------------
33//
34
35/** If queue_id == ALL_SUBQUEUES, all queues are deleted; otherwise,
36 *  only the specified queue is deleted.
37 */
38void
39SerialQueueManager::clear_evaluations(solverID_t solver_id, queueID_t queue_id)
40{
41   queueMap_t::iterator s_it = m_queues->find(solver_id);
42   if ( s_it == m_queues->end() )
43      return;
44
45   if ( queue_id == ALL_SUBQUEUES )
46   {
47      subqueueMap_t::iterator q_it = s_it->second.subqueues.begin();
48      subqueueMap_t::iterator q_itEnd = s_it->second.subqueues.end();
49      for ( ; q_it != q_itEnd; ++q_it )
50         q_it->second.pqueues.clear();
51   }
52   else
53   {
54      subqueueMap_t::iterator q_it = s_it->second.subqueues.find(queue_id);
55      if ( q_it != s_it->second.subqueues.end() )
56         s_it->second.subqueues.erase(q_it);
57   }
58}
59
60
61EvaluationID
62SerialQueueManager::queue_evaluation( AppRequest &request,
63                                      evalMngrID_t evalMngr_id,
64                                      solverID_t solver_id,
65                                      queueID_t queue_id,
66                                      evalPriority_t priority )
67{
68   queueMap_t::iterator s_it = m_queues->find(solver_id);
69   if (s_it == m_queues->end())
70   {
71      EXCEPTION_MNGR(runtime_error, "SerialQueueManager::queue_evaluation():"
72                     " invalid (unknown) solver id (" << solver_id << ")");
73   }
74   if (queue_id != NO_SUBQUEUE)
75   {
76      if (s_it->second.subqueues.find(queue_id)
77            == s_it->second.subqueues.end())
78      {
79         EXCEPTION_MNGR(runtime_error, "SerialQueueManager::"
80                        "queue_evaluation(): invalid (unknown) queue id ("
81                        << queue_id << ")");
82      }
83   }
84
85   // Insert the request...
86   EvaluationID evalID = EvaluationID(evalMngr_id, solver_id, queue_id);
87   s_it->second.subqueues[queue_id].pqueues[priority].push_back
88      (RequestRecord(evalID, request));
89   return evalID;
90}
91
92
93
94EvaluationID
95SerialQueueManager::get_next_request( AppRequest& request,
96                                      solverID_t solver_id,
97                                      queueID_t queue_id )
98{
99   // check for stupidity...
100   queueMap_t::iterator s_it = m_queues->find(solver_id);
101   if ( s_it == m_queues->end() )
102      return EvaluationID();
103
104   subqueueMap_t::iterator q_it;
105   subqueueMap_t::iterator q_itEnd = s_it->second.subqueues.end();
106
107   // Did the user specify a specific queue?
108   if ( queue_id != ALL_SUBQUEUES )
109   {
110      q_it = s_it->second.subqueues.find(queue_id);
111      if ( q_it == q_itEnd )
112         return EvaluationID();
113      if ( q_it->second.pqueues.empty() )
114         return EvaluationID();
115   }
116   else
117   {
118      // find the next evaluation we *should* perform
119      execSequence_t &execSequence = execSequenceMap[solver_id];
120      int pass = 0;
121      while ( pass < 2 )
122      {
123         while ( ! execSequence.empty() )
124         {
125            q_it = s_it->second.subqueues.find(execSequence.front());
126            execSequence.pop_front();
127            if (( q_it == q_itEnd ) || ( q_it->second.pqueues.empty() ))
128               continue;
129
130            pass = 3;
131            break;
132         }
133
134         if (( execSequence.empty() ) && ( pass < 2 ))
135         {
136            generate_exec_sequence(execSequence, s_it);
137            pass++;
138         }
139      }
140      if ( pass == 2 )
141         return EvaluationID();
142   }   
143
144   priorityMap_t::iterator pq_it = q_it->second.pqueues.begin();
145   request = pq_it->second.front().request;
146   EvaluationID evalID = pq_it->second.front().evalID;
147
148   pq_it->second.pop_front();
149   if ( pq_it->second.empty() )
150      q_it->second.pqueues.erase(pq_it);
151
152   return evalID;
153}
154
155
156void SerialQueueManager::new_queue_alloc(queueMap_t::iterator s_it)
157{
158   if ( s_it == m_queues->end() )
159      return;
160
161   generate_exec_sequence(execSequenceMap[s_it->first], s_it);
162
163   LocalQueueManager::new_queue_alloc(s_it);
164}
165
166
167void
168SerialQueueManager::
169generate_exec_sequence(execSequence_t &sequence, queueMap_t::iterator s_it)
170{
171   sequence.clear();
172   if ( s_it == m_queues->end() )
173      return;
174
175   // If there are no queues defined and no one has ever set a queue
176   // allocation, then we just return the default queue.
177   if (s_it->second.subqueues.empty())
178   {
179      sequence.push_back(NO_SUBQUEUE);
180      return;
181   }
182
183   subqueueMap_t::iterator q_it = s_it->second.subqueues.begin();
184   subqueueMap_t::iterator q_itEnd = s_it->second.subqueues.end();
185   // as the allocations should be normalized, the max should be <= 1;
186   double min = 2;
187   for( ; q_it != q_itEnd; ++q_it )
188      if (( min > q_it->second.allocation )
189          && ( q_it->second.allocation > ZeroAlloc))
190         min = q_it->second.allocation;
191
192   if ( min > 1.1 )
193   {
194      // If we don't have a sensible allocation, just return equal allocation
195      for ( q_it = s_it->second.subqueues.begin(); q_it != q_itEnd; ++q_it)
196         sequence.push_back(q_it->first);
197   }
198   else
199   {
200      // The "best" thing to do here is to find least multiple that gives
201      // a rationally close to integer ratio among allocations.  Yippie.
202      // This is more work than it is worth... so we will just get it to
203      // within a multiple of 4
204      map<queueID_t, double> tmp;
205      for( q_it = s_it->second.subqueues.begin(); q_it != q_itEnd; ++q_it)
206         tmp.insert( tmp.end(), pair<queueID_t, double>
207                     (q_it->first, q_it->second.allocation) );
208
209      double frac;
210      double i_part;
211      int mult = 1;
212
213      map<queueID_t, double>::iterator it = tmp.begin();
214      map<queueID_t, double>::iterator itEnd = tmp.end();
215      for ( ; it != itEnd; ++it)
216      {
217         if ( it->second < ZeroAlloc )
218            it->second = 0;
219         else
220         {
221            it->second /= min;
222            frac = std::modf(it->second, &i_part);
223            if ((mult <= 2) && (frac > .37) && (frac < .63))
224               mult = 2;
225            else if ((mult < 4) && (frac > 0.13) && (frac < 0.87))
226               mult = 4;
227         }
228      }
229
230      if (mult > 1)
231         for (it = tmp.begin(); it != itEnd; ++it)
232            it->second = std::floor(it->second*mult + 0.5);
233
234      for (it = tmp.begin(); it != itEnd; ++it)
235         if ( it->second > ZeroAlloc )
236            sequence.insert( sequence.end(),
237                             static_cast<size_t>(it->second),
238                             it->first );
239   }
240
241   // (pseudo) randomize the new sequence... believe it or not, this is
242   // O(N*log(N))
243   map<int, execSequence_t> sorted;
244   while ( ! sequence.empty() )
245   {
246      execSequence_t &tmp = sorted[std::rand()];
247      tmp.splice(tmp.end(), sequence, sequence.begin());
248   }
249   map<int, execSequence_t>::iterator sorted_it = sorted.begin();
250   map<int, execSequence_t>::iterator sorted_itEnd = sorted.end();
251   for (; sorted_it != sorted_itEnd; ++sorted_it)
252      sequence.splice(sequence.end(), sorted_it->second);
253
254}
255
256} //namespace colin
Note: See TracBrowser for help on using the repository browser.