删除指针的时间

时间:2010-06-24 11:50:26

标签: c++ pointers memory-management

Hei社区,

我有一个关于删除指针的小问题。

我正在使用Dimension 1024x1024的指针指针矩阵。由于我是动态创建的,因此我在程序结束时删除了为它们分配的空间。但是在通常的循环中执行此操作会花费相当多的时间 - 我使用处理器的时钟速率测量了大约2秒。当程序运行仅15秒时,2秒是巨大的 - 加上:使用这些分配的指针的函数被调用超过一次......。

以下是测量的时间关键代码,包括测量:

time=clock();
for(i=0;i<xSize;i++){            //xSize is dynamic, but 1024 for the measurement
    delete [] inDaten[i];
    delete [] inDaten2[i];
    delete [] copy[i];
}
delete inDaten; delete inDaten2; delete copy;
time=clock()-time;
     time/=CLOCKS_PER_SEC;

删除指针总是这么久吗?或者我只是以错误的方式做事?

我希望有人可以帮助我解决这个问题。由于我正在优化一个非常复杂的程序以便更快地运行,因此我无法使用这些2秒的代码。与所有其他部分相比,它的速度太慢了。但我仍然需要能够动态地实现这个代码。 SmartPointers可能会有所帮助,但如果我理解正确,他们也需要时间来删除自己 - 只是在不同的时间......

感谢您的回答!

Baradrist

编辑:我刚刚发现,测量这些删除计算的速度非常慢,因为我没有在发布模式下编译它。由于调试器发挥作用,我测量了这些(最终不真实的)数字让我头疼。最终程序自动优化,以便几乎不再有任何时间参与删除。

无论如何:感谢所有有用的答案!他们给了我很多额外的知识和事情要考虑!!!!

12 个答案:

答案 0 :(得分:3)

delete[]也会为数组的每个元素调用析构函数,这会增加时间,除非析构函数很简单。

除此之外 - 是的,动态内存分配相对昂贵。如果你不能容忍它 - 尝试分配更小的更大的块或者在时间关键的东西中没有动态分配。

智能指针无济于事 - 它们将在内部进行相同的释放。它们不是为了加速,而是为了设计方便。

答案 1 :(得分:2)

这是一个有趣的主题“Memory Allocation/Deallocation Bottleneck?

分配和解除分配需要很长时间,因此是您拥有的最常见的高成本操作之一。这是因为堆管理必须处理一堆事情。通常在调试模式下还会对内存块进行更多检查。如果您在发布配置中有相同的时间,我会感到惊讶,通常在至少2之间有一个因素。使用私有堆,您可以大大增加事情。如果您始终分配相同大小的对象,则内存池可能是最佳选择。

答案 2 :(得分:1)

如果在程序结束时删除它们并且无法运行多个析构函数,只需省略删除 - 操作系统将释放内存。否则,尝试使用单个间接,即没有指向指针的数组。除了减少删除时间,这也将改善参考的位置。

答案 3 :(得分:1)

看起来问题出在数据结构中。为什么需要这么多动态分配?可以采取哪些措施来减少分配数量?

如果释放指针需要2秒钟,那么分配它们的时间可能至少相同。

只需提前退出程序即可避免释放它们。 C ++不保证当前分配的内存会发生什么,但是你的操作系统可能会这样做,所以在实用术语中,它可能是一个简单的方法来减少执行时间2秒。

但是仍然留下了&gt;分配时间为2秒。

我认为,最好的办法是尝试更好地构建数据。您能告诉我们目前矩阵的结构吗?

答案 4 :(得分:1)

不应该是:

delete [] inDaten; delete [] inDaten2; delete [] copy;

因为使用它们显然是数组。 (至少他们看起来也是如此,你没有提供足够的背景)。

答案 5 :(得分:1)

你没有说数组中的对象有多大,但是如果它们足够大,那么部分内存可能被换出并需要重新交换(或者可能只是重新映射回进程)空间),这导致你看到的时间。

答案 6 :(得分:0)

尝试创建自己的内存分配方法,以便减少销毁时间。

例如,从Os请求一块内存并将数组分配给它,以便您可以在一个操作中释放整个块。

答案 7 :(得分:0)

非常感谢所有快速答案!很高兴看到有人帮助=)。仍然为我的问题似乎我必须处理这种时间损失,因为我需要动态数组作为较小的子程序中的临时矩阵,而不是在最后执行。

无论如何:再次感谢!!祝你有愉快的一天!

Baradrist

答案 8 :(得分:0)

如果数组中指向的对象具有非平凡的析构函数,那么在没有首先解决的情况下,您可以做很多事情来显着改善运行时。否则:

为什么不将大小为inDaten, inDaten2 and copy的数组指向大小为isize的数组的isize数组,而不是使用以下内容来处理单个项目: isize*isize使用array[i][j]解决这些问题。 这样您就可以通过拨打array[i*isize+j]来清理。

答案 9 :(得分:0)

对此的优化是以块的形式分配内存,使用placement new分配单个指针,删除后只删除整个块。

你必须要小心,因为这个选项隐含地不会为使用placement new分配的每个对象调用析构函数。

答案 10 :(得分:0)

如果您已确定内存分配/解除分配是瓶颈并希望更快,那么第一个明显的解决方案是为阵列使用连续缓冲区。您仍然可以提供一个矩阵接口,可以像二维数组一样访问它们。

// Rudimentary Implementation
template <class T>
class SquareMatrix
{
public:
    explicit SquareMatrix(int i_size): 
        size(i_size), mat(new T[i_size * i_size]) {}

    ~SquareMatrix()
    {
        delete[] mat;
    }

    // could also be column depending on row-major/col-major
    T* operator[](unsigned int row)
    {
        return mat + row * size;
    }

    // could also be column depending on row-major/col-major
    const T* operator[](unsigned int row) const
    {
        return mat + row * size;
    }

private:
    unsigned int size;
    T* mat;
};

第二个显而易见的事情是,有一个矩阵由一个包含你需要的所有数据的结构组成,而不是三个矩阵。这假设一个元组矩阵就足够了,这就像你发布的代码一样。

如果你真的想要硬核并需要多个矩阵,那么为此编写自己的内存分配器。您可以一次为多个矩阵分配内存,只需使用placement new构建它们。如果你想这样做需要进一步阅读和学习,因为编写内存分配器并不是一项简单的任务:你需要考虑对齐等问题,但这是最快的方法。

我建议您仍然使用分析器,而不是依赖于时序测试,并对代码进行正确的调用图分析。这将告诉你究竟花了多少时间在哪里。例如,可能是矩阵中物体的构造/破坏并不像它那样便宜。

缺乏明显的算法效率低下,即使是知识渊博的程序员也常常对其代码中的瓶颈不正确。如果效率是一个主要问题,那么探查器是你最好的朋友。

答案 11 :(得分:0)

如果矩阵中指针引用的所有对象都是相同的类型(或者至少是相同的大小),则可以分配一大块内存来保存它们并就地初始化它们。