【问题标题】:Why recursive memory deallocation so slow?为什么递归内存释放这么慢?
【发布时间】:2013-08-02 22:23:12
【问题描述】:

我制作了一个八叉树来快速匹配 3 维点。而且速度很快!但是,删除八叉树比构建八叉树需要多 100 倍的时间。我不明白为什么会这样。这是我的课:

#pragma once
#include "LeakCheck.h"
#include "vec3.h"

namespace Geometry 
{

static const float tolerance = 1.0e-30f;

class VertexOctree
{
private:
    float halfSize;
    vec3 center;
    VertexOctree *subTrees;
    int vertexIndex;
    void CreateSubTree()
    {
        subTrees = news VertexOctree[8];
        subTrees[0] = VertexOctree(center+(vec3(-1.0f,-1.0f,-1.0f)*halfSize),halfSize*0.5f);
        subTrees[1] = VertexOctree(center+(vec3(+1.0f,-1.0f,-1.0f)*halfSize),halfSize*0.5f);
        subTrees[2] = VertexOctree(center+(vec3(-1.0f,+1.0f,-1.0f)*halfSize),halfSize*0.5f);
        subTrees[3] = VertexOctree(center+(vec3(+1.0f,+1.0f,-1.0f)*halfSize),halfSize*0.5f);
        subTrees[4] = VertexOctree(center+(vec3(-1.0f,-1.0f,+1.0f)*halfSize),halfSize*0.5f);
        subTrees[5] = VertexOctree(center+(vec3(+1.0f,-1.0f,+1.0f)*halfSize),halfSize*0.5f);
        subTrees[6] = VertexOctree(center+(vec3(-1.0f,+1.0f,+1.0f)*halfSize),halfSize*0.5f);
        subTrees[7] = VertexOctree(center+(vec3(+1.0f,+1.0f,+1.0f)*halfSize),halfSize*0.5f);
    }
public:
    int AddVertex(std::vector<vec3> &VertexList, const vec3& Point)
    {
        if (vertexIndex == -1) {
            vertexIndex = VertexList.size();
            VertexList.push_back(Point);
            return vertexIndex;
        }
        if ((VertexList[vertexIndex]-Point).lengthSq() < tolerance) {
            return vertexIndex;
        }
        if (subTrees == NULL)
            CreateSubTree();

        return subTrees[(Point.x>center.x)+(2*(Point.y>center.y))+(4*(Point.z>center.z))].AddVertex(VertexList, Point);
    }
    VertexOctree()
    {
        subTrees = NULL;
        vertexIndex = -1;
    }
    VertexOctree(vec3 Center, float HalfSize)
    {
        subTrees = NULL;
        center = Center;
        halfSize = HalfSize;
        vertexIndex = -1;
    }
    ~VertexOctree()
    {
        if (subTrees)
            delete[] subTrees;
    }
};

};

删除 VertexOctree 需要很长时间。比创建还必须进行浮点运算来比较点和分配内存的树要长得多。为什么删除这么慢?我使用 Visual Studio 2012 并在发布模式下编译。

【问题讨论】:

  • 这是发布还是调试版本?调试构建会很慢,因为它会在释放以供重用之前填充所有已取消分配的内存(以检测您是否正在重用它)。
  • Visual Studio 2012 并在发布模式下编译。我的意思是发布版本。
  • 您不需要测试subTrees. delete 运算符已经这样做了。做两次没有任何好处。
  • 我曾经有一个程序需要 4 个小时来运行析构函数。 delete 如果解除分配的顺序与分配的顺序完全没有关系,并且您实际上有数千万个对象,那么这可能会非常慢。参考地点绝对很重要。
  • 我已经用 c++ 编程了十多年,从不知道你可以删除 NULL 指针。如果句子浪费了,那就是 4000!谢谢!

标签: c++ performance memory-management heap-memory


【解决方案1】:

当您按 F5 运行您的程序时,它使用一个特殊的、较慢的调试堆,即使在发布模式下也是如此。如果按 ctrl+F5,它会使用常规堆,即使在调试模式下也是如此。试试看,如果它加快了速度,那么在项目的调试属性中,在环境框中输入 _NO_DEBUG_HEAP=1 以始终使用快速堆。

【讨论】:

  • 做到了!非常感谢。我不知道那件事。这对调试有何影响?无论如何,我认为不可能在发布版本中进行任何调试。
  • 不客气!我认为调试堆会额外检查您没有覆盖缓冲区或写入已删除的内存。
  • 您可以在调试的情况下运行发布模式,但这更难,因为代码可能由于优化而被更改。
  • 要使该注释完整,请不要在调试版本或调试环境中测试性能。 Quonox的评论是经典评论,只关注第一类问题,这是第二类问题。
  • 在我的辩护中,我正在测试发布版本的性能。我不知道那还在调试。这有点误导......
猜你喜欢
  • 1970-01-01
  • 2012-11-12
  • 2011-10-31
  • 1970-01-01
  • 2012-02-13
  • 2016-11-06
  • 1970-01-01
  • 2016-10-28
  • 2013-01-12
相关资源
最近更新 更多