【问题标题】:Large vectors and memory conservation c++大向量和内存保护c ++
【发布时间】:2020-03-15 17:24:48
【问题描述】:

我正在用 C++ 制作一个瓦片地图编辑器。目前,在编辑地图时,其属性存储在三个向量中:

vector<vector<vector<bool>>> CanvasCollisionObstruction; //[collision,obstruction][map x][map y]
vector<vector<vector<bool>>> CanvasZoneOverlays; //zone overlays for programmable map zones [zone type][map x][map y]
vector<vector<vector<canvasClip>>> CanvasClips; //identifies which sprite occupies this tile [layer number][map x][map y]

在上述向量中,第 2 维和第 3 维([map x] 和 [map y])指的是地图上的实际瓦片坐标。这些只是普通的旧方形二维地图。最后一个向量的类型是以下结构:

struct canvasClip
{
    int tileset;
    int clip;
    //initialization to check if it's in-use
    canvasClip() : tileset(-1), clip(-1) {}
    bool isInitialized()
    {//a clip is only rendered if it is initialized
        return ((tileset >= 0) && (clip >= 0));
    }
    bool operator==(const canvasClip& a) const
    {//used in flood-fill to compare with target tile
        return ((tileset == a.tileset) && (clip == a.clip));
    }
    bool operator!=(const canvasClip& a) const
    {//used in flood-fill to compare with target tile
        return ((tileset != a.tileset) || (clip != a.clip));
    }
};

对于这个应用程序,我希望最终生成大小超过 50000x50000 瓦片的地图,跨越无限(但可能永远不会超过 10 个)层。总共大约有 12 个区域,而且这个数字是恒定的。

地图编辑器具有一些用于更改地图大小的控件(数字输入和按钮)。当我将地图大小设置为一个非常大的数字时,我会在每个向量上调用 vector.resize(),然后我可以在任务管理器中看到我的内存使用量快速上升,直到我的计算机最终崩溃。

谁能给我一些关于处理非常大的向量的建议或技巧?我是否将不得不做一些事情,比如压缩矢量,以便单个索引描述相似图块的跨度?我是否应该将地图存储在文件而不是内存中,然后根据需要一次只读回几块?

优秀的程序员如何处理这种情况?

【问题讨论】:

  • 我会将 3x3x3 向量隐藏在只有一个平面向量的类中,并将 3x3x3 位置(通过类的公共 API)转换为内部平面向量。如果向量的数据实际上太大而无法舒适地放入内存中,我会让类换入/换出到后备存储文件。
  • 您希望用户同时在多个层上工作吗?我可以想到一个解决方案,该解决方案涉及将所有图层存储在一个文件中,除了当前图层以及可能在任一缩放方向上的两个图层。现在,每当用户进入新图层(缩放级别)时,您都可以在缩放方向上再加载一个。如果你保持这种平衡,你应该能够有足够的内存来管理所有的瓦片,你只需要一个 2d 矢量而不是你当前管理的疯狂的 3d 地图。您可以在不损害响应能力的情况下完成所有这些操作
  • vector&lt;vector&lt;vector&lt;canvasClip&gt;&gt;&gt; CanvasClips,假设 10 层和 50000x50000 地图,仅数据需要 50 GB,假设 16 位 int - 需要存储在 RAM 中。对于 32 位 int,该要求高达 100GB。这还不包括std::vectors 本身的开销。优秀的程序员会进行这种计算,并找到另一种方式来表示他们的数据——例如只将一部分数据保留在内存中,并找到一种根据需要读取数据的方式。
  • 我有点好奇 50,000x50,000 瓦片地图的用例。如果每个图块是 1 平方英尺,那么整个地图将接近 90 平方英里!假设这是一款游戏,根据this 列表,您的地图将是有史以来第 16 大地图!
  • @boxcartenant 您能否尝试仅加载可见的地图部分,然后将其余部分保存在文件中,以便在您靠近时加载它?

标签: c++ c++11 vector large-data


【解决方案1】:

正如在 cmets 中已经提到的,您正在尝试仅为数据分配大量内存。

在这种情况下,你必须选择不同的数据结构来存储和操作。

以下是一些最简单的技巧,您可以应用这些技巧来降低操作数据的代码的复杂性:

  1. 您的默认值似乎毫无意义。为什么不只将设置为真值的数据存储在内存中?
  2. 您只能将数据的可见部分存储在内存中(请参阅Here's what's happening in Horizon: Zero Dawn every time you move a camera )。
  3. 您可能需要打包数据结构并处理对齐方式(请参阅Data structure alignment)。

当然,有时您必须限制要求,但这是生活的一部分。

【讨论】:

    猜你喜欢
    • 2010-11-29
    • 1970-01-01
    • 2013-07-11
    • 2016-01-20
    • 2012-06-14
    • 2010-09-24
    • 2010-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多