C++ 4d 数组内存释放很慢

Posted

技术标签:

【中文标题】C++ 4d 数组内存释放很慢【英文标题】:C++ 4d array memory deallocation is slow 【发布时间】:2017-05-01 14:32:51 【问题描述】:

我的代码中有一个 4D 矩阵,用于解决一些数学问题

int**** Sads = new int***[inputImage->HeightLines];
for (size_t i = 0; i < inputImage->HeightLines; i++)

    Sads[i] = new int**[inputImage->WidthColumns];
    for (size_t j = 0; j < inputImage->WidthColumns; j++)
    
        Sads[i][j] = new int*[W_SIZE];
        for (size_t k = 0; k < W_SIZE; k++)
         
              Sads[i][j][k] = new int[W_SIZE];
         
    
 

//do something with Sads...

for (int i = 0; i < inputImage->HeightLines; i++)
        
            int*** tempI = Sads[i];
            for (int j = 0; j < inputImage->WidthColumns; j++)
            
                int** tempJ = tempI[j];
                for (int k = 0; k < W_SIZE; k++)
                
                    delete[] tempJ[k];
                
                delete[] Sads[i][j];
            
            delete[] Sads[i];
        
        delete[] Sads;

大小非常大 WidthColumns = 2018, HeightLines = 1332, W_SIZE =7,内存分配非常快但内存释放(删除)非常慢。 有没有办法优化它? 我厌倦了openMP,但它会抛出不相关的缺少DLL的错误……如果我删除了#pragma omp parallel,一切正常。但是很慢……

【问题讨论】:

您正在运行发布版本吗?我已经看到了 Visual Studio 中的调试版本的执行时间比发布版本长 100 倍的情况,因为在调试版本中会发生额外的检查,例如堆损坏测试。还要考虑一维数组。 为了爱宇宙中所有邪恶的事物,请使用std::vector 和适当的智能指针。 @CaptainObvlious 我做到了并不快 @drescherjm 我将更改为发布,我不知道速度因素在内存分配中如此疯狂,但是我也在尝试进行 TDD 单元测试并在调试模式下运行它们,所以我想也许有人有更好的方法。一维数组当然意味着索引游戏,但也许这是要走的路。谢谢 那个代码比好莱坞星光大道的星星还多。 【参考方案1】:

使用指向...的指针是个坏主意,因为它会大量分割您的数据。

我会创建一个类来管理索引转换并使用一维数组,它有点复杂但会更快。

无论如何,一个技巧:没有什么可以阻止您使用指向内存中非稀疏区域的指针(您预先分配的一维数组)构建您的 int****,然后将其用作 4D 数组。

【讨论】:

Richard 的评论是正确的。我知道这很糟糕,我在寻求更好的方法 @RichardHodges 这将问题归为“过于宽泛”的类别。【参考方案2】:

我可能倾向于使用std::vector。现在内存分配已经为我处理好了(在一次分配/释放中),我得到了免费的复制/移动语义。

我所要做的就是提供偏移量计算:

#include <vector>
#include <cstddef>

struct vector4

    vector4(std::size_t lines, std::size_t columns)
            : lines_(lines), columns_(columns)
    , storage_(totalSize())
    

    auto totalSize() const -> std::size_t
    
        return lines_ * columns_ * w_size * w_size;
    

    int* at(std::size_t a)
    
        return storage_.data() + (a * columns_ * w_size * w_size);
    

    int* at(std::size_t a, std::size_t b)
    
        return at(a) + (b * w_size * w_size);
    

    int* at(std::size_t a, std::size_t b, std::size_t c)
    
        return at(a, b) + (c * w_size);
    

    int& at(std::size_t a, std::size_t b, std::size_t c, std::size_t d)
    
        return *(at(a, b, c) + d);
    

private:

    std::size_t lines_, columns_;
    static constexpr std::size_t w_size = 32; // ?
    std::vector<int> storage_;

;

int main()

    auto v = vector4(20, 20);
    v.at(3, 2, 5, 1) = 6;
    // other things

    // now let it go out of scope

【讨论】:

为什么是auto totalSize() const -&gt; std::size_t 而不是std::size_t totalSize() const?有没有我想念的微妙之处? @YSC 这两种形式在 c++11 中是等价的 我知道,但你为什么要使用奇怪的形式auto -&gt; type,在那里你可以使用我们几十年来都习惯的形式?无论如何,我并不是说这是批评,我只是好奇。 @YSC 我出于习惯使用自动表单,如果我碰巧需要它添加尾随返回类型(就像我在这种情况下所做的那样,因为我在定义之前调用了函数) @YSC 虽然你可以看到我不一致:)【参考方案3】:

投反对票的人,我更正了这段代码,这在更正之前确实很糟糕。还有什么值得投反对票的吗?如果有,说什么。如果不是,请重新考虑您的投票。


创建、使用和删除4D数组的正确方法是这样的,使用语句组的闭包来删除自动变量。


    const int H = 10;
    const int I = 10;
    const int J = 10;
    const int K = 10;
    int h = 0;
    int i = 0;
    int j = 0;
    int k = 0;
    int fourDimArray [H][I][J][K];
    fourDimArray[h][i][j][k] = 0;

如果您需要动态分配,则可以使用 STL 的列表或向量类,或者使用类似的方法以及内联方法,如果您需要极快的速度,则可以从 4D 数组索引计算 1D 数组的索引。

p>
int * fourDimArrayAsOneDim = new int[H*I*J*K];
fourDimArrayAsOneDim[indexFromIndices(h, i, j, k)] = 0;
delete [] fourDimArrayAsOneDim;

【讨论】:

这是不合法的 c++ 更正以正确编译并提供一些选项。道歉。

以上是关于C++ 4d 数组内存释放很慢的主要内容,如果未能解决你的问题,请参考以下文章

C++之申请释放内存(对象数组和99乘法表)

C++ 对象的动态建立 & 释放

C++ 关于内存泄露问题。内存泄露是指用new 分配的内存没有用delete释放,如果未释放会有啥后果?

C++ 删除不会释放所有内存 (Windows)

互操作 C++ 时释放分配的内存

无法释放 C++ 中 CreateFileMapping 和 MapViewOfFile 创建的共享内存