LCOV - code coverage report
Current view: top level - src/microsim - MSEdgeControl.cpp (source / functions) Coverage Total Hit
Test: lcov.info Lines: 100.0 % 134 134
Test Date: 2024-10-24 15:46:30 Functions: 100.0 % 14 14

            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              : /****************************************************************************/
        

Generated by: LCOV version 2.0-1