c++(哈希)映射速度优化
C++ (hash) map speed optimization
我正在制作一款游戏,但是我在地图性能方面遇到了麻烦。
在每次渲染/更新调用中,我必须循环遍历列表中的每个块。当我移动到块边界时,一些块(只是那些需要添加或删除的块)将被添加和删除到列表中(一个接一个)。
这需要花费很长时间,并且会严重影响我的游戏表现。如果我移除更新循环,我的FPS将增加100!
for(pair<const DWORD, Chunk*>& pair : loadedChunks){
Chunk* c = pair.second;
if(c != NULL){
c->update(delta); //Does totally nothing
}
}
(目前列表中有205个块)
这是我当前的实现:
unordered_map<DWORD, Chunk*> loadedChunks;
void ChunkManager::addChunk(int x, int y, int z){
Chunk* chunk = new Chunk(this, x, y, z);
rebuildChunks.push_back(chunk);
loadedChunks.emplace(((x & 0xFFFF)) << 16 | ((y & 0xFFFF) << 8) | (z & 0xFFFF), chunk);
}
void ChunkManager::removeChunk(int x, int y, int z){
long key = ((x & 0xFFFF)) << 16 | ((y & 0xFFFF) << 8) | (z & 0xFFFF);
delete loadedChunks[key];
loadedChunks.erase(key);
}
Chunk* ChunkManager::getChunkAt(int x, int y, int z){
if(loadedChunks.find(((x & 0xFFFF)) << 16 | ((y & 0xFFFF) << 8) | (z & 0xFFFF)) != loadedChunks.end()){
return loadedChunks[((x & 0xFFFF)) << 16 | ((y & 0xFFFF) << 8) | (z & 0xFFFF)];
}else{
return NULL;
}
}
我想知道是否有一个更快的地图,或者如果我在我的实现中做错了什么。
如果这是唯一可能的方法,我愿意使用外部库。
另一种可能性是使用std::vector
列表与XYZ;
注意:
哈希键:((x &0 xffff) & lt; & lt;16 | (y &0 xffff) & lt; & lt;8) | (z &0 xffff)。它不是完美的,因为它只允许0 - 255的值,但它现在可以工作,它比使用字符串更好,因为字符串的性能甚至更差,根据这篇文章
.
编辑:在评论中,有人指出FPS不是一个很好的指标,所以我使用了这个计时器:
unsigned int start = clock();
for(pair<const DWORD, Chunk*>& pair : loadedChunks){
Chunk* c = pair.second;
if(c != NULL){
c->update(delta);
}
}
unsigned int timepassed = clock() - start;
OutputDebugString((LPCWSTR) wstring(to_wstring(timepassed) + L"n").c_str());
,输出在1 &2毫秒。(这大约是我的渲染所需要的时间…仅用于循环遍历包含205个项目的列表)
编辑2:我决定通过添加计时器来减少循环的数量:
tickTimer+=delta;
if(tickTimer >= 0.05){
for(pair<const DWORD, Chunk*>& pair : loadedChunks){
pair.second->update(delta);
}
tickTimer = 0;
}
这样每秒只运行20次。
编辑3:@brianbeuning有一个非常好的观点,我正在使用MSVS并使用调试模式,这样所有的代码都运行得很慢。
我的超能力告诉我地图上的物品比你想象的要多。可能是程序中其他地方的错误没有从映射中删除项目。
修改主循环:
int count = 0;
int nullcount = 0;
for(pair<const DWORD, Chunk*>& pair : loadedChunks){
Chunk* c = pair.second;
if(c != NULL){
c->update(delta);
count++;
}
else {
nullcount++;
}
}
unsigned int timepassed = clock() - start;
OutputDebugString((LPCWSTR) wstring(to_wstring(timepassed) + L" items:" + to_wstring(count) + L" nullitems" + to_wstring(nullcount) + L"n").c_str());
现在打印什么?
嗯,我不知道你在优化时使用的编译器有多好,但是你在removeChunk()和getChunkAt()中都评估了同样的事情两次。例如,在getChunkAt中,首先应该存储由loadedChunks.find()
返回的迭代器,然后在单独的语句中测试它是否为NULL,如果不是,则返回其->second
。你可以在removecchunk()中做类似的优化。
顺便说一句,我不知道你在代码的其他地方做什么,但在addChunk()你创建一个新的块,保存在rebuildChunks 和把它放在loaddchunks地图。然而,在removeChunk()中,您使用loadedChunks[key]中的指针删除块,但是在您的代码片段中没有任何内容可以从rebuildChunks中删除块。如果它还在,你就有了一个悬浮指针
如果迭代速度很重要,请尝试使用map
而不是unordered_map
—unordered_map
以更大的内存使用和更慢的迭代为代价为您提供更快的查找/插入/删除。
- 解析参数后内联以优化算法速度
- 需要帮助优化C++中循环/点积函数的速度
- 编译器优化如何影响数据加载速度
- 优化.txt文件的创建速度
- 优化一个简单的方程式,用于C 中的执行速度
- 叮当 OSX 行军 = 原生 大约 1/3 速度没有优化
- 如何优化此数学操作以换取速度
- 当局部变量被复制到全局变量时,C++GCC优化速度会减慢
- STL算法是否针对速度进行了优化
- 优化最近邻居大小调整算法以提高速度
- C++正则表达式速度优化
- c++ 与 MATLAB 针对速度的优化.例如,我的 matlab 代码运行速度比 c++ 快
- 如何使用android ndk(速度优化)优化本地代码
- 可能的代码速度优化
- Visual Studio 2010-最适合优化的大小或速度
- 整数三角函数的c++库,速度优化与可选的近似
- c++(哈希)映射速度优化
- 在不同优化级别访问gcc/g++中的局部变量与全局变量的速度
- 如何优化交易算法以获得最有效的速度
- 如何优化 3D 复杂阵列的"for 循环"<double>以提高C++速度