【问题标题】:How to properly use memory dynamically allocated in C++ dll within Matlab如何在 Matlab 中正确使用 C++ dll 中动态分配的内存
【发布时间】:2015-07-14 01:15:57
【问题描述】:

我编写了一个 C++ 接口 dll 来调用英特尔集成性能基元 (IPP) 库中的一些关键图像处理统计测量方法,以便我们可以利用 SIMD 功能。我能够使用 calllib 将两个 2D Matlab 数组传递给函数

A = single( rand(3,4) );
B = single( rand(3,2) );

pOut = calllib('IPPInterface', 'myFunc', A' , B' , size(A,1), size(A,2) , size(B,1), size(B,2) );

在 C++ 中,myFunc 具有以下签名,以及 body 的 sn-p...

float* myFunc( float A[] , float B[] , int nRowsA , int nColsA , int nRowsB , int nColsB )
{
    ...
    float[] pDst = new float[nRowsA*nColsA];
    ...
    return pDst;
}

我不确定的是 Matlab 如何以及是否成功从内存中删除此类缓冲区。它们最终以 lib.pointers 的形式出现在 Matlab 进程中:

>> class(pOut)

ans =

lib.pointer

我只是好奇我所做的是否是一个坏主意,或者调用 Matlab 的 clear pOut 是否会处理所有事情并避免可能的内存泄漏。

【问题讨论】:

  • 值得注意的是,Matlab不能为你删除内存,因为有几十个native allocator,都是互不兼容的,而且你没有向Matlab表明是哪个一个正在使用中。
  • @BenVoigt 我不熟悉不兼容的本机分配器的概念,您是指跨操作系统平台还是在给定操作系统内?我知道不同的分配方式有不同的行为,比如 calloc、malloc、C++ new,但是如果我想到的例子完全符合这种不兼容的概念的话。
  • 我说的是malloc vs new vs new[] vs HeapAlloc vs VirtualAlloc vs SysAllocString vs SafeArrayCreateVector vs CoTaskMemAlloc vs .NET 垃圾收集器.还有一个事实是,一个编译器提供的new 与另一个编译器提供的不同(这就是操作系统提供HeapAlloc 的原因——所以你可以独立于你的编译器),最重要的是,C++允许重载::operator new,因此它甚至不使用编译器提供的实现。
  • 导出返回的指针甚至可能根本不是动态分配的——它可能是指向内存映射文件的指针,或者是 DLL 中具有静态生命周期的全局变量。或者它可能是一个指向更大动态分配中间的指针。最后,除非您以某种方式告诉它要使用哪个函数,否则 Matlab 无法正确解除分配。您所希望的最好结果是能够为 Matlab 指定一个释放函数,以便在 Matlab 对象被垃圾回收时调用。
  • @BenVoigt solid,这是我在整理我一直在研究的所有这些多语言内容时必须开始欣赏的那种想法。这些动态类型语言处理了很多细节,但我所做的确实是在 Matlab 之外的,它不可能知道如何处理发送的实体。我对 Matlab 的假设太多了,现在我知道并且可以在跨越其他语言障碍时提出类似的问题。非常感谢。

标签: c++ matlab dll loadlibrary dynamic-allocation


【解决方案1】:

所以我一直在通过在 Matlab 中创建如下两个数组来进行一些内存测试...

I = single( rand( 1200 , 1600 ) );
T = single( rand( 100  , 100  ) );

然后我将我的函数放入一个循环中,将内存使用情况打印到文本文件并清除返回的 libpointer。

for i = 1:10000
    lp = calllib('IPPInterface', 'myFunc', I , T , size(I,2) , size(I,1) , size(T,2) , size(T,1) );
    clear lp;

    [u,s] = memory;

    fprintf( fileID ,'%13g    %13s\n' ,  u.MemUsedMATLAB , s.SystemMemory.Available );
end 

走这条路肯定会填满我的物理内存,如下所示,并且让我相信我所做的事情是个坏主意,Matlab 并没有像你这样以某种自动垃圾收集方式处理这个问题。

>> memory
Maximum possible array:              38799 MB (4.068e+010 bytes) *
Memory available for all arrays:     38799 MB (4.068e+010 bytes) *
Memory used by MATLAB:               21393 MB (2.243e+010 bytes)
Physical Memory (RAM):               34814 MB (3.650e+010 bytes)

*  Limited by System Memory (physical + swap file) available.
>> clear all
>> memory
Maximum possible array:              38803 MB (4.069e+010 bytes) *
Memory available for all arrays:     38803 MB (4.069e+010 bytes) *
Memory used by MATLAB:               21388 MB (2.243e+010 bytes)
Physical Memory (RAM):               34814 MB (3.650e+010 bytes)

*  Limited by System Memory (physical + swap file) available.
>> 

如果我关闭 Matlab,操作系统自然会回收所有内存。

在挖掘了 Matlab 的网站后,我确实找到了一个足够接近的示例,该示例在共享库中动态分配了一个 c-struct,后来 Matlab 不得不调用在同一个库中编写的函数,其唯一任务是删除该结构。

Working with Pointer Arguments; Multilevel Pointers

这个例子是正确的,在实现对共享库的简单接口调用以释放我的数组并在我完成后使用它之后

void deallocateArray( float* A )
{
    delete[] A;
}

内存配置文件是平坦的,整个 10000 次迭代完成得更快...

for i = 1:10000
    lp = calllib('IPPInterface', 'myFunc', I , T , size(I,2) , size(I,1) , size(T,2) , size(T,1) );
    calllib('IPPInterface', 'deallocateArray', lp );
    clear lp;

    [u,s] = memory;

    fprintf( fileID ,'%13g    %13s\n' ,  u.MemUsedMATLAB , s.SystemMemory.Available );
end 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    • 1970-01-01
    • 1970-01-01
    • 2018-09-21
    • 2018-10-16
    • 1970-01-01
    • 2017-05-08
    相关资源
    最近更新 更多