使用Rcpp比scan()更快?

时间:2012-01-30 09:28:38

标签: r rcpp armadillo

从文本文件中读取〜5x10 ^ 6个数字值在我的机器上相对较慢(几秒钟,我读了几个这样的文件),即使使用scan(..., what="numeric", nmax=5000)或类似的技巧。为这类任务尝试Rcpp包装器是否值得(例如Armadillo有一些实用程序来读取文本文件)? 或者,由于预期的接口开销,我是否会浪费我的时间在性能上几乎没有收获?我不确定目前是什么限制了速度(内在的机器性能,或者其他?)这是我每天重复多次的任务,通常,文件格式总是相同的,1000列,大约5000行。

如果需要,这是一个可以播放的示例文件。

nr <- 5000
nc <- 1000

m <- matrix(round(rnorm(nr*nc),3),nr=nr)

cat(m[1, -1], "\n", file = "test.txt") # first line is shorter
write.table(m[-1, ], file = "test.txt", append=TRUE,
            row.names = FALSE, col.names = FALSE)

更新:我使用Armadillo尝试read.csv.sqlload("test.txt", arma::raw_ascii),两者都比scan解决方案慢。

4 个答案:

答案 0 :(得分:8)

我强烈建议您在fread的最新版本中查看data.table。 CRAN(1.8.6)上的版本还没有fread(在本文发布时),所以如果您从R-forge的最新源安装,您应该能够获得它。请参阅here

答案 1 :(得分:5)

请记住,我不是R专家,但也许这个概念适用于此:通常阅读二进制文件比阅读文本文件要快得多。如果您的源文件不经常更改(例如,您在相同的数据上运行不同版本的脚本/程序),请尝试通过scan()一次读取它们并以二进制格式存储它们(手册中有一章说明导出二进制文件)。 从那以后,您可以修改程序以读取二进制输入。

@Rcpp:scan()&amp;朋友可能会调用本机实现(如fscanf()),因此通过Rcpp编写自己的文件读取函数可能无法提供巨大的性能提升。您仍然可以尝试(并针对您的特定数据进行优化)。

答案 2 :(得分:4)

Salut Baptiste,

数据输入/输出是一个很大的主题,如此之大以至于R带有自己的manual on data input/output

R的基本功能可能很慢,因为它们非常通用。如果你知道你的格式,你可以轻松地自己写一个更快的导入适配器。如果您也了解尺寸,则只需要一次内存分配就更容易了。

编辑:作为第一个近似,我会写一个C ++十行。打开文件,读取一行,将其分解为标记,分配给vector<vector< double > >或类似的东西。即使您对单个向量元素使用push_back(),您也应该与scan()竞争,即使用它。

根据Brian Kernighan本人的代码,我曾经在C ++中有一个简洁的小csv reader类。相当通用(对于csv文件),相当强大。

然后,您可以根据需要挤压效果。

进一步编辑:这个SO question有许多针对csv阅读案例的指针,以及对Kernighan和Plauger书的引用。

答案 3 :(得分:3)

是的,你几乎肯定能创造出比read.csv / scan更快的东西。但是,对于高性能文件读取,有一些现有的技巧已经让你走得更快,所以你做的任何事情都会与那些竞争。

正如Mathias所提到的,如果您的文件不经常更改,则可以通过调用save来缓存它们,然后使用load恢复它们。 (确保使用ascii = FALSE,因为读取二进制文件会更快。)

其次,正如Gabor所提到的,通过将文件读入数据库然后从该数据库读入R,您通常可以获得显着的性能提升。

第三,您可以使用HadoopStreaming包来使用Hadoop的文件读取功能。

有关这些技巧的更多想法,请参阅Quickly reading very large tables as dataframes in R