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

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
default E rayCastingPolygon(@NotNull final E inEdge,
@NotNull final VPoint q,
@NotNull final VPoint p,
@NotNull final Predicate<E> stopCondition,
@NotNull final LinkedList<E> visitedEdges) {
@NotNull final Predicate<E> stopCondition) {
E outEdge = null;
E outIfInside = null;
......@@ -2413,8 +2412,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
default E walkAroundBoundaryStraight(@NotNull final E inEdge,
@NotNull final VPoint q,
@NotNull final VPoint p,
@NotNull final Predicate<E> stopCondition,
@NotNull final LinkedList<E> visitedEdges) {
@NotNull final Predicate<E> stopCondition) {
E outEdge = null;
E outIfInside = null;
F face = getMesh().getFace(inEdge);
......@@ -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)) {
return rayCastingPolygon(inEdge, q, p, stopCondition, visitedEdges);
return rayCastingPolygon(inEdge, q, p, stopCondition);
} else {
return outEdge;
}
......@@ -2478,7 +2476,7 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
@NotNull final VPoint q,
@NotNull final VPoint p,
@NotNull final Predicate<E> stopCondition,
@NotNull final LinkedList<E> visitedEdges) {
@Nullable final LinkedList<E> visitedEdges) {
E outEdge = null;
F face = getMesh().getFace(inEdge);
......@@ -2492,8 +2490,8 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
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());
outEdge = walkAroundBoundaryStraight(inEdge, q, p, stopCondition, visitedEdges);
//outEdge = rayCastingPolygon(inEdge, q, p, stopCondition, visitedEdges);
outEdge = walkAroundBoundaryStraight(inEdge, q, p, stopCondition);
//outEdge = rayCastingPolygon(inEdge, q, p, stopCondition);
// the point outside
if(outEdge == null) {
return Optional.empty();
......@@ -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
if(iPoint1.distanceSq(p) <= iPoint2.distanceSq(p)) {
// TODO this is too expensive!
outEdge = rayCastingPolygon(inEdge, q, p, stopCondition, visitedEdges);
outEdge = rayCastingPolygon(inEdge, q, p, stopCondition);
}
// the point outside
......@@ -2566,7 +2564,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
return Optional.of(getMesh().getTwin(nextOutEdge));
}
else {
visitedEdges.add(nextOutEdge);
if(visitedEdges != null) {
visitedEdges.add(nextOutEdge);
}
return Optional.empty();
}
......@@ -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>.
*/
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
* @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) {
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
* @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 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>.
*/
default LinkedList<E> straightGatherWalk2D(
......@@ -2671,7 +2672,8 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
@NotNull final VPoint pDirection,
@NotNull final F startFace,
@NotNull final Predicate<E> stopCondition,
@NotNull final boolean directional) {
final boolean directional,
final boolean gather) {
LinkedList<E> visitedEdges = new LinkedList<>();
assert contains(q.getX(), q.getY(), startFace);
......@@ -2713,6 +2715,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
p = pDirection;
// if this is true we are already done
if(contains(pDirection.getX(), pDirection.getY(), startFace)) {
if(!gather) {
visitedEdges.clear();
}
visitedEdges.add(getMesh().getEdge(startFace));
return visitedEdges;
}
......@@ -2737,6 +2742,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
throw new IllegalArgumentException("did not find any edge.");
}
if(!gather) {
visitedEdges.clear();
}
visitedEdges.addLast(inEdge);
......@@ -2809,6 +2817,9 @@ public interface ITriConnectivity<V extends IVertex, E extends IHalfEdge, F exte
if(optEdge.isPresent()) {
inEdge = optEdge.get();
if(!gather) {
visitedEdges.clear();
}
visitedEdges.addLast(inEdge);
// special case (1): hitting the border i.e. outer boundary
......
......@@ -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;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
......@@ -27,107 +28,50 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
private final static Logger logger = Logger.getLogger(UpdateSchemeEventDrivenParallel.class);
static {
logger.setDebug();
}
private final Topography topography;
private LinkedCellsGrid<PedestrianOSM> linkedCellsGrid;
private boolean[][] locked;
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) {
super(topography);
this.topography = topography;
this.pedestrianPotentialWidth = pedestrianPotentialWidth;
this.map = new HashMap<>();
}
@Override
public void update(final double timeStepInSec, final double currentTimeInSec) {
int count = 0;
// construct delaunay triangulation
topography.getElements(PedestrianOSM.class).parallelStream().forEach(pedestrianOSM -> pedestrianOSM.clearStrides());
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);
/*for(PedestrianOSM pedestrianOSM : topography.getElements(PedestrianOSM.class)) {
pedestrianOSM.clearStrides();
}
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);
}
double stepSize = Math.max(maxStepSize, maxDesiredSpeed * timeStepInSec);
double sideLength = (stepSize+pedestrianPotentialWidth) * 2.0;
logger.debug("initial grid with a grid edge length equal to " + sideLength);
int counter = 1;
// event driven update ignores time credits
do {
mesh = new PMesh();
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));
linkedCellsGrid = new LinkedCellsGrid<>(new VRectangle(topography.getBounds()), sideLength);
locked = new boolean[linkedCellsGrid.getGridWidth()][linkedCellsGrid.getGridHeight()];
List<PedestrianOSM> parallelUpdatablePeds = new ArrayList<>();
List<PedestrianOSM> unUpdatablePedsd = new ArrayList<>();
List<PedestrianOSM> updateAbleAgents = new LinkedList<>();
List<PedestrianOSM> notUpdateAbleAgents = new LinkedList<>();
while (!pedestrianEventsQueue.isEmpty() && pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec) {
PedestrianOSM ped = pedestrianEventsQueue.poll();
int[] gridPos = linkedCellsGrid.gridPos(ped.getPosition());
boolean requiresUpdate = requireUpdate(ped);
if(!locked[gridPos[0]][gridPos[1]] && requiresUpdate) {
parallelUpdatablePeds.add(ped);
}
else if(requiresUpdate) {
unUpdatablePedsd.add(ped);
}
// lock cell of the agent
if(!locked[gridPos[0]][gridPos[1]]) {
updateAbleAgents.add(ped);
if(requiresUpdate) {
// lock neighbours
for(int y = -1; y <= 1; y++) {
for(int x = -1; x <= 1; x++) {
int col = Math.min(locked.length-1, Math.max(0, gridPos[0]+x));
......@@ -135,158 +79,22 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
locked[col][row] = true;
}
}
}
if(!requiresUpdate) {
double stepDuration = ped.getDurationNextStep();
ped.setTimeOfNextStep(ped.getTimeOfNextStep() + stepDuration);
pedestrianEventsQueue.add(ped);
count++;
} else {
notUpdateAbleAgents.add(ped);
}
}
//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());
//System.out.println(ped.getId());
update(ped, timeStepInSec, currentTimeInSec);
});
pedestrianEventsQueue.addAll(unUpdatablePedsd);
pedestrianEventsQueue.addAll(parallelUpdatablePeds);
pedestrianEventsQueue.addAll(notUpdateAbleAgents);
pedestrianEventsQueue.addAll(updateAbleAgents);
counter++;
} 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
}
}
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,
final Random random,
final double maxAgentPotentialInfluenceRadius) {
switch (updateType) {
case SEQUENTIAL: return new UpdateSchemeSequential(topography);
case PARALLEL: return new UpdateSchemeParallel(topography);
......@@ -51,7 +55,7 @@ public interface UpdateSchemeOSM extends DynamicElementRemoveListener<Pedestrian
//TODO: magic number!
case EVENT_DRIVEN_PARALLEL:
case EVENT_DRIVEN_CL:
return new UpdateSchemeEventDrivenParallel(topography, 1.4);
return new UpdateSchemeEventDrivenParallel(topography, maxAgentPotentialInfluenceRadius);
default: throw new IllegalArgumentException(updateType + " is not supported.");
}
}
......
......@@ -51,19 +51,31 @@ public class PotentialFieldPedestrianCompact implements PotentialFieldAgent {
}
private AttributesPotentialCompact attributes;
private AttributesAgent attributesAgent;
private double width;
private double height;
public PotentialFieldPedestrianCompact() {}
@Override
public void initialize(List<Attributes> attributesList, Domain topography,
public void initialize(List<Attributes> attributesList, Domain domain,
AttributesAgent attributesPedestrian, Random random) {
this.attributes = Model.findAttributes(attributesList, AttributesPotentialCompact.class);
this.attributesAgent = domain.getTopography().getAttributesPedestrian();
this.width = attributes.getPedPotentialWidth();
this.height = attributes.getPedPotentialHeight();
}
@Override
public double getMaximalInfluenceRadius() {
if(attributes.isUseHardBodyShell()) {
return width + attributesAgent.getRadius();
}
else {
return width;
}
}
@Override
public Collection<Pedestrian> getRelevantAgents(@NotNull final VCircle stepDisc,
Agent pedestrian, Topography scenario) {
......
......@@ -25,6 +25,7 @@ import java.util.Random;
public class PotentialFieldPedestrianCompactSoftshell implements PotentialFieldAgent {
private AttributesPotentialCompactSoftshell attributes;
private AttributesAgent attributesAgent;
private double intimateWidth; // radius of intimate zone \delta_{int}
private double personalWidth; // radius of personal width \delta_{per}
private double height; // intensity of repulsion \mu_p
......@@ -32,14 +33,20 @@ public class PotentialFieldPedestrianCompactSoftshell implements PotentialFieldA
public PotentialFieldPedestrianCompactSoftshell() {}
@Override
public void initialize(List<Attributes> attributesList, Domain topography,
public void initialize(List<Attributes> attributesList, Domain domain,
AttributesAgent attributesPedestrian, Random random) {
this.attributes = Model.findAttributes(attributesList, AttributesPotentialCompactSoftshell.class);
this.attributesAgent = domain.getTopography().getAttributesPedestrian();
this.intimateWidth = attributes.getPedPotentialIntimateSpaceWidth();
this.personalWidth = attributes.getPedPotentialPersonalSpaceWidth();
this.height = attributes.getPedPotentialHeight();
}
@Override
public double getMaximalInfluenceRadius() {
return Math.max(personalWidth, intimateWidth) + attributesAgent.getRadius();
}
@Override
public Collection<Pedestrian> getRelevantAgents(VCircle maxStepCircle,
Agent pedestrian, Topography scenario) {
......
......@@ -23,13 +23,20 @@ import java.util.Random;
public class PotentialFieldPedestrianOSM implements PotentialFieldAgent {
private AttributesPotentialOSM attributes;
private AttributesAgent attributesAgent;
public PotentialFieldPedestrianOSM() {}
@Override
public void initialize(List<Attributes> attributesList, Domain topography,
public void initialize(List<Attributes> attributesList, Domain domain,
AttributesAgent attributesPedestrian, Random random) {
this.attributes = Model.findAttributes(attributesList, AttributesPotentialOSM.class);
this.attributesAgent = domain.getTopography().getAttributesPedestrian();
}
@Override
public double getMaximalInfluenceRadius() {
return attributesAgent.getRadius() + attributes.getPedestrianRepulsionWidth();
}
@Override
......
......@@ -30,6 +30,10 @@ public interface PotentialFieldAgent extends Model {
@Override
default void update(double simTimeInSec) {}
default double getMaximalInfluenceRadius() {
return Double.POSITIVE_INFINITY;
}
/**
* Computes the pedestrians possessing a potential that reaches into the
* given relevantArea.
......
......@@ -156,7 +156,7 @@ public class PotentialFieldTarget implements IPotentialFieldTarget {
}*/
// point lies outside
if(domain.getTopography().distanceToObstacle(pos) <= 0) {
if(domain.getTopography().distanceToObstacle(pos, caller) <= 0) {
return Double.MAX_VALUE;
}
......
......@@ -236,7 +236,7 @@ public class Topography implements DynamicElementMover{
return -obstacleDistanceFunction.apply(point);
}
public double distanceToObstacle(@NotNull final IPoint point, final Agent caller) {
public double distanceToObstacle(@NotNull final IPoint point, final Object caller) {
return -obstacleDistanceFunction.apply(point, caller);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment