如何在Octave中有效地存储和操作稀疏二进制矩阵?

时间:2014-06-26 19:19:11

标签: matrix octave sparse-matrix binary-matrix

我正在尝试在GNU Octave中操作稀疏的二进制矩阵,并且它使用的内存比我预期的多,并且相关的稀疏矩阵函数的行为与我想要的不同。我看到this question about higher-than-expected sparse-matrix storage in MATLAB,这表明此矩阵应该消耗更多内存,但有助于解释(仅)部分情况。

对于稀疏的二进制矩阵,我无法弄清楚是否有任何方法可以将Octave变为 NOT STORE 值的数组(它们总是隐式1,所以不需要存储)。 可以这样做吗? Octave似乎总是占用值数组的内存。

一个展示情况的精简示例:创建随机稀疏矩阵,将其变为“二进制”:

mys=spones(sprandn(1024,1024,.03)); nnz(mys), whos mys

显示情况。消耗的大小与aforementioned SO answer中概述的存储机制一致,并在下面展开,如果spones()创建存储类double数组并且所有索引都是32位(即< / p>

TotalStorageSize - rowIndices - columnIndices == NumNonZero*sizeof(double)
- 不必要地存储这些值(所有1 s为double s)超过此3% - 稀疏对象消耗的总内存的一半。

< / p>

在撰写这个问题时,我发现了一些部分的解决方法,因此我发现了一些部分的解决方法,因此我将“自我回答”(仅)部分问题的连续性(希望如此),但我没有找出主要问题的充分答案:

如何在Octave中创建高效存储(“无/隐含值”)二进制矩阵?

存储格式的其他背景如下......

Octave文档说storage format for sparse matrices使用格式Compressed Sparse Column (CSC)。这似乎意味着存储以下数组(扩展到aforementioned SO answer,使用规范Yale format labels并调整column-major order):

  • A),存储类大小的非零数(NNZ)条目;
  • 行号IA),索引大小的NNZ条目(希望int64但可能int32);
  • 每列的开头JA),列数加1条索引大小的条目)

在这种情况下,对于仅二进制存储,我希望有一种方法可以完全避免存储数组(A),但我无法弄明白。

1 个答案:

答案 0 :(得分:1)

完全披露:如上所述,在我撰写此问题时,我发现了一种减少内存使用量的解决方法,因此我自我回答了#34;这里的一部分,但它仍然不是完全令人满意的,所以我仍然在寻找一个更好的实际答案来存储稀疏二进制矩阵而不需要琐碎,臃肿,不必要values array ...

要在类似数字的值中获取类似二进制的值,并在这种情况下减少内存使用量,请使用&#34; logical&#34;存储,由logical(X)创建。例如,从上面构建,

logicalmys = logical(mys);

创建一个sparse bool matrix,它占用更少的内存(1个字节logical而不是8个字节double的值数组。)

使用whoswhos_line_format信息添加更多信息有助于说明这种情况:默认字符串包括7个属性中的5个(see docs以获取更多信息)。我使用格式字符串

whos_line_format(" %a:4; %ln:6; %cs:16:6:1; %rb:12; %lc:8; %e:10; %t:20;\n")

添加&#34;元素&#34;和&#34;类型&#34;的显示(不同于&#34;类&#34;)。

这样,whos mys logicalmys显示类似

的内容
 Attr Name            Size      Bytes Class      Elements                 Type
 ==== ====            ====      ===== =====      ========                 ==== 
      mys          1024x1024   391100 double        32250        sparse matrix
      logicalmys   1024x1024   165350 logical       32250   sparse bool matrix

因此,这显示了sparse matrixsparse bool matrix之间的区别。但是,logicalmys消耗的总内存与实际存储NNZ布尔数组(1字节)一致 - 即:

  • totalMemory减去rowIndices减去columnOffsets剩下NNZ个字节;

数字,

  • 165350 - 32250*4 - 1025*4 == 32250

所以我们仍然存储32250个元素,所有元素都是1。此外,如果您将其中一个1 - 元素设置为零,则会减少报告的存储空间!有一段时间,请尝试:选择一个非零元素,例如(42,1),然后将其归零:logicalmys(42,1) = 0;然后whos它!

我希望这是正确的,这可以为那些可能感兴趣的人澄清一些事情。欢迎提出评论,更正或实际答案!