这是一个想法:
您说您有一个无序的矩阵,即不同长度的列表。我假设其中包含浮点数。
您可以将矩阵扁平化以获得单个长的压缩 1D 数组(如果需要,使用Developer`ToPackedArray
进行打包),并单独存储子列表的起始索引。然后在导入数据后重新构建无序矩阵。
这里展示了在Mathematica内部(即在导入后)从巨大的扁平列表中提取子列表的速度非常快。
data = RandomReal[1, 10000000];
indexes = Union@RandomInteger[{1, 10000000}, 10000];
ranges =
data[[
{0.093, Null}
或者存储一个子列表长度的序列,使用 Mr.Wizard 的 dynamicPartition
函数,它恰好可以做到这一点。我的观点是,在内核中以平面格式存储数据并对其进行分区将会增加可忽略的开销。
将打包数组作为 MX 文件导入速度非常快。我只有 2 GB 的内存,所以无法在非常大的文件上测试,但在我的机器上,打包数组的导入时间总是不到一秒钟。这将解决导入未打包数据可能会更慢的问题(尽管如我在主问题的评论中所说,我无法复制您提到的极端缓慢情况)。
如果 BinaryReadList
很快(它现在并不像读取 MX 文件那样快,但看起来 在 Mathematica 9 中它将显著加快速度),您可以将整个数据集存储为一个大型二进制文件,而无需将其分成单独的 MX 文件。然后,您可以像这样导入文件的相关部分:
首先创建一个测试文件:
In[3]:= f = OpenWrite["test.bin", BinaryFormat -> True]
In[4]:= BinaryWrite[f, RandomReal[1, 80000000], "Real64"]; // Timing
Out[4]= {9.547, Null}
In[5]:= Close[f]
打开它:
In[6]:= f = OpenRead["test.bin", BinaryFormat -> True]
In[7]:= StreamPosition[f]
Out[7]= 0
跳过前五百万个条目:
In[8]:= SetStreamPosition[f, 5000000*8]
Out[8]= 40000000
阅读500万条记录:
In[9]:= BinaryReadList[f, "Real64", 5000000] // Length // Timing
Out[9]= {0.609, 5000000}
阅读所有剩余条目:
In[10]:= BinaryReadList[f, "Real64"] // Length // Timing
Out[10]= {7.782, 70000000}
In[11]:= Close[f]
(作为比较,
Get
通常在此处从MX文件中读取相同的数据,时间不到1.5秒。我用的是WinXP。)
编辑如果您愿意花时间,编写一些C代码,另一个想法是创建一个库函数(使用
Library Link),将文件内存映射(
Windows链接)并将其直接复制到一个
MTensor
对象中(
MTensor
只是一个紧凑的Mathematica数组,在库链接的C端看到)。
Import
/ReadList
时比其他任何格式都要快。我不知道BinaryReadList
... - Szabolcs