Col*_*ers 6 memory csv matlab textscan
我在Linux Mint v12上运行Matlab R2011b和R版本2.13.1,内存为16 GB.
我有一个csv文件.前5行(和标题)是:
#RIC,Date[G],Time[G],GMT Offset,Type,Price,Volume
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.68,1008
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.68,1008
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.66,300
DAEG.OQ,07-JUL-2011,15:10:03.424,-4,Trade,1.65,1000
DAEG.OQ,07-JUL-2011,15:10:03.464,-4,Trade,1.65,3180
Run Code Online (Sandbox Code Playgroud)
文件很大(约900MB).鉴于字符和数字数据的组合,可以将此文件读入matlab,如下所示:
fid1 = fopen('/home/MyUserName/Temp/X.csv');
D = textscan(fid1, '%s%s%s%f%s%f%f', 'Delimiter', ',', 'HeaderLines', 1);
fclose(fid1);
Run Code Online (Sandbox Code Playgroud)
虽然文件是900MB,但在运行上面的代码时,系统监视器表明我的RAM使用率从大约2GB跳到10GB.更糟糕的是,如果我尝试使用稍微大一点的csv文件(大约1.2 GB)进行相同的操作,我的RAM最大值为16GB,而Matlab从未设法读完数据(它只是停留在"忙碌"模式).
如果我想将相同的文件读入R,我可能会使用:
D <- read.csv("/home/MyUserName/Temp/X.csv", stringsAsFactors=FALSE)
Run Code Online (Sandbox Code Playgroud)
这比Matlab要长一些,但系统监视器表明我的RAM使用率仅从2GB跳到3.3GB(考虑到原始文件大小,更合理).
我的问题有两个部分:
1)为什么textscan在这种情况下会出现这样的记忆?
2)我是否可以使用另一种方法在我的系统上将这种类型的1.2GB csv文件放入Matlab而不会超出RAM?
编辑:只是为了澄清,我很好奇是否存在一个仅限matlab的解决方案,即我对使用不同语言将csv文件分解为更小块的解决方案不感兴趣(因为这是什么我已经在做了).对不起Trav1s,我应该从一开始就明白这一点.
问题可能是那些“%s”字符串被读入 Matlab cellstr,这是低基数字符串的内存效率低下的数据结构。对于像这样的大表格数据来说,Cellstr 很糟糕。每个字符串最终都会存储在一个单独的原始char数组中,每个数组都有大约 400 字节的开销和碎片问题。对于 900MB 的文件,看起来有 1800 万行;每行 4 个字符串,大约需要 10-20 GB 的 cellstr 来保存这些字符串。啊。
您想要的是在这些字符串传入时将其转换为紧凑的原始数据类型,而不是一次性将所有 1800 万行转换为庞大的单元格字符串。日期和时间戳作为日期数字或您正在使用的任何数字表示形式,而那些低基数字符串作为二维char数组或某种等效的分类变量。(考虑到您的数据集大小,您可能希望这些字符串表示为带有查找表的简单数字标识符,而不是字符。)
一旦你决定了你的紧凑数据结构,有几种方法来加载它。你可以在纯 Matlab 中将读取分成块:使用textscan()循环调用一次读取 1000 行,解析和转换该块中的 cellstr 转换为紧凑形式,缓冲所有结果,并cat在读取结束时将它们组合在一起。这将使峰值内存需求降低。
如果您要做很多这样的工作,并且性能很重要,您可能需要使用 Java 并编写自己的解析器,该解析器可以在字符串和日期传入时对其进行转换,然后将它们返回给 Matlab更紧凑的数据类型。这并不难,而且 Java 方法可以直接从 Matlab 调用,因此这可能只能算作使用单独的语言。