此文件位于C:\Program Files\MATLAB\R2013a\extern\examples\refbook
。在mex之后,我使用了:
aa = [1 2 3 ; 4 5 6]
fulltosparse(aa)
第一次,该命令可能有效。但请多次尝试fulltosparse(aa)
。你会发现它会崩溃。谁能告诉我为什么?
mex -largeArrayDims fulltosparse.c
aa = [1 2 3; 4 5 7];
fulltosparse(aa);
fulltosparse(aa);
fulltosparse(aa);
fulltosparse(aa);
fulltosparse(aa);
fulltosparse(aa);
答案 0 :(得分:3)
当稀疏矩阵需要额外的非零存储空间时,fulltosparse.c
中出现了一个新的nzmax
计算错误。
分别在i
源矩阵的j
行和m
列的每个非零行n
和列full
( k
非零元素),进行检查(k>=nzmax
)以确保稀疏矩阵数据缓冲区(sr
,si
和{中有足够的存储空间{1}})。如果没有足够的空间容纳更多元素,则缓冲区将通过irs
扩展,并有足够的空间来增加mxRealloc
个非零元素。
问题在于它如何计算 new nzmax
:
nzmax
该函数以初始mwSize oldnzmax = nzmax;
percent_sparse += 0.1;
nzmax = (mwSize)ceil((double)m*(double)n*percent_sparse);
/* make sure nzmax increases atleast by 1 */
if (oldnzmax == nzmax)
nzmax++;
开头,percent_sparse = 0.2
完整矩阵2x3
对应aa
,并开始循环遍历行(最快)和列。这是出了什么问题:
nzmax = ceil(6*0.2) = 2
(MATLAB索引中的第三个元素; k=2
,i=0
),它需要首次展开缓冲区,并且上面的代码在重新分配之前运行。 j=1
为2. oldnzmax
增加到0.3,给出percent_sparse
。自nzmax=ceil(6*0.3)=2
起,它只会递增(oldnzmax == nzmax
)并重新分配nzmax++
。行。nzmax=3
(第四个元素; k=3
,i=1
),它会经过类似的路径,将j=1
增加到0.4,计算percent_sparse
和将nzmax=ceil(6*0.4)=3
增加到4。nzmax
(第五个元素; k=4
,i=0
)时,循环迭代从j=2
和{{1开始}}。到目前为止,很明显nzmax=4
没有跟上:percent_sparse=0.4
。现在,当percent_sparse
仅提供0.5而新(nzmax=4)/6 = 0.666 > percent_sparse=0.4
时,该错误变得明显,该percent_sparse += 0.1;
小于nzmax=ceil(6*0.5)=3
!。灾难:使用oldnzmax=4
和k=4
,重新分配稀疏矩阵缓冲区(nzmax=3
,sr
和si
),并超出缓冲器:
irs
缓冲区实际上缩小了。但是,即使测试更改为sr[k] = pr[i]; // k=4, sr is length 3
irs[k] = i; // irs is length 3
,缓冲区的大小仍然不会增加,因为 oldnzmax >= nzmax
是根据nzmax
计算得不够快的<{1}} 。我认为需要进行两项更改。首先,在percent_sparse
:
nzmax<oldnzmax
第二,只是为了好的衡量标准,当条件为真且if (oldnzmax >= nzmax)
nzmax = oldnzmax+1;
增加而不是从percent_sparse
计算时,nzmax
应该正确更新:
percent_sparse