在我的自定义物理引擎中,最大的瓶颈是从空间分区(2D网格)获取所有物体的方法,并返回仅包含指向身体的唯一指针的集合。
template<typename T, typename V> bool contains(const T& mContainer, const V& mValue)
{
return std::find(std::begin(mContainer),
std::end(mContainer), mValue) != std::end(mContainer);
}
const vector<Body*>& GridInfo::getBodiesToCheck()
{
bodiesToCheck.clear();
for(auto& query : queries)
for(auto& body : *query)
if(!contains(bodiesToCheck, body)) bodiesToCheck.push_back(body);
return bodiesToCheck;
}
使用分析器显示瓶颈在“包含”方法中。
显然,std::unordered_set
将是这里的“理想”解决方案。但是,它比当前解决方案慢很多。我也尝试了google::dense_hash_set
,它比std::unordered_set
快,但仍比当前解决方案慢。
const unordered_set<Body*>& GridInfo::getBodiesToCheck()
{
bodiesToCheck.clear();
for(auto& query : queries)
for(auto& body : *query)
/*if(!contains(bodiesToCheck, body))*/ bodiesToCheck.insert(body);
return bodiesToCheck;
}
为什么“正确”的容器比std::vector
慢?
有什么方法可以进一步加快这种方法的发展吗?
答案 0 :(得分:4)
我能想到两种可能性:
contains
函数在unordered_set
中查找元素,而不是使用成员函数find
。答案 1 :(得分:1)
如果复制实体的数量与其他实体相比不是那么高,则可以选择将所有实体推入向量中,然后删除重复实体。但这需要std::sort
后跟erase(std::unique, end)
。
但值得一试,考虑到你的向量似乎无论如何都要超过std::unordered_set
,它没有相同的内存位置和像std::vector
那样的简单访问。
答案 2 :(得分:0)
我不确定我是否正确理解了问题,但似乎std::vector
/ std::find
上的查找速度较慢,但迭代可能比std::unordered_set
更快。如果是这种情况,并且您不受内存限制的限制,则可以混合使用两种方法:
使用元素维护std::unordered_set
和std::vector
。在std::unordered_set
内查找以确定元素是否已存在,如果不存在,则将其添加到两个容器中。最后迭代std::vector
。
请注意,您可以向两个容器提供有关它们将包含的“预期”元素数量的提示,这将减少内存分配/重新散列的数量。
答案 3 :(得分:0)
我遇到了类似的问题,即线性搜索的速度比哈希加比较查找的速度快。(支持Mark的第一个答案)。
我尝试使用BFS来改善网格的CPU体素化。 std::unordered_set
用于标记访问过的体素。但是,unordered_set
比线性迭代空间慢100%。通过配置文件比较,我发现如果活动体素在所有访问的体素中的比率高于3%
,则线性搜索会更快。否则,使用unordered_set
的BFS更好。
答案 4 :(得分:-2)
以下是您在std文档中找到的内容:
“unordered_set容器比使用它们的键访问单个元素的set容器更快,尽管它们通过其元素的子集进行范围迭代的效率通常较低。”
好了,因为find方法最终会遍历相当多的元素,这可能就是原因......
也许如果你使用了costum哈希函数,你应该改进它以使它更快......我只能想到......