2010-06-24 135 views
5

黑族社区,删除指针的时间

我对删除指针有个小问题。

我正在使用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

编辑:我刚刚发现,即测量这些删除的计算的速度很慢,因为我没有在释放模式编译。由于调试器发挥作用,我测量了这些(最终虚幻)数字,这让我很头疼。最终的程序会自动进行自动优化,以便几乎不再有时间参与删除操作。

反正:感谢所有有用的答案!他们给了我很多额外的知识和想法!

+1

“inDaten”,“inDaten2”和“copy”中的对象的类型是什么?它们只是整数或类似的东西,还是它们是真实的物体? – 2010-06-24 12:01:33

+1

你需要动态分配一切吗?你需要这么多的*单独的*分配吗?是否有可能重写程序来存储更少,更大的分配数据? – jalf 2010-06-24 12:06:12

+0

在我的上网本上,删除double []并没有达到下一个时钟周期,所以无论是用附加的调试器运行,还是在阵列中元素的析构函数中发生了一些昂贵的事情。 – 2010-06-24 12:06:34

回答

3

delete[]也会为数组的每个元素调用析构函数,这会增加时间,除非析构函数是微不足道的。

除此之外 - 是的,动态内存分配相对昂贵。如果你无法容忍它 - 试着分配更少的更大块,或者不要在时间关键的东西中进行动态分配。

智能指针不会有太大帮助 - 它们会在内部执行相同的释放操作。它们不是为了加速,而是为了方便设计。

1

如果您在程序结束时删除它们,并且运行析构函数并不重要,则只需省略删除 - 操作系统将取消分配内存。否则,尝试使用单个间接指针,即不要使用指针指针数组。除了减少删除时间,这也会改善参考的地点。

+2

无法保证操作系统将释放任何内存。 – Yacoby 2010-06-24 11:55:42

+3

@Yacoby:除非操作系统本身给出这样的保证。任何现代(桌面)操作系统都可以。 – jalf 2010-06-24 12:05:50

+0

无论操作系统是否清理出口处的进程内存,依靠这样的拐杖仍然是不好的做法。最好使用更适合快速释放的分配器,和/或重新设计代码以尽量减少释放(当然,不会引入泄漏)。 – Void 2010-06-24 23:10:55

2

这里有一个有趣的线程“Memory Allocation/Deallocation Bottleneck?

分配和释放需要很长的时间,因此是你拥有的最常见的昂贵的操作之一。这是因为堆管理必须处理一堆事情。在调试模式下,通常也会在内存块上进行更多的检查。如果你在发布配置中有相同的时间,我会感到惊讶,通常至少有两个因素在起作用。有了私有堆,你可以大大增加事物。如果你总是分配相同大小的对象,那么内存池可能是最好的选择。

0

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

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

1

看起来问题出在你的数据结构中。为什么你需要这么多的动态分配?可以做些什么来减少分配数量?

如果释放指针需要2秒钟,它可能至少需要分配它们。

只要退出程序,就可以避免释放它们。 C++并不保证所分配的内存会发生什么,但是你的操作系统可能会这样做,所以在实际的条款中,它可能是一个简单的方法来削减2秒的执行时间。

但是,这仍然留下> 2秒的分配。

我认为,最好的办法是尝试更好地构建数据。你能向我们展示矩阵当前的结构吗?

+0

使用1-dim矩阵节省时间!你对结构是正确的。矩阵包含pinys的灰度(如1024x1024等)。 但仍然:分配是比解除分配方式更快(测量明智) – Baradrist 2010-06-24 12:35:56

0

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

反正:再次谢谢!祝你有愉快的一天!

Baradrist

+0

使用一维矩阵应该做的伎俩 - 谢谢! – Baradrist 2010-06-24 12:28:47

0

如果对象指出,在你的阵列有不平凡的析构函数没有太多可以做,以提高显著运行时不解决,第一。否则:

而不是使指针的大小isizeinDaten, inDaten2 and copy阵列尺寸isize数组为什么不能让他们大小isize*isize的阵列和,而不是解决与个别项目:array[i][j]array[i*isize+j]解决这些问题。 这样你就可以打电话给delete []

1

不应该是这样:

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

因为使用的,他们显然阵列。 (至少他们看起来也是,你没有提供足够的上下文)。

+0

是的,它应该是 - 已经改变它,但它不会改变时间数字=)。 – Baradrist 2010-06-24 12:18:58

0

对此的优化是以区块形式分配内存,分配带有新位置的单个指针并在删除时删除整个区块。

但是,您必须小心谨慎,因为此选项隐含地暗示不会调用每个分配了新位置的对象的析构函数。

1

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

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; 
}; 

第二个明显的事情是,而不是三个矩阵,有一个矩阵是由具有你所需要的数据的构成。这是假设一个元组矩阵就足够了,这似乎是你发布的代码的情况。

如果你真的想去核心,并需要多个矩阵,然后编写你自己的内存分配器。您可以一次为多个矩阵分配内存,并使用新的放置位置来构造它们。如果你想这样做,需要进一步的阅读和学习,因为编写内存分配器不是一件小事:你需要考虑像对齐这样的问题,但这是最快的方法。

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

缺乏显而易见的算法效率低下,即使是非常有知识的程序员也往往对其代码中的瓶颈不正确。如果效率是一个主要问题,那么剖析器就是您最好的朋友。

0

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