1
votes

Currently I have some trouble with my Pathfinding system which is "anormally" slow on my big graph:

My Graph

  • Graph properties: 16814 vertices / 61512 edges
  • Graph is directed.
  • Each vertex has an ID of subgraph (Island ID) → No solution between subgraph BUT ALWAYS inside same subgraph.

Each vertex of graph is defines by:

  • type (rock, sand, ...).
  • height

Last rule, earth is not connect to ocean (so we have many sub-graph).

Small demo design

My Astar configuration

My heuristic is very classic: I compute dot between current vertex position and goal position.

I don't have a pre-compute weight for edges. I use "complexe" algo (depends of speed of walker, kind of ground, if we go up or down)

float PathWorld::updateWeight(const Agent& agent, const EdgeInfo& edgeInfo) const
{
    const Agent::Navigation& navigation = agent.getNavigation();

    const auto& fromTerrain = edgeInfo._from->_terrain;
    const auto& toTerrain   = edgeInfo._to->_terrain;

    const float mean = (navigation._speed.at(fromTerrain._type) + navigation._speed.at(toTerrain._type)) * 0.5f;
    const float diff = BT::Maths::clamp((1000.0f + toTerrain._height - fromTerrain._height) / 1000.0f, 0.5f, 2.0f);

    return edgeInfo._distance / mean * diff;
}

Issues

Currently, the execution time take less than 1ms to 1 second when I compute one path. The path solution is just between 8 or 80 vertices and I don't have proportionnal time. (So 8 vertices path can take 1 second and 80 vertices path take 1 ms).

I make a quick profiling with visual Studio: boost is my bottleneck.

Code and testing data

All complete code and testing data can be found on my GitHub.

https://github.com/Rominitch/myBlogSource/tree/master/DEMO/TestPathfinding

The easy/small demo don't suffer of my issue. Just complexe case. All graphes was generated by same program (not published).

My Testing program output

My testing program is really dummy: - I take a node to start into my graph - I take XXX nodes after this (using index) and compute path.

Outputs:

Statistics:
 Start node: Ocean H= 0 SubGraph= 2
 nbValid: 2053/15000   (valid path / number of path computed)
 min / max: 1/75       (number of vertex in path computed)
 min time for one path: 0 ms
 max time for one path: 7 ms

Statistics:
 Start node: Forest H= 100 SubGraph= 1
 nbValid: 1420/1500
 min / max: 1/76
 min time for one path: 0 ms
 max time for one path: 558 ms

Statistics:
 Start node: Swamp H= 50 SubGraph= 1
 nbValid: 601/1000
 min / max: 1/51
 min time for one path: 0 ms
 max time for one path: 1246 ms

Statistics:
 Start node: Clay H= 300 SubGraph= 22
 nbValid: 138/15000
 min / max: 1/12
 min time for one path: 0 ms
 max time for one path: 0 ms

Questions

  • Where is my issue ? (bad boost using / bad graph / boost limitation)
  • Boost is a good choose to resolve pathfinding (another library) ?
  • Can we optimize my graph data (best boost algo, reduce data duplication, ...) ?

Thanks !

1
Haven't looked at your code, but I'm in the process of implementing one in c++ as well. I'm using this: groebelsloot.com/2015/12/24/pathfinding-part-1, which relies heavily on this: david-gouveia.com/pathfinding-on-a-2d-polygonal-map. - Roger Rapid
@Roger Rapid: Thanks I do something similar (into my graph generator): I use sketchup to make polygon in 2D plane, I create convex polygon using CGAL library and compute connectivity + graph info. But my issue is on Astar ! I will look in details your article. - Rominitch
"boost is my bottleneck" - no wonder, if you implement your core logic with library X, library X should be your bottle-neck - sehe
@sehe Sorry for this dummy sentence ! I want to say: all time is spend inside boost part (it's my profiler report not a personnal belief). I have two suspicions way: graph issue (= too many useless edge), or bad boost using (I use directed edge but I use it as bidirectional with multi-weight) or both. - Rominitch

1 Answers

2
votes

Ok ! I found my issue.

Currently, Bug was inside my heuristic implementation which doesn't compute square of distance between current node and goal. It's just make a "quasi random" heuristic.

Moreover, in my case

boost::astar_search

is less performant than

boost::astar_search_tree

Finally, I optimized my graph too (remove dummy edges).

New stats:

Statistics:
  Start node: Ocean H= 0 SubGraph= 2
  nbValid: 2028/15000
  min / max: 1/145
  min time for one path: 0 ms
  max time for one path: 13 ms
  mean: 0 ms
  Global time: 1845 ms

Statistics:
  Start node: Forest H= 100 SubGraph= 1
  nbValid: 1420/1500
  min / max: 1/92
  min time for one path: 0 ms
  max time for one path: 13 ms
  mean: 0 ms
  Global time: 1232 ms

Statistics:
  Start node: Swamp H= 50 SubGraph= 1
  nbValid: 601/1000
  min / max: 1/50
  min time for one path: 0 ms
  max time for one path: 11 ms
  mean: 0 ms
  Global time: 504 ms

Statistics:
  Start node: Clay H= 300 SubGraph= 23
  nbValid: 138/15000
  min / max: 1/17
  min time for one path: 0 ms
  max time for one path: 1 ms
  mean: 0 ms
  Global time: 115 ms