16.12.2021, 9:00 - 11:00: Due to updates GitLab may be unavailable for some minutes between 09:00 and 11:00.

Commit 32cf607f authored by Benedikt Zoennchen's avatar Benedikt Zoennchen
Browse files

Merge branch 'dev/parallelEventDrivenOSM-CPU' into 'master'

Dev/parallel event driven osm cpu

See merge request !134
parents 17ea3e8c 7062c914
Pipeline #266874 passed with stages
in 147 minutes and 4 seconds
...@@ -2377,8 +2377,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2377,8 +2377,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
default E rayCastingPolygon(@NotNull final E inEdge, default E rayCastingPolygon(@NotNull final E inEdge,
@NotNull final VPoint q, @NotNull final VPoint q,
@NotNull final VPoint p, @NotNull final VPoint p,
@NotNull final Predicate<E> stopCondition, @NotNull final Predicate<E> stopCondition) {
@NotNull final LinkedList<E> visitedEdges) {
E outEdge = null; E outEdge = null;
E outIfInside = null; E outIfInside = null;
...@@ -2413,8 +2412,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2413,8 +2412,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
default E walkAroundBoundaryStraight(@NotNull final E inEdge, default E walkAroundBoundaryStraight(@NotNull final E inEdge,
@NotNull final VPoint q, @NotNull final VPoint q,
@NotNull final VPoint p, @NotNull final VPoint p,
@NotNull final Predicate<E> stopCondition, @NotNull final Predicate<E> stopCondition) {
@NotNull final LinkedList<E> visitedEdges) {
E outEdge = null; E outEdge = null;
E outIfInside = null; E outIfInside = null;
F face = getMesh().getFace(inEdge); F face = getMesh().getFace(inEdge);
...@@ -2440,7 +2438,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2440,7 +2438,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
} }
if(getMesh().isBoundary(face) && isLeftOf(p.getX(), p.getY(), outEdge)) { if(getMesh().isBoundary(face) && isLeftOf(p.getX(), p.getY(), outEdge)) {
return rayCastingPolygon(inEdge, q, p, stopCondition, visitedEdges); return rayCastingPolygon(inEdge, q, p, stopCondition);
} else { } else {
return outEdge; return outEdge;
} }
...@@ -2478,7 +2476,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2478,7 +2476,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
@NotNull final VPoint q, @NotNull final VPoint q,
@NotNull final VPoint p, @NotNull final VPoint p,
@NotNull final Predicate<E> stopCondition, @NotNull final Predicate<E> stopCondition,
@NotNull final LinkedList<E> visitedEdges) { @Nullable final LinkedList<E> visitedEdges) {
E outEdge = null; E outEdge = null;
F face = getMesh().getFace(inEdge); F face = getMesh().getFace(inEdge);
...@@ -2492,8 +2490,8 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2492,8 +2490,8 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
V v2 = getMesh().getTwinVertex(inEdge); V v2 = getMesh().getTwinVertex(inEdge);
VPoint iPoint1 = GeometryUtils.intersectionPoint(q.getX(), q.getY(), p.getX(), p.getY(), v1.getX(), v1.getY(), v2.getX(), v2.getY()); VPoint iPoint1 = GeometryUtils.intersectionPoint(q.getX(), q.getY(), p.getX(), p.getY(), v1.getX(), v1.getY(), v2.getX(), v2.getY());
outEdge = walkAroundBoundaryStraight(inEdge, q, p, stopCondition, visitedEdges); outEdge = walkAroundBoundaryStraight(inEdge, q, p, stopCondition);
//outEdge = rayCastingPolygon(inEdge, q, p, stopCondition, visitedEdges); //outEdge = rayCastingPolygon(inEdge, q, p, stopCondition);
// the point outside // the point outside
if(outEdge == null) { if(outEdge == null) {
return Optional.empty(); return Optional.empty();
...@@ -2506,7 +2504,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2506,7 +2504,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
// we did no progress towards p => walking around does not work cause the boundary is not convex, therefore we use the expensive method // we did no progress towards p => walking around does not work cause the boundary is not convex, therefore we use the expensive method
if(iPoint1.distanceSq(p) <= iPoint2.distanceSq(p)) { if(iPoint1.distanceSq(p) <= iPoint2.distanceSq(p)) {
// TODO this is too expensive! // TODO this is too expensive!
outEdge = rayCastingPolygon(inEdge, q, p, stopCondition, visitedEdges); outEdge = rayCastingPolygon(inEdge, q, p, stopCondition);
} }
// the point outside // the point outside
...@@ -2566,7 +2564,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2566,7 +2564,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
return Optional.of(getMesh().getTwin(nextOutEdge)); return Optional.of(getMesh().getTwin(nextOutEdge));
} }
else { else {
visitedEdges.add(nextOutEdge); if(visitedEdges != null) {
visitedEdges.add(nextOutEdge);
}
return Optional.empty(); return Optional.empty();
} }
...@@ -2620,7 +2620,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2620,7 +2620,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
* @return all visited edges in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>. * @return all visited edges in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>.
*/ */
default LinkedList<E> straightGatherWalk2D(final VPoint q, final VPoint p, final F startFace, final Predicate<E> stopCondition) { default LinkedList<E> straightGatherWalk2D(final VPoint q, final VPoint p, final F startFace, final Predicate<E> stopCondition) {
return straightGatherWalk2D(q, p, startFace, stopCondition, false); return straightGatherWalk2D(q, p, startFace, stopCondition, false, false);
} }
/** /**
...@@ -2643,7 +2643,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2643,7 +2643,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
* @return all visited edges in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>. * @return all visited edges in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>.
*/ */
default LinkedList<E> straightGatherWalk2DDirectional(final VPoint q, final VPoint direction, final F startFace, final Predicate<E> stopCondition) { default LinkedList<E> straightGatherWalk2DDirectional(final VPoint q, final VPoint direction, final F startFace, final Predicate<E> stopCondition) {
return straightGatherWalk2D(q, direction, startFace, stopCondition, true); return straightGatherWalk2D(q, direction, startFace, stopCondition, true, false);
} }
/** /**
...@@ -2664,6 +2664,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2664,6 +2664,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
* @param startFace start face of the walk * @param startFace start face of the walk
* @param stopCondition stop condition of the walk, i.e. the walk stops if the condition is no longer fulfilled * @param stopCondition stop condition of the walk, i.e. the walk stops if the condition is no longer fulfilled
* @param directional if true we walk in the direction of <tt>pDirection</tt> otherwise we walk to the face containing <tt>pDirection</tt> * @param directional if true we walk in the direction of <tt>pDirection</tt> otherwise we walk to the face containing <tt>pDirection</tt>
* @param gather
* @return all visited edges in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>. * @return all visited edges in a first visited first in ordered queue, i.e. <tt>LinkedList</tt>.
*/ */
default LinkedList<E> straightGatherWalk2D( default LinkedList<E> straightGatherWalk2D(
...@@ -2671,7 +2672,8 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2671,7 +2672,8 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
@NotNull final VPoint pDirection, @NotNull final VPoint pDirection,
@NotNull final F startFace, @NotNull final F startFace,
@NotNull final Predicate<E> stopCondition, @NotNull final Predicate<E> stopCondition,
@NotNull final boolean directional) { final boolean directional,
final boolean gather) {
LinkedList<E> visitedEdges = new LinkedList<>(); LinkedList<E> visitedEdges = new LinkedList<>();
assert contains(q.getX(), q.getY(), startFace); assert contains(q.getX(), q.getY(), startFace);
...@@ -2713,6 +2715,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2713,6 +2715,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
p = pDirection; p = pDirection;
// if this is true we are already done // if this is true we are already done
if(contains(pDirection.getX(), pDirection.getY(), startFace)) { if(contains(pDirection.getX(), pDirection.getY(), startFace)) {
if(!gather) {
visitedEdges.clear();
}
visitedEdges.add(getMesh().getEdge(startFace)); visitedEdges.add(getMesh().getEdge(startFace));
return visitedEdges; return visitedEdges;
} }
...@@ -2737,6 +2742,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2737,6 +2742,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
throw new IllegalArgumentException("did not find any edge."); throw new IllegalArgumentException("did not find any edge.");
} }
if(!gather) {
visitedEdges.clear();
}
visitedEdges.addLast(inEdge); visitedEdges.addLast(inEdge);
...@@ -2809,6 +2817,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte ...@@ -2809,6 +2817,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
if(optEdge.isPresent()) { if(optEdge.isPresent()) {
inEdge = optEdge.get(); inEdge = optEdge.get();
if(!gather) {
visitedEdges.clear();
}
visitedEdges.addLast(inEdge); visitedEdges.addLast(inEdge);
// special case (1): hitting the border i.e. outer boundary // special case (1): hitting the border i.e. outer boundary
......
...@@ -211,7 +211,7 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel { ...@@ -211,7 +211,7 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel {
} }
); );
*/} */}
default: return UpdateSchemeOSM.create(attributesOSM.getUpdateType(), topography, random); default: return UpdateSchemeOSM.create(attributesOSM.getUpdateType(), topography, random, getPotentialFieldAgent().getMaximalInfluenceRadius());
} }
} }
......
...@@ -19,6 +19,7 @@ import org.vadere.util.logging.Logger; ...@@ -19,6 +19,7 @@ import org.vadere.util.logging.Logger;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -27,107 +28,50 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven { ...@@ -27,107 +28,50 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
private final static Logger logger = Logger.getLogger(UpdateSchemeEventDrivenParallel.class); private final static Logger logger = Logger.getLogger(UpdateSchemeEventDrivenParallel.class);
static {
logger.setDebug();
}
private final Topography topography; private final Topography topography;
private LinkedCellsGrid<PedestrianOSM> linkedCellsGrid; private LinkedCellsGrid<PedestrianOSM> linkedCellsGrid;
private boolean[][] locked; private boolean[][] locked;
private double pedestrianPotentialWidth; private double pedestrianPotentialWidth;
private PMesh mesh;
private MeshPanel<PVertex, PHalfEdge, PFace> panel;
private Map<PedestrianOSM, PVertex> map;
private IIncrementalTriangulation<PVertex, PHalfEdge, PFace> triangulation;
public UpdateSchemeEventDrivenParallel(@NotNull final Topography topography, @NotNull final double pedestrianPotentialWidth) { public UpdateSchemeEventDrivenParallel(@NotNull final Topography topography, @NotNull final double pedestrianPotentialWidth) {
super(topography); super(topography);
this.topography = topography; this.topography = topography;
this.pedestrianPotentialWidth = pedestrianPotentialWidth; this.pedestrianPotentialWidth = pedestrianPotentialWidth;
this.map = new HashMap<>();
} }
@Override @Override
public void update(final double timeStepInSec, final double currentTimeInSec) { public void update(final double timeStepInSec, final double currentTimeInSec) {
int count = 0; topography.getElements(PedestrianOSM.class).parallelStream().forEach(pedestrianOSM -> pedestrianOSM.clearStrides());
// construct delaunay triangulation
double maxStepSize = topography.getElements(PedestrianOSM.class).parallelStream().mapToDouble(ped -> ped.getDesiredStepSize()).max().orElse(0);
double maxDesiredSpeed = topography.getElements(PedestrianOSM.class).parallelStream().mapToDouble(ped -> ped.getDesiredSpeed()).max().orElse(0);
double stepSize = Math.max(maxStepSize, maxDesiredSpeed * timeStepInSec);
/*for(PedestrianOSM pedestrianOSM : topography.getElements(PedestrianOSM.class)) { double sideLength = (stepSize+pedestrianPotentialWidth) * 2.0;
pedestrianOSM.clearStrides(); logger.debug("initial grid with a grid edge length equal to " + sideLength);
}
if(!pedestrianEventsQueue.isEmpty()) {
// event driven update ignores time credits!
while (pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec) {
PedestrianOSM ped = pedestrianEventsQueue.poll();
update(ped, currentTimeInSec);
pedestrianEventsQueue.add(ped);
}
}*/
double maxStepSize = 0;
double maxDesiredSpeed = 0;
for(PedestrianOSM pedestrianOSM : topography.getElements(PedestrianOSM.class)) {
pedestrianOSM.clearStrides();
maxStepSize = Math.max(pedestrianOSM.getDesiredStepSize(), maxStepSize);
maxDesiredSpeed = Math.max(pedestrianOSM.getDesiredSpeed(), maxDesiredSpeed);
}
int counter = 1; int counter = 1;
// event driven update ignores time credits // event driven update ignores time credits
do { do {
mesh = new PMesh(); linkedCellsGrid = new LinkedCellsGrid<>(new VRectangle(topography.getBounds()), sideLength);
Collection<VPoint> pedPoints = topography.getElements(PedestrianOSM.class)
.stream()
.map(ped -> ped.getPosition())
.collect(Collectors.toList());
triangulation = new IncrementalTriangulation(mesh);
for(PedestrianOSM pedestrianOSM : topography.getElements(PedestrianOSM.class)) {
PHalfEdge halfEdge = triangulation.insert(pedestrianOSM.getPosition().getX(), pedestrianOSM.getPosition().getY());
PVertex vertex = triangulation.getMesh().getVertex(halfEdge);
triangulation.getMesh().setData(vertex, "pedestrian", pedestrianOSM);
map.put(pedestrianOSM, vertex);
}
triangulation.finish();
if(panel == null) {
panel = new MeshPanel<>(mesh, 1000, 1000);
panel.display();
}
else {
panel.getMeshRenderer().setMesh(mesh);
}
/*for(PVertex pedestrianPoint : mesh.getVertices()) {
map.put(mesh.getPoint(pedestrianPoint).pedestrianOSM, pedestrianPoint);
}*/
panel.repaint();
double stepSize = Math.max(maxStepSize, maxDesiredSpeed * timeStepInSec);
linkedCellsGrid = new LinkedCellsGrid<>(new VRectangle(topography.getBounds()), (pedestrianPotentialWidth));
locked = new boolean[linkedCellsGrid.getGridWidth()][linkedCellsGrid.getGridHeight()]; locked = new boolean[linkedCellsGrid.getGridWidth()][linkedCellsGrid.getGridHeight()];
List<PedestrianOSM> parallelUpdatablePeds = new ArrayList<>(); List<PedestrianOSM> updateAbleAgents = new LinkedList<>();
List<PedestrianOSM> unUpdatablePedsd = new ArrayList<>(); List<PedestrianOSM> notUpdateAbleAgents = new LinkedList<>();
while (!pedestrianEventsQueue.isEmpty() && pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec) { while (!pedestrianEventsQueue.isEmpty() && pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec) {
PedestrianOSM ped = pedestrianEventsQueue.poll(); PedestrianOSM ped = pedestrianEventsQueue.poll();
int[] gridPos = linkedCellsGrid.gridPos(ped.getPosition()); int[] gridPos = linkedCellsGrid.gridPos(ped.getPosition());
boolean requiresUpdate = requireUpdate(ped); // lock cell of the agent
if(!locked[gridPos[0]][gridPos[1]]) {
if(!locked[gridPos[0]][gridPos[1]] && requiresUpdate) { updateAbleAgents.add(ped);
parallelUpdatablePeds.add(ped);
}
else if(requiresUpdate) {
unUpdatablePedsd.add(ped);
}
if(requiresUpdate) { // lock neighbours
for(int y = -1; y <= 1; y++) { for(int y = -1; y <= 1; y++) {
for(int x = -1; x <= 1; x++) { for(int x = -1; x <= 1; x++) {
int col = Math.min(locked.length-1, Math.max(0, gridPos[0]+x)); int col = Math.min(locked.length-1, Math.max(0, gridPos[0]+x));
...@@ -135,158 +79,22 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven { ...@@ -135,158 +79,22 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
locked[col][row] = true; locked[col][row] = true;
} }
} }
} } else {
notUpdateAbleAgents.add(ped);
if(!requiresUpdate) {
double stepDuration = ped.getDurationNextStep();
ped.setTimeOfNextStep(ped.getTimeOfNextStep() + stepDuration);
pedestrianEventsQueue.add(ped);
count++;
} }
} }
//logger.info("update " + parallelUpdatablePeds.size() + " in parallel in round " + counter + ".");
parallelUpdatablePeds.stream().forEach(ped -> { logger.debug("update " + updateAbleAgents.size() + " in parallel in round " + counter + ".");
logger.debug("not updated " + notUpdateAbleAgents.size() + " " + counter + ".");
updateAbleAgents.parallelStream().forEach(ped -> {
//logger.info(ped.getTimeOfNextStep()); //logger.info(ped.getTimeOfNextStep());
//System.out.println(ped.getId()); //System.out.println(ped.getId());
update(ped, timeStepInSec, currentTimeInSec); update(ped, timeStepInSec, currentTimeInSec);
}); });
pedestrianEventsQueue.addAll(notUpdateAbleAgents);
pedestrianEventsQueue.addAll(unUpdatablePedsd); pedestrianEventsQueue.addAll(updateAbleAgents);
pedestrianEventsQueue.addAll(parallelUpdatablePeds);
counter++; counter++;
} while (!pedestrianEventsQueue.isEmpty() && pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec); } while (!pedestrianEventsQueue.isEmpty() && pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec);
logger.info("avoided updates: " + count);
}
private boolean requireUpdate(@NotNull final PedestrianOSM pedestrianOSM) {
PVertex vertex = map.get(pedestrianOSM);
if(hasChanged(pedestrianOSM)) {
return true;
}
for(PVertex v : mesh.getAdjacentVertexIt(vertex)) {
PedestrianOSM ped = triangulation.getMesh().getData(v, "pedestrian", PedestrianOSM.class).get();
if(hasChanged(ped)) {
return true;
}
}
return false;
}
private boolean hasChanged(@NotNull final PedestrianOSM pedestrianOSM) {
return pedestrianOSM.getLastPosition().equals(pedestrianOSM.getPosition());
}
private class PedestrianPoint implements IPoint {
private final PedestrianOSM pedestrianOSM;
private final VPoint point;
public PedestrianPoint(VPoint point, PedestrianOSM pedestrianOSM) {
this.point = point;
this.pedestrianOSM = pedestrianOSM;
}
private boolean hasChanged() {
//System.out.println(pedestrianOSM.getTrajectory().getTrajectory().size());
return pedestrianOSM.getTrajectory().isEmpty() || pedestrianOSM.getTrajectory().getFootSteps().peekLast().length() > 0;
}
@Override
public double getX() {
return point.getX();
}
@Override
public double getY() {
return point.getY();
}
@Override
public IPoint add(IPoint point) {
return this.point.add(point);
}
@Override
public IPoint add(double x, double y) {
return point.add(x, y);
}
@Override
public IPoint addPrecise(IPoint point) {
return this.point.addPrecise(point);
}
@Override
public IPoint subtract(IPoint point) {
return this.point.subtract(point);
}
@Override
public IPoint multiply(IPoint point) {
return this.point.multiply(point);
}
@Override
public IPoint scalarMultiply(double factor) {
return this.point.scalarMultiply(factor);
}
@Override
public IPoint rotate(double radAngle) {
return this.point.rotate(radAngle);
}
@Override
public double scalarProduct(IPoint point) {
return this.point.scalarProduct(point);
}
@Override
public IPoint norm() {
return this.point.norm();
}
@Override
public IPoint norm(double len) {
return this.point.norm(len);
}
@Override
public IPoint normZeroSafe() {
return this.point.normZeroSafe();
}
@Override
public double distance(IPoint other) {
return this.point.distance(other);
}
@Override
public double distance(double x, double y) {
return this.point.distance(x, y);
}
@Override
public double distanceSq(IPoint other) {
return this.point.distanceSq(other);
}
@Override
public double distanceSq(double x, double y) {
return this.point.distanceSq(x, y);
}
@Override
public double distanceToOrigin() {
return this.point.distanceToOrigin();
}
@Override
public PedestrianPoint clone() {
return new PedestrianPoint(this.point, pedestrianOSM.clone());
}
} }
} }
...@@ -42,7 +42,11 @@ public interface UpdateSchemeOSM extends DynamicElementRemoveListener<Pedestrian ...@@ -42,7 +42,11 @@ public interface UpdateSchemeOSM extends DynamicElementRemoveListener<Pedestrian
} }
} }
static UpdateSchemeOSM create(@NotNull final UpdateType updateType, @NotNull final Topography topography, final Random random) { static UpdateSchemeOSM create(
@NotNull final UpdateType updateType,
@NotNull final Topography topography,