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 42566 : MSEdgeControl::MSEdgeControl(const std::vector< MSEdge* >& edges)
46 42566 : : myEdges(edges),
47 42566 : myLanes(MSLane::dictSize()),
48 42566 : myWithVehicles2Integrate(MSGlobals::gNumSimThreads > 1),
49 42566 : myLastLaneChange(edges.size()),
50 42566 : myInactiveCheckCollisions(MSGlobals::gNumSimThreads > 1),
51 42566 : myMinLengthGeometryFactor(1.),
52 : #ifdef THREAD_POOL
53 : myThreadPool(false, std::vector<int>(MSGlobals::gNumThreads, 0)),
54 : #endif
55 42566 : myStopWatch(3) {
56 : // build the usage definitions for lanes
57 1777712 : for (MSEdge* const edge : myEdges) {
58 : const std::vector<MSLane*>& lanes = edge->getLanes();
59 1735146 : if (!edge->hasLaneChanger()) {
60 1289598 : const int pos = lanes.front()->getNumericalID();
61 1289598 : myLanes[pos].lane = lanes.front();
62 1289598 : myLanes[pos].amActive = false;
63 1289598 : myLanes[pos].haveNeighbors = false;
64 2579196 : myMinLengthGeometryFactor = MIN2(edge->getLengthGeometryFactor(), myMinLengthGeometryFactor);
65 : } else {
66 1312839 : for (MSLane* const l : lanes) {
67 : const int pos = l->getNumericalID();
68 867291 : myLanes[pos].lane = l;
69 867291 : myLanes[pos].amActive = false;
70 867291 : myLanes[pos].haveNeighbors = true;
71 1706764 : myMinLengthGeometryFactor = MIN2(l->getLengthGeometryFactor(), myMinLengthGeometryFactor);
72 : }
73 445548 : myLastLaneChange[edge->getNumericalID()] = -1;
74 : }
75 : }
76 : #ifndef THREAD_POOL
77 : #ifdef HAVE_FOX
78 42566 : if (MSGlobals::gNumThreads > 1) {
79 20346 : while (myThreadPool.size() < MSGlobals::gNumThreads) {
80 16258 : new WorkerThread(myThreadPool);
81 : }
82 : }
83 : #endif
84 : #endif
85 42566 : }
86 :
87 :
88 39639 : MSEdgeControl::~MSEdgeControl() {
89 : #ifndef THREAD_POOL
90 : #ifdef HAVE_FOX
91 39639 : 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 118917 : }
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 80112737 : MSEdgeControl::patchActiveLanes() {
117 80695228 : for (std::set<MSLane*, ComparatorNumericalIdLess>::iterator i = myChangedStateLanes.begin(); i != myChangedStateLanes.end(); ++i) {
118 582491 : LaneUsage& lu = myLanes[(*i)->getNumericalID()];
119 : // if the lane was inactive but is now...
120 582491 : if (!lu.amActive && (*i)->getVehicleNumber() > 0) {
121 : // ... add to active lanes and mark as such
122 564413 : if (lu.haveNeighbors) {
123 445199 : myActiveLanes.push_front(*i);
124 : } else {
125 119214 : myActiveLanes.push_back(*i);
126 : }
127 564413 : lu.amActive = true;
128 : }
129 : }
130 : myChangedStateLanes.clear();
131 80112737 : }
132 :
133 :
134 : void
135 80112737 : 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 159974357 : for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
143 79861620 : const int vehNum = (*i)->getVehicleNumber();
144 79861620 : if (vehNum == 0) {
145 343022 : myLanes[(*i)->getNumericalID()].amActive = false;
146 343022 : 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 79518598 : if (MSGlobals::gNumSimThreads > 1) {
159 12120174 : myThreadPool.add((*i)->getPlanMoveTask(t), (*i)->getRNGIndex() % myThreadPool.size());
160 : ++i;
161 12120174 : continue;
162 : }
163 : #endif
164 : #endif
165 67398424 : (*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 80112737 : if (MSGlobals::gNumSimThreads > 1) {
176 3661956 : myThreadPool.waitAll(false);
177 : }
178 : #endif
179 : #endif
180 : #ifdef PARALLEL_STOPWATCH
181 : myStopWatch[0].stop();
182 : #endif
183 80112737 : }
184 :
185 :
186 : void
187 80112737 : MSEdgeControl::setJunctionApproaches(SUMOTime t) {
188 159631335 : for (MSLane* const lane : myActiveLanes) {
189 79518598 : lane->setJunctionApproaches(t);
190 : }
191 80112737 : }
192 :
193 :
194 : void
195 80112737 : MSEdgeControl::executeMovements(SUMOTime t) {
196 : #ifdef PARALLEL_STOPWATCH
197 : myStopWatch[1].start();
198 : #endif
199 80112737 : std::vector<MSLane*> wasActive(myActiveLanes.begin(), myActiveLanes.end());
200 80112737 : 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 80112737 : if (MSGlobals::gNumSimThreads > 1) {
214 15782130 : for (MSLane* const lane : myActiveLanes) {
215 12120174 : myThreadPool.add(lane->getExecuteMoveTask(t), lane->getRNGIndex() % myThreadPool.size());
216 : }
217 3661956 : myThreadPool.waitAll(false);
218 : }
219 : #endif
220 : #endif
221 : #endif
222 159631315 : for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
223 : if (
224 : #ifdef PARALLEL_EXEC_MOVE
225 79518583 : MSGlobals::gNumSimThreads <= 1 &&
226 : #endif
227 67398409 : (*i)->getVehicleNumber() > 0) {
228 67398409 : (*i)->executeMovements(t);
229 : }
230 79518578 : if ((*i)->getVehicleNumber() == 0) {
231 6428610 : myLanes[(*i)->getNumericalID()].amActive = false;
232 6428610 : i = myActiveLanes.erase(i);
233 : } else {
234 : ++i;
235 : }
236 : }
237 159631310 : for (MSLane* lane : wasActive) {
238 79518578 : lane->updateLengthSum();
239 : }
240 : // arrived vehicles should not influence lane changing
241 80112732 : MSNet::getInstance()->getVehicleControl().removePending();
242 : std::vector<MSLane*>& toIntegrate = myWithVehicles2Integrate.getContainer();
243 80112732 : 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 109888232 : for (MSLane* const lane : toIntegrate) {
249 : const bool wasInactive = lane->getVehicleNumber() == 0;
250 29775500 : lane->integrateNewVehicles();
251 29775500 : if (wasInactive && lane->getVehicleNumber() > 0) {
252 5908318 : LaneUsage& lu = myLanes[lane->getNumericalID()];
253 5908318 : if (!lu.amActive) {
254 5908318 : if (lu.haveNeighbors) {
255 2675418 : myActiveLanes.push_front(lane);
256 : } else {
257 3232900 : myActiveLanes.push_back(lane);
258 : }
259 5908318 : lu.amActive = true;
260 : }
261 : }
262 : }
263 : #ifdef PARALLEL_STOPWATCH
264 : myStopWatch[1].stop();
265 : #endif
266 80112737 : }
267 :
268 :
269 : void
270 80112732 : MSEdgeControl::changeLanes(const SUMOTime t) {
271 : std::vector<MSLane*> toAdd;
272 : #ifdef PARALLEL_CHANGE_LANES
273 : std::vector<const MSEdge*> recheckLaneUsage;
274 : #endif
275 80112732 : MSGlobals::gComputeLC = true;
276 126437362 : for (const MSLane* const l : myActiveLanes) {
277 56219890 : if (myLanes[l->getNumericalID()].haveNeighbors) {
278 : const MSEdge& edge = l->getEdge();
279 46324630 : if (myLastLaneChange[edge.getNumericalID()] != t) {
280 35839107 : 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 35839107 : edge.changeLanes(t);
289 105712334 : for (MSLane* const lane : edge.getLanes()) {
290 69873227 : LaneUsage& lu = myLanes[lane->getNumericalID()];
291 : //if ((*i)->getID() == "disabled") {
292 : // std::cout << SIMTIME << " vehicles=" << toString((*i)->getVehiclesSecure()) << "\n";
293 : // (*i)->releaseVehicles();
294 : //}
295 69873227 : if (lane->getVehicleNumber() > 0 && !lu.amActive) {
296 317728 : toAdd.push_back(lane);
297 317728 : lu.amActive = true;
298 : }
299 69873227 : if (MSGlobals::gLateralResolution > 0) {
300 18044471 : 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 80112732 : MSGlobals::gComputeLC = false;
331 80430460 : for (std::vector<MSLane*>::iterator i = toAdd.begin(); i != toAdd.end(); ++i) {
332 317728 : myActiveLanes.push_front(*i);
333 : }
334 80112732 : }
335 :
336 :
337 : void
338 320460712 : MSEdgeControl::detectCollisions(SUMOTime timestep, const std::string& stage) {
339 : // Detections is made by the edge's lanes, therefore hand over.
340 637396757 : for (MSLane* lane : myActiveLanes) {
341 316936045 : if (lane->needsCollisionCheck()) {
342 85982509 : lane->detectCollisions(timestep, stage);
343 : }
344 : }
345 320460712 : if (myInactiveCheckCollisions.size() > 0) {
346 682173 : for (MSLane* lane : myInactiveCheckCollisions.getContainer()) {
347 452717 : lane->detectCollisions(timestep, stage);
348 : }
349 229456 : myInactiveCheckCollisions.clear();
350 : myInactiveCheckCollisions.unlock();
351 : }
352 320460712 : }
353 :
354 :
355 : void
356 582907 : MSEdgeControl::gotActive(MSLane* l) {
357 : myChangedStateLanes.insert(l);
358 582907 : }
359 :
360 : void
361 453693 : MSEdgeControl::checkCollisionForInactive(MSLane* l) {
362 453693 : myInactiveCheckCollisions.insert(l);
363 453693 : }
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 : /****************************************************************************/
|