【发布时间】:2015-01-07 10:04:18
【问题描述】:
我目前正在学习 C++,因此我正在将我之前用 Python 编写的 A* 寻路算法转换为 C++。尽管对 C++ 库中所有不同类型的数据类型了解不多,但我还是决定投入其中。
完成程序编写后,C++ 版本的运行速度比 Python 版本慢(该程序使用 std::map 而不是 Python 字典来存储移动成本)。不管您是否知道寻路,是否有人可以查看我的代码并告诉它为什么运行效率如此低下?
我运行了 Visual Studios Profiler 来检查效率如此低下的原因(我知道队列可用于加快搜索速度,但请记住,在 Python 中使用相同的代码且没有优先级队列的情况下,它的运行速度要快 50 倍)..似乎几乎所有时间都被 std::map [] 运算符使用:
Function Name Total CPU (%) -> 88.01 %
+ std::map<std::pair<int,int>,int,std::less<std::pair<int,int>>,
std::allocator<std::pair<std::pair<int,int> const ,int> > >::
operator[]
我的代码:
void findPath(pair<int, int> startLocation, pair<int, int> endLocation){
vector<pair<int, int>> openSet;
vector<pair<int, int>> closedSet;
openSet.push_back(startLocation);
map<pair<int, int>, pair<int, int>> cameFrom;
map<pair<int, int>, int> gCosts;
map<pair<int, int>, int> fCosts;
gCosts[startLocation] = 0;
fCosts[startLocation] = heuristic(startLocation, endLocation);
pair<int, int> currentNode;
while (openSet.size() > 0){
currentNode = openSet[0];
for (std::vector<pair<int, int>>::iterator it = openSet.begin(); it != openSet.end(); ++it){
pair<int, int> node = *it;
if (fCosts[node] < fCosts[currentNode])
currentNode = node;
}
if (DEBUG){
cout << "Current Node: " << currentNode.first << " " << currentNode.second << endl;
}
if (currentNode == endLocation){
break;
}
openSet.erase( remove(openSet.begin(), openSet.end(), currentNode), openSet.end() );
closedSet.push_back(currentNode);
vector<pair<int, int>> neighbors = getNeighbors(currentNode);
for (std::vector<pair<int, int>>::iterator it = neighbors.begin(); it != neighbors.end(); ++it){
pair<int, int> neighbor = *it;
if (std::find(closedSet.begin(), closedSet.end(), neighbor) != closedSet.end()) {
continue;
}
int possiblegCost = gCosts[currentNode] + heuristic(currentNode, neighbor);
bool inOpenSet = find(openSet.begin(), openSet.end(), neighbor) != openSet.end();
if (!inOpenSet || (possiblegCost < gCosts[neighbor])) {
cameFrom[neighbor] = currentNode;
gCosts[neighbor] = possiblegCost;
fCosts[neighbor] = possiblegCost + heuristic(neighbor, endLocation);
/*if (DEBUG){
console() << "Modifying neighbor: " << neighbor.first << "," << neighbor.second << " Costs of: "
<< gCosts[neighbor] << " " << fCosts[neighbor] << endl;
}*/
if (!inOpenSet){
openSet.push_back(neighbor);
}
}
}
}
}
【问题讨论】:
-
尝试使用
std::unordered_map而不是普通的旧std::map,它使用散列可以充分加快您的程序。 -
您是否正在运行优化的构建?
-
@TartanLlama 可能值得一提的是,这还需要为
std::pair<int, int>添加一个特化,或者像我描述的here 那样指定一个散列函数。 -
小微优化,但您可以将
while (openSet.size() > 0)替换为while (!myset.empty()) -
你为什么总是把自己定位在
openSet[0]?当你找到一个成本较低的节点时,你push_back,所以它在向量的末尾。您并没有真正正确使用 C++。例如,在第二个for循环中,您总是声明neighbour。在 C++ 中,这转换为:调用pair构造函数,它是operator=。因此,微优化是将pair放在循环之前。
标签: c++ visual-c++ path-finding stdmap