为什么内存减少了稀疏阵列的相同副本?

1次查看(最近30天)
拉尔斯路德维希
拉尔斯路德维希 于2020年8月7日
编辑: 马特J. 8月8日
A = sparse([1,1],[1,1],[pi],1,1);
aa = a(1:结束,1:结束);
谁是一种;谁是AA.
上面的最小示例显示了我目前无法解释的现象(48字节与AA 32字节)
以何种方式存储在a中的数据不同?

接受的答案

布鲁诺鲁
布鲁诺鲁 于2020年8月7日
编辑:布鲁诺鲁 于2020年8月7日
不,与名称长度无关,它是Matlab保留的('IR“和”PR“旧符号的”公关“和”PR“旧符号)数组的数量。在第一个呼叫稀疏它的2个双打,在第二种情况下,它是1,最小的可能值,或类似的东西。
复制的矩阵甚至具有“虚构”大小,因为必须共享其数据阵列。当数据最终写入后,将复制它。
这些数组将具有相同的大小,因为我们强制保留非零的数量为1。
aaaaaaa =稀疏([1],[1],[pi + pi],1,1,1);%查看sparse的NZ参数
a = aaaaaaa(1:结束,1:结束);
>> Whos Aaaaaaa.
姓名尺寸字节班级属性
AAAAAAA1x1.32.
>> Whos A.
姓名尺寸字节班级属性
一种1x1.32.
4评论
布鲁诺鲁
布鲁诺鲁 8月8日
反向齐手术试验,以查看matlab修剪
根据我的测试, 当NZMAX < 3*NNZ时,MATLAB将独立分配内部数组 但对于大于2的比例,Matlab将修剪
%2D网格无向GRAOH相邻矩阵
[x,y] = ndgrid(1:1000);
n = numel(x);
I1 = sub2ind(大小(X) X (1: end-1,:), Y (1: end-1,:));
j - 1 = I1 (:) + 1;
I2 = sub2ind(size(x),x(:,1:end-1),y(:,1:结束-1));
J2 = I2(:)+大小(x,1);
I0 = [I1(:);I2(:)];
J0 = [J1(:);J2(:)];
[钱数,j₀]=交易([I0 (:); j₀(:)],[j₀(:),I0 (:)));
V0 = 1 + 0(大小(钱数));
%在这里是矩阵
% A = sparse(I0,J0,V0,n,n);
%循环创建不同比例的重复I / J.
为了nrep = 1:0.1:4
%以给定的比例复制I / J.
数控=装天花板(nrep);
P = CEIL(大小(I0,1)* nrep);
I = repmat(钱数,数控,1);
j = repmat(J0,NC,1);
v = repmat(v0,nc,1);
我= I(1:P);
j = j(1:p);
v = v(1:p);
生成稀疏矩阵
=稀疏(I, J, V、n, n);
%检查盈余
fprintf('nrep =%f,分配剩余比率=%f \ n',nrep,nzmax(a)/ nnz(a));
结尾
结果
>>托托
nrep = 1.000000,分配剩余比率= 1.000000
nrep = 1.100000,分配剩余比率= 1.100000
nrep = 1.200000,分配剩余比率= 1.200000
nrep = 1.300000,分配剩余比率= 1.300000
nrep = 1.400000,分配剩余比率= 1.400000
nrep = 1.500000,分配剩余比率= 1.500000
nrep = 1.600000,分配盈余比率= 1.600000
nrep = 1.700000,分配剩余比率= 1.700000
nrep = 1.800000,分配剩余比率= 1.800000
nrep = 1.900000,分配剩余比率= 1.900000
nrep = 2.000000,分配剩余比率= 2.000000%<=你的测试就在这里
nrep = 2.100000,分配剩余比率= 2.100000
nrep = 2.200000,分配剩余比率= 2.200000
nrep = 2.300000,分配剩余比率= 2.300000
nrep = 2.400000,分配剩余比率= 2.400000
nrep = 2.500000,分配剩余比率= 2.500000
nrep = 2.600000,分配剩余比率= 2.600000
nrep = 2.700000,分配剩余比率= 2.700000
nrep = 2.800000,分配剩余比率= 2.800000
nrep = 2.900000,分配盈余率= 2.900000
nrep = 3.000000,分配剩余比率= 1.000000%******它从3 ******修剪
nrep = 3.100000,分配剩余比率= 1.000000
nrep = 3.200000,分配剩余比率= 1.000000
nrep = 3.300000,分配剩余比率= 1.000000
nrep = 3.400000,分配剩余比率= 1.000000
nrep = 3.500000,分配剩余比率= 1.000000
nrep = 3.600000,分配剩余比率= 1.000000
nrep = 3.700000,分配剩余比率= 1.000000
nrep = 3.800000,分配剩余比率= 1.000000
nrep = 3.900000,分配剩余比率= 1.000000
nrep = 4.000000,分配剩余比率= 1.000000
>>

登录评论。

更多的答案(3)

Bjorn Gustavsson.
Bjorn Gustavsson. 于2020年8月7日
它似乎是这样你的16字节的差异就是由于你的名字越来越长 AA.
AA =稀疏([1,1,2],[1,1,2],[PI PI EXP(1)],2,2);
a = aa(1:结束,1:结束);
谁是一种;谁是AA.
%返回:
% Name Size Bytes类属性
% A 2x2 56双稀疏
% Name Size Bytes类属性
%aa 2x2 72双稀疏
由于大小差异似乎是独立于大小的 一种 AA. 而且此示例显示与您的示例相比的相反尺寸......

沃尔特罗伯森
沃尔特罗伯森 于2020年8月7日
编辑:沃尔特罗伯森 于2020年8月7日
AAAAAAA(1:end,1:end)与AAAAAAA本身并不相同。
>> V = [1 -2 3 -4 5]
V =
1 -2 3 -4 5
>>格式调试
> > V
V =
结构地址= 1cc30d9c0.
m = 1
n = 5.
公关= 60 c004eb8b60
1 -2 3 -4 5
>> B = v
B =
结构地址= 1cc30d9c0.
m = 1
n = 5.
公关= 60 c004eb8b60
1 -2 3 -4 5
因此整个矩阵的直接副本获取相同的数据指针
>> C = V(1:结束)
C =
结构地址= 1 cc30c400
m = 1
n = 5.
pr = 60c004eb8bc0.
1 -2 3 -4 5
但所有元素的副本就可以了 不是 获取相同的数据指针。
在每一个访问值子集的情况下,数据指针必须 不是 是相同的(至少是非稀疏数组)。假设代码可以特殊情况下,索引是全部的和正常的顺序…但是代码并没有这样做。实际上,表示需要普通变量的深度副本的方法是使用1:end,因此在整个数组被访问的情况下重用数据指针的优化可能会导致微妙的问题。
您需要知道的另一个信息是,当您在不使用Total Array的表达式中使用稀疏数组时,请将Matlab 总是 从松弛的非零点上剥离。例如,如果你有
a = spalloc(50,50,75);%75是非零的数目
A = A + speye(50);
然后A + speye(50)将给出一个临时稀疏数组,有非零剥离,它是剥离的数组,将被分配在A之上。
这类似于你如何定义
B =复数(1 (1,10),0 (1,10))
b和b将是数据类型复杂的,但只要用它计算任何计算,就像
C = b + 0
然后将检查临时值B + 0,并发现具有全零复杂部分,并且复杂部分将被剥离。

马特J.
马特J. 8月8日
编辑:马特J. 8月8日
你确定你必须担心吗?根据我所看到的(在R2019A,R2020A中),额外的16个字节只有在有2个,只有2个重复的条目时才发生。不仅仅是那个,你很好:
字节=南(10);
为了n = 1:numel(字节);
我=那些(1,n);
j = 1(1,n);
S =π* 1 (1,N);
a =稀疏(i,j,s,1,1);
字节(n)= getfield(whos('一种'),'bytes');
结尾
酒吧(bytes)
ylabel.'bytes'
包含'n'
1条评论
马特J.
马特J. 8月8日
好吧,如果您有许多不同的重复条目坐标,我猜这可能是一个问题。在任何情况下,这里都是一种方法,你可以使用预先修剪数据 splitapply 或者 积分,
预累积的%%结构
[ij,〜,g] =唯一([i(:),j(:)],'行');
Sacc = accumarray (G (:), S (:));
一个=稀疏(IJ (: 1), IJ (:, 2), Sacc);
上图的修改版本显示了我们为生成的矩阵获得了适当的nzmax:
m = 300;
2字节=南(10日);
为了N = 1:大小(字节,1)
I = (1: M)。‘* 1 (1,N);
J = 1 (M, N);
S =π* 1 (M, N);
%%常规建筑
A0 =稀疏(I,J,S);
字节(n,1)= getfield(whos('a0'),'bytes');
预累积的%%结构
[ij,〜,g] =唯一([i(:),j(:)],'行');
Sacc = accumarray (G (:), S (:));
一个=稀疏(IJ (: 1), IJ (:, 2), Sacc);
字节(N, 2) = getfield(谁('一种'),'bytes');
结尾
酒吧(bytes)
ylabel.'bytes'
包含'n'
传奇('传统的''预累积'

登录评论。

标签

社区寻宝

找到Matlab Central中的宝藏,并发现社区如何帮助您!

开始狩猎!