如何解决matlab示例“fulltosparse.c”的bug

时间:2013-12-11 21:58:50

标签: c matlab mex sparse-matrix

此文件位于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);

1 个答案:

答案 0 :(得分:3)

当稀疏矩阵需要额外的非零存储空间时,fulltosparse.c中出现了一个新的nzmax计算错误。

分别在i源矩阵的j行和m列的每个非零行n和列fullk非零元素),进行检查(k>=nzmax)以确保稀疏矩阵数据缓冲区(srsi和{中有足够的存储空间{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=2i=0),它需要首次展开缓冲区,并且上面的代码在重新分配之前运行。 j=1为2. oldnzmax增加到0.3,给出percent_sparse。自nzmax=ceil(6*0.3)=2起,它只会递增(oldnzmax == nzmax)并重新分配nzmax++。行。
  • nzmax=3(第四个元素; k=3i=1),它会经过类似的路径,将j=1增加到0.4,计算percent_sparse和将nzmax=ceil(6*0.4)=3增加到4。
  • 当它达到nzmax (第五个元素; k=4i=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=4k=4,重新分配稀疏矩阵缓冲区(nzmax=3srsi),并超出缓冲器:

    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