首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在MATLAB中查看变量使用的实际内存?

如何在MATLAB中查看变量使用的实际内存?
EN

Stack Overflow用户
提问于 2018-04-28 07:03:20
回答 3查看 2.1K关注 0票数 7

当我试图使用MATLAB的复制(懒散复制)机制从一个单元格数组中的多个单元格连接相同的大矩阵时,我想知道是否有一种方法可以判断我是否做得对。

例如:

代码语言:javascript
复制
img = randn(500);
[dx,dy] = gradient(img);
S = cell(2,2);
S{1,1} = dx.^2;
S{2,2} = dy.^2;
S{1,2} = dx.*dy;
S{2,1} = S{1,2};  % should be a reference, as long as not modified

但是看看whos的输出

代码语言:javascript
复制
>> whos
  Name        Size               Bytes  Class     Attributes

  S           2x2              8000448  cell                
  dx        500x500            2000000  double              
  dy        500x500            2000000  double              
  img       500x500            2000000  double              

我希望看到S占据6 MB,而不是8 MB。

有没有办法验证程序中没有错误,而这两个单元格在结尾仍然引用相同的数组?

我知道memory函数,但遗憾的是它只适用于MacOS平台(我在MacOS上)。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2018-05-02 20:38:25

编辑:

在编辑答案之前,我使用了一个无文档的函数,它具有意想不到的行为,而且它的签名在不同版本的MATLAB之间并不稳定,所以这里我提供了@CrisLuengo答案的扩展版本。

我们可以使用哈希映射在递归函数check_shared中存储数据元素及其关联的check_shared的唯一地址,并获取数据大小。请注意,在这里,我们可以检查单元格中的共享状态,也不能检查单元格之外的元素,它们的地址与单元格元素的地址相同。

代码语言:javascript
复制
#include "mex.h"
#include <unordered_map>
typedef std::unordered_map<void *,const mxArray *> TableType;

TableType check_shared(const mxArray* arr, TableType table = TableType())
{
    switch (mxGetClassID(arr)) {
        case mxCELL_CLASS:
            for(int i = 0; i < mxGetNumberOfElements (arr); i++) {
                table  = check_shared(mxGetCell (arr,i), std::move(table));
            }
            break;
        case mxSTRUCT_CLASS:
            for (int i = 0; i < mxGetNumberOfFields (arr); i++) {
                for (int j = 0; j < mxGetNumberOfElements (arr); j++) {
                    table = check_shared(mxGetFieldByNumber (arr, j, i), std::move(table));
                }
            }
            break;
        case mxVOID_CLASS:
        case mxFUNCTION_CLASS:
        case mxUNKNOWN_CLASS:
            return table;
    }
    if (!mxIsEmpty (arr)) {
        void* data = mxGetData(arr);
        table[data] = arr;
    }
    return table;
}
uint64_t actual_size(const TableType& table)
{
    uint64_t sz = 0;
    for (const auto& entry : table) {
        const mxArray * arr = entry.second;
        sz += mxGetElementSize (arr) * mxGetNumberOfElements (arr);
    }
    return sz;
}

void mexFunction(int nlhs, mxArray *plhs[],
                 int nrhs, const mxArray *prhs[])
{
    TableType table = check_shared(prhs[0]);
    plhs[0] = mxCreateNumericMatrix(1,1, mxUINT64_CLASS, mxREAL );
    uint64_t* result = static_cast<uint64_t*>(mxGetData (plhs[0]));
    result[0] = actual_size(table);
}

(*)支持基本数据类型,如cellstruct和数字数组。对于未知的数据结构和classdef对象,函数返回零。

票数 2
EN

Stack Overflow用户

发布于 2018-04-29 05:49:23

验证两个特定数组是否真正共享数据的一个可能的解决方案是使用以下从Yair的无文件的MATLAB博客修改的MEX文件

代码语言:javascript
复制
#include "mex.h"
#include <cstdint>
void mexFunction( int /*nlhs*/, mxArray* plhs[], int nrhs, mxArray const* prhs[]) {
   if (nrhs < 1) mexErrMsgTxt("One input required.");
   plhs[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL);
   std::uint64_t* out = static_cast<std::uint64_t*>(mxGetData(plhs[0]));
   out[0] = reinterpret_cast<std::uint64_t>(mxGetData(prhs[0]));
}

将其保存为getaddr.cpp并使用

代码语言:javascript
复制
mex getaddr.cpp

允许进行以下测试:

代码语言:javascript
复制
img = randn(500);
[dx,dy] = gradient(img);
S = cell(2,2);
S{1,1} = dx.^2;
S{2,2} = dy.^2;
S{1,2} = dx.*dy;
S{2,1} = S{1,2};  % should be a reference, as long as not modified

assert(getaddr(S{1,2}) == getaddr(S{2,1}))

这与获取结构S实际使用的内存的摘要不一样(我仍然认为这将是有用的),但它确实允许验证内存是共享的。

票数 3
EN

Stack Overflow用户

发布于 2018-05-01 12:01:55

“是否有一种方法可以验证程序中没有错误,而这两个单元格在结尾仍然引用相同的数组?”

我会试着测量它花了多少时间。因为复制指针比复制数据更快,所以它应该以不同的比例缩放。

这表明了不同之处:

代码语言:javascript
复制
i=500:500:5000;
t=zeros(2,length(i));
for ct=1:length(i)
    img = randn(i(ct));
    [dx,dy] = gradient(img);
    S = cell(2,2);
    S{1,1} = dx.^2;
    S{2,2} = dy.^2;
    S{1,2} = dx.*dy;
    tic;
    S{2,1} = S{1,2};  % should be a reference, as long as not modified
    t(1,ct)=toc;
    tic
    S{2,1} = S{1,2}+1; 
    t(2,ct)=toc;
end
B=(i.^2)*8;
figure(1);clf
subplot(1,2,1);
plot(t(1,:),B,'.')
xlabel('time(s)');ylabel('Bytes');
title(sprintf('reference: no relation'))

subplot(1,2,2);
a=sum(B.*t(2,:))/sum(t(2,:).^2);
plot(t(2,:),B,'.',t(2,:),a*t(2,:))
xlabel('time(s)');ylabel('Bytes');
title(sprintf('datacopy: %.2f GB/s',a/1E9))

所以程序中没有错误。Matlab给出了单元格的错误内存使用量。

mex文件和内存

所以我读了这篇文章:http://undocumentedmatlab.com/blog/matlabs-internal-memory-representation

在MATLAB2018a中,我无法复制结果。printmem适用于从format debug获得的指针,但getaddrprintaddr似乎不再提供相同的指针。

代码语言:javascript
复制
A=1:10
>Structure address = 7d9a3eb0
>m = 1
>n = 10
>pr = 74ed5f20
printaddr(A)
>000000007D894640

用它作为printaddr:

代码语言:javascript
复制
/* printaddr.cpp */
#include "mex.h"
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
   if (nrhs < 1) mexErrMsgTxt("One input required.");
   printf("%p\n", prhs[0]);
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50073860

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档