Line data Source code
1 : /****************************************************************************/
2 : // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo
3 : // Copyright (C) 2001-2026 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 <utils/options/OptionsCont.h>
29 : #include <mesosim/MELoop.h>
30 : #include "MSEdgeControl.h"
31 : #include "MSVehicleControl.h"
32 : #include "MSGlobals.h"
33 : #include "MSEdge.h"
34 : #include "MSLane.h"
35 : #include "MSVehicle.h"
36 :
37 : #define PARALLEL_PLAN_MOVE
38 : #define PARALLEL_EXEC_MOVE
39 : //#define PARALLEL_CHANGE_LANES
40 : //#define LOAD_BALANCING
41 :
42 : //#define PARALLEL_STOPWATCH
43 :
44 : // ===========================================================================
45 : // member method definitions
46 : // ===========================================================================
47 40893 : MSEdgeControl::MSEdgeControl(const std::vector< MSEdge* >& edges)
48 40893 : : myEdges(edges),
49 40893 : myLanes(MSLane::dictSize()),
50 40893 : myWithVehicles2Integrate(MSGlobals::gNumSimThreads > 1),
51 40893 : myLastLaneChange(edges.size()),
52 40893 : myInactiveCheckCollisions(MSGlobals::gNumSimThreads > 1),
53 40893 : myMinLengthGeometryFactor(1.),
54 : #ifdef THREAD_POOL
55 : myThreadPool(false, std::vector<int>(MSGlobals::gNumThreads, 0)),
56 : #endif
57 40893 : myStopWatch(3) {
58 : // build the usage definitions for lanes
59 1747749 : for (MSEdge* const edge : myEdges) {
60 : const std::vector<MSLane*>& lanes = edge->getLanes();
61 1706856 : if (!edge->hasLaneChanger()) {
62 1276102 : const int pos = lanes.front()->getNumericalID();
63 1276102 : myLanes[pos].lane = lanes.front();
64 1276102 : myLanes[pos].amActive = false;
65 1276102 : myLanes[pos].haveNeighbors = false;
66 2552204 : myMinLengthGeometryFactor = MIN2(edge->getLengthGeometryFactor(), myMinLengthGeometryFactor);
67 : } else {
68 1211360 : for (MSLane* const l : lanes) {
69 : const int pos = l->getNumericalID();
70 780606 : myLanes[pos].lane = l;
71 780606 : myLanes[pos].amActive = false;
72 780606 : myLanes[pos].haveNeighbors = true;
73 1536468 : myMinLengthGeometryFactor = MIN2(l->getLengthGeometryFactor(), myMinLengthGeometryFactor);
74 : }
75 430754 : myLastLaneChange[edge->getNumericalID()] = -1;
76 : }
77 : }
78 : #ifndef THREAD_POOL
79 : #ifdef HAVE_FOX
80 40893 : if (MSGlobals::gNumThreads > 1) {
81 22265 : while (myThreadPool.size() < MSGlobals::gNumThreads) {
82 17796 : new WorkerThread(myThreadPool);
83 : }
84 : }
85 : #endif
86 : #endif
87 40893 : }
88 :
89 :
90 40449 : MSEdgeControl::~MSEdgeControl() {
91 : #ifndef THREAD_POOL
92 : #ifdef HAVE_FOX
93 40449 : myThreadPool.clear();
94 : #endif
95 : #endif
96 : #ifdef PARALLEL_STOPWATCH
97 : StopWatch<std::chrono::nanoseconds> wPlan;
98 : for (MSEdge* const edge : myEdges) {
99 : for (MSLane* const l : edge->getLanes()) {
100 : wPlan.add(l->getStopWatch()[0]);
101 : }
102 : }
103 : std::cout << wPlan.getHistory().size() << " lane planmove calls, average " << wPlan.getAverage() << " ns, total " << wPlan.getTotal() / double(1e9) << " s" << std::endl;
104 : std::cout << myStopWatch[0].getHistory().size() << " planmove calls, average " << myStopWatch[0].getAverage() << " ns, total " << myStopWatch[0].getTotal() / double(1e9) << " s" << std::endl;
105 : std::cout << myStopWatch[1].getHistory().size() << " execmove calls, average " << myStopWatch[1].getAverage() << " ns, total " << myStopWatch[1].getTotal() / double(1e9) << " s" << std::endl;
106 : #endif
107 121347 : }
108 :
109 : void
110 8 : MSEdgeControl::setActiveLanes(std::list<MSLane*> lanes) {
111 8 : myActiveLanes = lanes;
112 41 : for (MSLane* lane : lanes) {
113 33 : myLanes[lane->getNumericalID()].amActive = true;
114 : }
115 8 : }
116 :
117 : void
118 43951088 : MSEdgeControl::patchActiveLanes() {
119 44605373 : for (std::set<MSLane*, ComparatorNumericalIdLess>::iterator i = myChangedStateLanes.begin(); i != myChangedStateLanes.end(); ++i) {
120 654285 : LaneUsage& lu = myLanes[(*i)->getNumericalID()];
121 : // if the lane was inactive but is now...
122 654285 : if (!lu.amActive && (*i)->getVehicleNumber() > 0) {
123 : // ... add to active lanes and mark as such
124 634792 : if (lu.haveNeighbors) {
125 503683 : myActiveLanes.push_front(*i);
126 : } else {
127 131109 : myActiveLanes.push_back(*i);
128 : }
129 634792 : lu.amActive = true;
130 : }
131 : }
132 : myChangedStateLanes.clear();
133 43951088 : }
134 :
135 :
136 : void
137 43951088 : MSEdgeControl::planMovements(SUMOTime t) {
138 : #ifdef PARALLEL_STOPWATCH
139 : myStopWatch[0].start();
140 : #endif
141 : #ifdef THREAD_POOL
142 : std::vector<std::future<void>> results;
143 : #endif
144 144488055 : for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
145 100536967 : const int vehNum = (*i)->getVehicleNumber();
146 100536967 : if (vehNum == 0) {
147 367485 : myLanes[(*i)->getNumericalID()].amActive = false;
148 367485 : i = myActiveLanes.erase(i);
149 : } else {
150 : #ifdef THREAD_POOL
151 : if (MSGlobals::gNumSimThreads > 1) {
152 : results.push_back(myThreadPool.executeAsync([i, t](int) {
153 : (*i)->planMovements(t);
154 : }, (*i)->getRNGIndex() % MSGlobals::gNumSimThreads));
155 : ++i;
156 : continue;
157 : }
158 : #else
159 : #ifdef HAVE_FOX
160 100169482 : if (MSGlobals::gNumSimThreads > 1) {
161 17593954 : myThreadPool.add((*i)->getPlanMoveTask(t), (*i)->getRNGIndex() % myThreadPool.size());
162 : ++i;
163 17593954 : continue;
164 : }
165 : #endif
166 : #endif
167 82575528 : (*i)->planMovements(t);
168 : ++i;
169 : }
170 : }
171 : #ifdef THREAD_POOL
172 : for (auto& r : results) {
173 : r.wait();
174 : }
175 : #else
176 : #ifdef HAVE_FOX
177 43951088 : if (MSGlobals::gNumSimThreads > 1) {
178 8445821 : myThreadPool.waitAll(false);
179 : }
180 : #endif
181 : #endif
182 : #ifdef PARALLEL_STOPWATCH
183 : myStopWatch[0].stop();
184 : #endif
185 43951088 : }
186 :
187 :
188 : void
189 43951088 : MSEdgeControl::setJunctionApproaches() {
190 144120570 : for (MSLane* const lane : myActiveLanes) {
191 100169482 : lane->setJunctionApproaches();
192 : }
193 43951088 : }
194 :
195 :
196 : void
197 43951088 : MSEdgeControl::executeMovements(SUMOTime t) {
198 : #ifdef PARALLEL_STOPWATCH
199 : myStopWatch[1].start();
200 : #endif
201 43951088 : std::vector<MSLane*> wasActive(myActiveLanes.begin(), myActiveLanes.end());
202 43951088 : myWithVehicles2Integrate.clear();
203 : #ifdef PARALLEL_EXEC_MOVE
204 : #ifdef THREAD_POOL
205 : if (MSGlobals::gNumSimThreads > 1) {
206 : for (MSLane* const lane : myActiveLanes) {
207 : myThreadPool.executeAsync([lane, t](int) {
208 : lane->executeMovements(t);
209 : }, lane->getRNGIndex() % MSGlobals::gNumSimThreads);
210 : }
211 : myThreadPool.waitAll();
212 : }
213 : #else
214 : #ifdef HAVE_FOX
215 43951088 : if (MSGlobals::gNumSimThreads > 1) {
216 26039775 : for (MSLane* const lane : myActiveLanes) {
217 17593954 : myThreadPool.add(lane->getExecuteMoveTask(t), lane->getRNGIndex() % myThreadPool.size());
218 : }
219 8445821 : myThreadPool.waitAll(false);
220 : }
221 : #endif
222 : #endif
223 : #endif
224 144120567 : for (std::list<MSLane*>::iterator i = myActiveLanes.begin(); i != myActiveLanes.end();) {
225 : if (
226 : #ifdef PARALLEL_EXEC_MOVE
227 100169482 : MSGlobals::gNumSimThreads <= 1 &&
228 : #endif
229 82575528 : (*i)->getVehicleNumber() > 0) {
230 82575528 : (*i)->executeMovements(t);
231 : }
232 100169479 : if ((*i)->getVehicleNumber() == 0) {
233 8424248 : myLanes[(*i)->getNumericalID()].amActive = false;
234 8424248 : i = myActiveLanes.erase(i);
235 : } else {
236 : ++i;
237 : }
238 : }
239 144120564 : for (MSLane* lane : wasActive) {
240 100169479 : lane->updateLengthSum();
241 : }
242 : // arrived vehicles should not influence lane changing
243 43951085 : MSNet::getInstance()->getVehicleControl().removePending();
244 : std::vector<MSLane*>& toIntegrate = myWithVehicles2Integrate.getContainer();
245 43951085 : std::sort(toIntegrate.begin(), toIntegrate.end(), ComparatorIdLess());
246 : /// @todo: sorting only needed to account for lane-ordering dependencies.
247 : //This should disappear when parallelization is working. Until then it would
248 : //be better to use ComparatorNumericalIdLess instead of ComparatorIdLess
249 : myWithVehicles2Integrate.unlock();
250 78384617 : for (MSLane* const lane : toIntegrate) {
251 : const bool wasInactive = lane->getVehicleNumber() == 0;
252 34433532 : lane->integrateNewVehicles();
253 34433532 : if (wasInactive && lane->getVehicleNumber() > 0) {
254 7838412 : LaneUsage& lu = myLanes[lane->getNumericalID()];
255 7838412 : if (!lu.amActive) {
256 7838412 : if (lu.haveNeighbors) {
257 3113234 : myActiveLanes.push_front(lane);
258 : } else {
259 4725178 : myActiveLanes.push_back(lane);
260 : }
261 7838412 : lu.amActive = true;
262 : }
263 : }
264 : }
265 : #ifdef PARALLEL_STOPWATCH
266 : myStopWatch[1].stop();
267 : #endif
268 43951088 : }
269 :
270 :
271 : void
272 43951085 : MSEdgeControl::changeLanes(const SUMOTime t) {
273 : std::vector<MSLane*> toAdd;
274 : #ifdef PARALLEL_CHANGE_LANES
275 : std::vector<const MSEdge*> recheckLaneUsage;
276 : #endif
277 43951085 : MSGlobals::gComputeLC = true;
278 101629743 : for (const MSLane* const l : myActiveLanes) {
279 73980199 : if (myLanes[l->getNumericalID()].haveNeighbors) {
280 : const MSEdge& edge = l->getEdge();
281 57678658 : if (myLastLaneChange[edge.getNumericalID()] != t) {
282 45861868 : myLastLaneChange[edge.getNumericalID()] = t;
283 : #ifdef PARALLEL_CHANGE_LANES
284 : if (MSGlobals::gNumSimThreads > 1) {
285 : MSLane* lane = edge.getLanes()[0];
286 : myThreadPool.add(lane->getLaneChangeTask(t), lane->getRNGIndex() % myThreadPool.size());
287 : recheckLaneUsage.push_back(&edge);
288 : } else {
289 : #endif
290 45861868 : edge.changeLanes(t);
291 136827294 : for (MSLane* const lane : edge.getLanes()) {
292 90965426 : LaneUsage& lu = myLanes[lane->getNumericalID()];
293 : //if ((*i)->getID() == "disabled") {
294 : // std::cout << SIMTIME << " vehicles=" << toString((*i)->getVehiclesSecure()) << "\n";
295 : // (*i)->releaseVehicles();
296 : //}
297 90965426 : if (lane->getVehicleNumber() > 0 && !lu.amActive) {
298 335431 : toAdd.push_back(lane);
299 335431 : lu.amActive = true;
300 : }
301 90965426 : if (MSGlobals::gLateralResolution > 0) {
302 20003034 : lane->sortManeuverReservations();
303 : }
304 : }
305 : #ifdef PARALLEL_CHANGE_LANES
306 : }
307 : #endif
308 : }
309 : } else {
310 : break;
311 : }
312 : }
313 :
314 : #ifdef PARALLEL_CHANGE_LANES
315 : if (MSGlobals::gNumSimThreads > 1) {
316 : myThreadPool.waitAll(false);
317 : for (const MSEdge* e : recheckLaneUsage) {
318 : for (MSLane* const l : e->getLanes()) {
319 : LaneUsage& lu = myLanes[l->getNumericalID()];
320 : if (l->getVehicleNumber() > 0 && !lu.amActive) {
321 : toAdd.push_back(l);
322 : lu.amActive = true;
323 : }
324 : if (MSGlobals::gLateralResolution > 0) {
325 : l->sortManeuverReservations();
326 : }
327 : }
328 : }
329 : }
330 : #endif
331 :
332 43951085 : MSGlobals::gComputeLC = false;
333 44286516 : for (std::vector<MSLane*>::iterator i = toAdd.begin(); i != toAdd.end(); ++i) {
334 335431 : myActiveLanes.push_front(*i);
335 : }
336 43951085 : }
337 :
338 :
339 : void
340 175814402 : MSEdgeControl::detectCollisions(SUMOTime timestep, const std::string& stage) {
341 : // Detections is made by the edge's lanes, therefore hand over.
342 575146986 : for (MSLane* lane : myActiveLanes) {
343 399332584 : if (lane->needsCollisionCheck()) {
344 107654940 : lane->detectCollisions(timestep, stage);
345 : }
346 : }
347 175814402 : if (myInactiveCheckCollisions.size() > 0) {
348 873047 : for (MSLane* lane : myInactiveCheckCollisions.getContainer()) {
349 548871 : lane->detectCollisions(timestep, stage);
350 : }
351 324176 : myInactiveCheckCollisions.clear();
352 : myInactiveCheckCollisions.unlock();
353 : }
354 175814402 : }
355 :
356 :
357 : void
358 654734 : MSEdgeControl::gotActive(MSLane* l) {
359 : myChangedStateLanes.insert(l);
360 654734 : }
361 :
362 : void
363 549909 : MSEdgeControl::checkCollisionForInactive(MSLane* l) {
364 549909 : myInactiveCheckCollisions.insert(l);
365 549909 : }
366 :
367 : void
368 65 : MSEdgeControl::setAdditionalRestrictions() {
369 2163 : for (MSEdge* e : myEdges) {
370 2098 : e->inferEdgeType();
371 : const std::vector<MSLane*>& lanes = e->getLanes();
372 4762 : for (std::vector<MSLane*>::const_iterator j = lanes.begin(); j != lanes.end(); ++j) {
373 2664 : (*j)->initRestrictions();
374 : }
375 : }
376 65 : }
377 :
378 : void
379 5940 : MSEdgeControl::buildMesoSegments() {
380 5940 : const OptionsCont& oc = OptionsCont::getOptions();
381 300141 : for (MSEdge* edge : myEdges) {
382 294201 : if (!edge->getLanes().empty()) {
383 294201 : MSGlobals::gMesoNet->buildSegmentsFor(*edge, oc);
384 : }
385 : }
386 5940 : }
387 :
388 : void
389 8 : MSEdgeControl::saveState(OutputDevice& out) {
390 8 : out.openTag(SUMO_TAG_EDGECONTROL);
391 8 : out.writeAttr(SUMO_ATTR_LANES, myActiveLanes);
392 8 : out.closeTag();
393 8 : }
394 :
395 : /****************************************************************************/
|