Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2024 German Aerospace Center (DLR) and others.
4 : // This program and the accompanying materials are made available under the
5 : // terms of the Eclipse Public License 2.0 which is available at
6 : // https://www.eclipse.org/legal/epl-2.0/
7 : // This Source Code may also be made available under the following Secondary
8 : // Licenses when the conditions for such availability set forth in the Eclipse
9 : // Public License 2.0 are satisfied: GNU General Public License, version 2
10 : // or later which is available at
11 : // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 : // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 : /****************************************************************************/
14 : /// @file MSEdgeControl.cpp
15 : /// @author Christian Roessel
16 : /// @author Daniel Krajzewicz
17 : /// @author Jakob Erdmann
18 : /// @author Michael Behrisch
19 : /// @date Mon, 09 Apr 2001
20 : ///
21 : // Stores edges and lanes, performs moving of vehicle
22 : /****************************************************************************/
23 : #include <config.h>
24 :
25 : #include <iostream>
26 : #include <queue>
27 : #include <vector>
28 : #include "MSEdgeControl.h"
29 : #include "MSVehicleControl.h"
30 : #include "MSGlobals.h"
31 : #include "MSEdge.h"
32 : #include "MSLane.h"
33 : #include "MSVehicle.h"
34 :
35 : #define PARALLEL_PLAN_MOVE
36 : #define PARALLEL_EXEC_MOVE
37 : //#define PARALLEL_CHANGE_LANES
38 : //#define LOAD_BALANCING
39 :
40 : //#define PARALLEL_STOPWATCH
41 :
42 : // ===========================================================================
43 : // member method definitions
44 : // ===========================================================================
45 42324 : MSEdgeControl::MSEdgeControl(const std::vector< MSEdge* >& edges)
46 42324 : : myEdges(edges),
47 42324 : myLanes(MSLane::dictSize()),
48 42324 : myWithVehicles2Integrate(MSGlobals::gNumSimThreads > 1),
49 42324 : myLastLaneChange(edges.size()),
50 42324 : myInactiveCheckCollisions(MSGlobals::gNumSimThreads > 1),
51 42324 : myMinLengthGeometryFactor(1.),
52 : #ifdef THREAD_POOL
53 : myThreadPool(false, std::vector<int>(MSGlobals::gNumThreads, 0)),
54 : #endif
55 42324 : myStopWatch(3) {
56 : // build the usage definitions for lanes
57 1772531 : for (MSEdge* const edge : myEdges) {
58 : const std::vector<MSLane*>& lanes = edge->getLanes();
59 1730207 : if (!edge->hasLaneChanger()) {
60 1286387 : const int pos = lanes.front()->getNumericalID();
61 1286387 : myLanes[pos].lane = lanes.front();
62 1286387 : myLanes[pos].amActive = false;
63 1286387 : myLanes[pos].haveNeighbors = false;
64 2572774 : myMinLengthGeometryFactor = MIN2(edge->getLengthGeometryFactor(), myMinLengthGeometryFactor);
65 : } else {
66 1307680 : for (MSLane* const l : lanes) {
67 : const int pos = l->getNumericalID();
68 863860 : myLanes[pos].lane = l;
69 863860 : myLanes[pos].amActive = false;
70 863860 : myLanes[pos].haveNeighbors = true;
71 1700036 : myMinLengthGeometryFactor = MIN2(l->getLengthGeometryFactor(), myMinLengthGeometryFactor);
72 : }
73 443820 : myLastLaneChange[edge->getNumericalID()] = -1;
74 : }
75 : }
76 : #ifndef THREAD_POOL
77 : #ifdef HAVE_FOX
78 42324 : if (MSGlobals::gNumThreads > 1) {
79 20226 : while (myThreadPool.size() < MSGlobals::gNumThreads) {
80 16162 : new WorkerThread(myThreadPool);
81 : }
82 : }
83 : #endif
84 : #endif
85 42324 : }
86 :
87 :
88 39408 : MSEdgeControl::~MSEdgeControl() {
89 : #ifndef THREAD_POOL
90 : #ifdef HAVE_FOX
91 39408 : myThreadPool.clear();
92 : #endif
93 : #endif
94 : #ifdef PARALLEL_STOPWATCH
95 : StopWatch<std::chrono::nanoseconds> wPlan;
96 : for (MSEdge* const edge : myEdges) {
97 : for (MSLane* const l : edge->getLanes()) {
98 : wPlan.add(l->getStopWatch()[0]);
99 : }
100 : }
101 : std::cout << wPlan.getHistory().size() << " lane planmove calls, average " << wPlan.getAverage() << " ns, total " << wPlan.getTotal() / double(1e9) << " s" << std::endl;
102 : std::cout << myStopWatch[0].getHistory().size() << " planmove calls, average " << myStopWatch[0].getAverage() << " ns, total " << myStopWatch[0].getTotal() / double(1e9) << " s" << std::endl;
103 : std::cout << myStopWatch[1].getHistory().size() << " execmove calls, average " << myStopWatch[1].getAverage() << " ns, total " << myStopWatch[1].getTotal() / double(1e9) << " s" << std::endl;
104 : #endif
105 118224 : }
106 :
107 : void
108 3 : MSEdgeControl::setActiveLanes(std::list<MSLane*> lanes) {
109 3 : myActiveLanes = lanes;
110 7 : for (MSLane* lane : lanes) {
111 4 : myLanes[lane->getNumericalID()].amActive = true;
112 : }
113 3 : }
114 :
115 : void
116 78377716 : MSEdgeControl::patchActiveLanes() {
117 78959765 : for (std::set<MSLane*, ComparatorNumericalIdLess>::iterator i = myChangedStateLanes.begin(); i != myChangedStateLanes.end(); ++i) {
118 582049 : LaneUsage& lu = myLanes[(*i)->getNumericalID()];
119 : // if the lane was inactive but is now...
120 582049 : if (!lu.amActive && (*i)->getVehicleNumber() > 0) {
121 : // ... add to active lanes and mark as such
122 563988 : if (lu.haveNeighbors) {
123 444876 : myActiveLanes.push_front(*i);
124 : } else {
125 119112 : myActiveLanes.push_back(*i);
126 : }
127 563988 : lu.amActive = true;
128 : }
129 : }
130 : myChangedStateLanes.clear();
131 78377716 : }
132 :
133 :
134 : void
135 78377716 : MSEdgeControl::planMovements(SUMOTime t) {
136 : #ifdef PARALLEL_STOPWATCH
137 : myStopWatch[0].start();
138 : #endif
139 : #ifdef THREAD_POOL
140 : std::vector<std::future<void>> results;
141 : #endif
142 155910748 : for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
143 77533032 : const int vehNum = (*i)->getVehicleNumber();
144 77533032 : if (vehNum == 0) {
145 342946 : myLanes[(*i)->getNumericalID()].amActive = false;
146 342946 : i = myActiveLanes.erase(i);
147 : } else {
148 : #ifdef THREAD_POOL
149 : if (MSGlobals::gNumSimThreads > 1) {
150 : results.push_back(myThreadPool.executeAsync([i, t](int) {
151 : (*i)->planMovements(t);
152 : }, (*i)->getRNGIndex() % MSGlobals::gNumSimThreads));
153 : ++i;
154 : continue;
155 : }
156 : #else
157 : #ifdef HAVE_FOX
158 77190086 : if (MSGlobals::gNumSimThreads > 1) {
159 12106384 : myThreadPool.add((*i)->getPlanMoveTask(t), (*i)->getRNGIndex() % myThreadPool.size());
160 : ++i;
161 12106384 : continue;
162 : }
163 : #endif
164 : #endif
165 65083702 : (*i)->planMovements(t);
166 : ++i;
167 : }
168 : }
169 : #ifdef THREAD_POOL
170 : for (auto& r : results) {
171 : r.wait();
172 : }
173 : #else
174 : #ifdef HAVE_FOX
175 78377716 : if (MSGlobals::gNumSimThreads > 1) {
176 3653591 : myThreadPool.waitAll(false);
177 : }
178 : #endif
179 : #endif
180 : #ifdef PARALLEL_STOPWATCH
181 : myStopWatch[0].stop();
182 : #endif
183 78377716 : }
184 :
185 :
186 : void
187 78377716 : MSEdgeControl::setJunctionApproaches(SUMOTime t) {
188 155567802 : for (MSLane* const lane : myActiveLanes) {
189 77190086 : lane->setJunctionApproaches(t);
190 : }
191 78377716 : }
192 :
193 :
194 : void
195 78377716 : MSEdgeControl::executeMovements(SUMOTime t) {
196 : #ifdef PARALLEL_STOPWATCH
197 : myStopWatch[1].start();
198 : #endif
199 78377716 : std::vector<MSLane*> wasActive(myActiveLanes.begin(), myActiveLanes.end());
200 78377716 : myWithVehicles2Integrate.clear();
201 : #ifdef PARALLEL_EXEC_MOVE
202 : #ifdef THREAD_POOL
203 : if (MSGlobals::gNumSimThreads > 1) {
204 : for (MSLane* const lane : myActiveLanes) {
205 : myThreadPool.executeAsync([lane, t](int) {
206 : lane->executeMovements(t);
207 : }, lane->getRNGIndex() % MSGlobals::gNumSimThreads);
208 : }
209 : myThreadPool.waitAll();
210 : }
211 : #else
212 : #ifdef HAVE_FOX
213 78377716 : if (MSGlobals::gNumSimThreads > 1) {
214 15759975 : for (MSLane* const lane : myActiveLanes) {
215 12106384 : myThreadPool.add(lane->getExecuteMoveTask(t), lane->getRNGIndex() % myThreadPool.size());
216 : }
217 3653591 : myThreadPool.waitAll(false);
218 : }
219 : #endif
220 : #endif
221 : #endif
222 155567782 : for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
223 : if (
224 : #ifdef PARALLEL_EXEC_MOVE
225 77190071 : MSGlobals::gNumSimThreads <= 1 &&
226 : #endif
227 65083687 : (*i)->getVehicleNumber() > 0) {
228 65083687 : (*i)->executeMovements(t);
229 : }
230 77190066 : if ((*i)->getVehicleNumber() == 0) {
231 6427185 : myLanes[(*i)->getNumericalID()].amActive = false;
232 6427185 : i = myActiveLanes.erase(i);
233 : } else {
234 : ++i;
235 : }
236 : }
237 155567777 : for (MSLane* lane : wasActive) {
238 77190066 : lane->updateLengthSum();
239 : }
240 : // arrived vehicles should not influence lane changing
241 78377711 : MSNet::getInstance()->getVehicleControl().removePending();
242 : std::vector<MSLane*>& toIntegrate = myWithVehicles2Integrate.getContainer();
243 78377711 : std::sort(toIntegrate.begin(), toIntegrate.end(), ComparatorIdLess());
244 : /// @todo: sorting only needed to account for lane-ordering dependencies.
245 : //This should disappear when parallelization is working. Until then it would
246 : //be better to use ComparatorNumericalIdLess instead of ComparatorIdLess
247 : myWithVehicles2Integrate.unlock();
248 108122528 : for (MSLane* const lane : toIntegrate) {
249 : const bool wasInactive = lane->getVehicleNumber() == 0;
250 29744817 : lane->integrateNewVehicles();
251 29744817 : if (wasInactive && lane->getVehicleNumber() > 0) {
252 5907321 : LaneUsage& lu = myLanes[lane->getNumericalID()];
253 5907321 : if (!lu.amActive) {
254 5907321 : if (lu.haveNeighbors) {
255 2674497 : myActiveLanes.push_front(lane);
256 : } else {
257 3232824 : myActiveLanes.push_back(lane);
258 : }
259 5907321 : lu.amActive = true;
260 : }
261 : }
262 : }
263 : #ifdef PARALLEL_STOPWATCH
264 : myStopWatch[1].stop();
265 : #endif
266 78377716 : }
267 :
268 :
269 : void
270 78377711 : MSEdgeControl::changeLanes(const SUMOTime t) {
271 : std::vector<MSLane*> toAdd;
272 : #ifdef PARALLEL_CHANGE_LANES
273 : std::vector<const MSEdge*> recheckLaneUsage;
274 : #endif
275 78377711 : MSGlobals::gComputeLC = true;
276 122414023 : for (const MSLane* const l : myActiveLanes) {
277 53929102 : if (myLanes[l->getNumericalID()].haveNeighbors) {
278 : const MSEdge& edge = l->getEdge();
279 44036312 : if (myLastLaneChange[edge.getNumericalID()] != t) {
280 34873442 : myLastLaneChange[edge.getNumericalID()] = t;
281 : #ifdef PARALLEL_CHANGE_LANES
282 : if (MSGlobals::gNumSimThreads > 1) {
283 : MSLane* lane = edge.getLanes()[0];
284 : myThreadPool.add(lane->getLaneChangeTask(t), lane->getRNGIndex() % myThreadPool.size());
285 : recheckLaneUsage.push_back(&edge);
286 : } else {
287 : #endif
288 34873442 : edge.changeLanes(t);
289 102440684 : for (MSLane* const lane : edge.getLanes()) {
290 67567242 : LaneUsage& lu = myLanes[lane->getNumericalID()];
291 : //if ((*i)->getID() == "disabled") {
292 : // std::cout << SIMTIME << " vehicles=" << toString((*i)->getVehiclesSecure()) << "\n";
293 : // (*i)->releaseVehicles();
294 : //}
295 67567242 : if (lane->getVehicleNumber() > 0 && !lu.amActive) {
296 317527 : toAdd.push_back(lane);
297 317527 : lu.amActive = true;
298 : }
299 67567242 : if (MSGlobals::gLateralResolution > 0) {
300 18022653 : lane->sortManeuverReservations();
301 : }
302 : }
303 : #ifdef PARALLEL_CHANGE_LANES
304 : }
305 : #endif
306 : }
307 : } else {
308 : break;
309 : }
310 : }
311 :
312 : #ifdef PARALLEL_CHANGE_LANES
313 : if (MSGlobals::gNumSimThreads > 1) {
314 : myThreadPool.waitAll(false);
315 : for (const MSEdge* e : recheckLaneUsage) {
316 : for (MSLane* const l : e->getLanes()) {
317 : LaneUsage& lu = myLanes[l->getNumericalID()];
318 : if (l->getVehicleNumber() > 0 && !lu.amActive) {
319 : toAdd.push_back(l);
320 : lu.amActive = true;
321 : }
322 : if (MSGlobals::gLateralResolution > 0) {
323 : l->sortManeuverReservations();
324 : }
325 : }
326 : }
327 : }
328 : #endif
329 :
330 78377711 : MSGlobals::gComputeLC = false;
331 78695238 : for (std::vector<MSLane*>::iterator i = toAdd.begin(); i != toAdd.end(); ++i) {
332 317527 : myActiveLanes.push_front(*i);
333 : }
334 78377711 : }
335 :
336 :
337 : void
338 313520653 : MSEdgeControl::detectCollisions(SUMOTime timestep, const std::string& stage) {
339 : // Detections is made by the edge's lanes, therefore hand over.
340 621143970 : for (MSLane* lane : myActiveLanes) {
341 307623317 : if (lane->needsCollisionCheck()) {
342 83364407 : lane->detectCollisions(timestep, stage);
343 : }
344 : }
345 313520653 : if (myInactiveCheckCollisions.size() > 0) {
346 681536 : for (MSLane* lane : myInactiveCheckCollisions.getContainer()) {
347 452406 : lane->detectCollisions(timestep, stage);
348 : }
349 229130 : myInactiveCheckCollisions.clear();
350 : myInactiveCheckCollisions.unlock();
351 : }
352 313520653 : }
353 :
354 :
355 : void
356 582464 : MSEdgeControl::gotActive(MSLane* l) {
357 : myChangedStateLanes.insert(l);
358 582464 : }
359 :
360 : void
361 453381 : MSEdgeControl::checkCollisionForInactive(MSLane* l) {
362 453381 : myInactiveCheckCollisions.insert(l);
363 453381 : }
364 :
365 : void
366 65 : MSEdgeControl::setAdditionalRestrictions() {
367 2163 : for (MSEdge* e : myEdges) {
368 2098 : e->inferEdgeType();
369 : const std::vector<MSLane*>& lanes = e->getLanes();
370 4762 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
371 2664 : (*j)->initRestrictions();
372 : }
373 : }
374 65 : }
375 :
376 : void
377 20 : MSEdgeControl::setMesoTypes() {
378 180 : for (MSEdge* edge : myEdges) {
379 160 : edge->updateMesoType();
380 : }
381 20 : }
382 :
383 : void
384 3 : MSEdgeControl::saveState(OutputDevice& out) {
385 3 : out.openTag(SUMO_TAG_EDGECONTROL);
386 3 : out.writeAttr(SUMO_ATTR_LANES, myActiveLanes);
387 3 : out.closeTag();
388 3 : }
389 :
390 : /****************************************************************************/
|