将地图与矢量和缓存影响结合使用
Using map in conjunction with vector and cache impact
我正在考虑使用map
将自定义ID映射到vector
索引,例如;
struct Mesh
{
GLsizei mIndices;
GLuint mVBO;
GLuint mIndexBuffer;
GLuint mVAO;
size_t vertexDataSize;
size_t normalDataSize;
};
typedef uint32_t MeshID;
std::map<MeshID, uint16_t> gMeshIDIndexMap;
std::vector<Mesh> gMeshes;
std::vector<MeshID> drawCmds = {1, 1, 2, 3, 4, 5, 8, ,8 ,8, 9, 10, ...}; //sorted
std::for_each(drawCmds.begin(), drawCmds.end(), [](MeshID& id)
{
Mesh& mesh = gMeshes[gMeshIDIndexMap.at(id)];
glBindVertexArray(mesh.mVAO);
glDrawElements(GL_TRIANGLES, mesh.mIndexBuffer, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
....
}
由于 std::map 不将其元素存储在连续内存中,因此在每次新的迭代中,gMeshIDIndexMap.at(id)
都必须将一个全新的缓存行加载到缓存中。这会破坏缓存并导致大量缓存未命中,对吗?我该怎么做才能改进这一点并尽可能少地获得缓存未命中?
如果您 (1( 首先用数据填充地图,然后 (2( 使用它进行查找,(3( 最后当你完成后销毁它,那么boost::container::flat_map
可能对你来说是一个不错的选择。它基本上是一个排序向量。优点(无耻地从网站上窃取(:
- 查找速度比标准关联容器更快
- 迭代速度比标准关联容器快得多 减少小对象的内存消耗
- (如果shrink_to_fit,则减少大对象的内存消耗被使用(
- 改进了缓存性能(数据存储在连续内存中(
潜在的缺点:
- 最坏情况下的线性时间插入和线性时间删除
观察结果是,容器通常根据上述模式使用(填充数据 - 用于查找 - 销毁(。如果您的用法符合此模式,则排序向量可能是一个不错的选择。
您需要将网格ID放入网格中。如果您知道或者可以对地图中的元素数量给出合理的估计,您甚至可以提前预留空间,这样就不必由于底层矢量的缓冲区重新分配而移动元素。
我的建议与ComicSansMS的回答基本相同;我只建议你使用提升容器,而不是滚动自己的flat_map。
当然,您的使用模式可能如下所示:您执行 (a( 查找或 (b( 在随机位置删除或 (c( 在随机位置插入;在地图的整个生命周期中,您执行 (a( 或 (b( 或 (c( 看似随机的操作。在这种情况下,基于节点的容器(如 std::map
(可能是更好的选择。
相关文章:
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 多态性和功能结合
- 为什么擦除方法会影响结束方法
- 内联如何影响模块接口中的成员函数
- 为什么返回类型的'const'限定符对标有 __forceinline/内联的函数没有影响?
- 将 Vulkan 与 SFML 结合使用?
- 在容量内调整矢量大小时的性能影响
- 重载运算符的范围是什么?它是否会影响作为类成员的集合的插入函数?
- 未达到的情况会影响开关外壳性能
- 将 c++ 生成器应用程序与外部 dll 结合使用
- 如何将增强MSM与增强信号结合使用?
- 循环仅对第一行正常工作.其他行不受 for 的影响
- MS Visual Studio 解决方案结合了非托管C++项目和 C# 项目
- 处理影响跨不同线程共享对象的定时回调的最佳方法是什么?
- 模板如何影响C++中隐式声明的规则?
- 函数未在作用域中声明 / 如何结合使用 header.h、header.cpp 和 main.cpp?
- 命名空间信息会影响C++的可读性
- [[可能]]和[[不太可能]]影响程序汇编的简单示例?
- 如何保护非托管应用程序中的字符串不受进程转储的影响
- 将地图与矢量和缓存影响结合使用