R的计算速度?


16

我的任务是将我们当前的大型随机模型之一从SAS迁移到新语言。就个人而言,我更喜欢传统的编译语言,但PI希望我签出我从未使用过的R。我们将模型从SAS中剔除的动机是:(1)许多人因为SAS昂贵而无法使用它;(2)我们正在寻求摆脱解释型语言;(3)SAS对于我们拥有的模型类型。

对于(1),显然R满足自由的需求。对于(2),理想情况下,我们想创建一个可执行文件,但是R通常用作脚本语言。我看到有人最近发布了R编译器-这是否广受欢迎?这个容易用吗?我们不想强迫用户自己下载R。对于(3),我们的SAS问题是所有时间都花在I / O写入和读取数据集上。我们的模型是计算密集型的,并且经常受到运行时的限制。(例如,有人在周末劫持人们的计算机来执行运行并不少见。)我们在Fortran中建立了一个类似的模型,该模型不会出现相同的问题,因为所有工作都在内存中完成。R如何工作?它是否与SAS相同,因为它可以在数据步骤中工作,读写文件?还是可以在内存中进行数组操作?


通常,您可以在一个数据步骤中完成所有工作,从而加快sas的速度。这将减少I / O时间,因为您实际上只读取一次数据。使用大量程序也会使您减速。例如,如果您对重复调用proc glm或proc logistic(例如引导程序)进行建模,则创建大型数据集并使用by语句比调用许多proc调用(例如使用宏%do循环)要快。如果您的编程很好,那么您就不会因为读取和输出文件而遇到运行时问题(至少没有其他软件
概率

此外,您可以在sas数据步骤中使用临时数组,其方式与在R中使用矩阵的方式类似
概率

Answers:


18

R在内存中工作-因此您的数据确实需要容纳大多数功能的内存。

如果考虑到您在考虑的事情(R附带的Luke Tierney的编译器软件包),编译器包与传统意义上的编译语言(C,Fortran)是不同的。从Java VM执行的Java字节码或Emacs LISP代码的字节编译的意义上来说,它是R的字节编译器。它不会将R代码编译为机器代码,而是将R代码准备为字节码,因此与要解释的原始R代码相比,它可以更有效地使用。

请注意,如果您拥有格式良好的Fortran,则可能两全其美。R可以调用编译的Fortran例程。


谢谢!很高兴知道我可以拥有出色的R图形并调用编译的Fortran例程。这可能是答案!
梅利莎(Melissa)2012年

2
只是为了扩展Gavin关于内存的注释:如果要使用更大的数据集,请参见此
Brandon

1
还认为必须注意,Rcpp可能会用于获得性能的增量提升,这一点也很重要。
布兰登·贝特尔森

Rcpp对于包装C ++以用于R /与R一起使用非常有用。它极大地帮助了该过程,但仍在使用R的基本工具来调用已编译的代码。如果OP已经具有Fortran代码或Fortran技能,则Rcpp的使用可能较少。
恢复莫妮卡-辛普森(G. Simpson)2012年

13

我已经使用SAS了15年,并且R在过去的6个月中开始认真使用它,并且在此之前的几年中进行了一些修补。从编程的角度来看,R 直接进行数据操作是没有等效的DATAPROC SQL过程的,因为不需要它们(SAS当从外部数据源(例如管理数据)进行大量数据操作时,后者会更有效)。这意味着,现在我掌握了它,数据处理速度更快R,所需的代码也少得多。

我遇到的主要问题是内存。并非所有R包都允许WEIGHT类型规范,因此,如果您的SAS数据集包含在FREQREPLICATE语句中使用的变量,则可能会出现问题。我已经看过R 中的ffbigmemory程序包,但它们似乎并不与所有R程序包兼容,因此,如果您有非常庞大的数据集,需要比较少见的分析并进行了汇总,则可能存在内存问题。

对于自动化,如果有的SAS macros话,那么您应该可以对等效程序进行编程R并批量运行。

为了进行编码R,我使用Notepad++了语言并将其设置为R,现在我发现了它的乐趣R Studio。这两个产品都是免费的,并且像改进的SAS语法GUI 一样进行语言标记(我只使用过中的语法屏幕SAS)。

有一个网站和相关书籍,供人们从切换SASR。我发现它们对于尝试找出如何将某些SAS命令转换为有用R

更新:一两件事,促使我坚果来的时候RR不承担一切的数据集(data frameR用语),因为它不是在路上的统计包SASSPSSStata等都是。因此,例如,我花了一段时间才能使if语句正常工作,因为我一直在获得有关if向量(或矩阵)语句的帮助,而我却需要使用的if语句data frames。因此,可能需要比平时更仔细地阅读帮助页面,因为您需要检查要执行的命令是否可以对您拥有的数据对象类型进行操作。

当学习一个新R命令(例如,有贡献的软件包中的分析方法)时,仍然令我发疯的一点是,命令帮助通常并不完全独立。我将转到帮助页面以尝试学习该命令以及其中经常...包含的用法说明。有时尝试找出可以或应该去的地方使...我进入了递归循环。帮助笔记的相对简短,SAS从中提供了详细的语法示例和工作示例,并提供了示例中的研究解释,这是一个很大的震惊。


2
+1请考虑更新我们已收集到统计软件资源链接的元线程。那里有一个针对R的答复,另一个针对SAS的答复:都拥有指向r4stats.com的链接,将从中受益。(该线程实际上是我们的常见问题解答的一部分。我们希望使其保持最新和有用。)
whuber

1
R还具有支持通过RODBC驱动程序或SQLite访问SQL的软件包。
DWin 2012年

1
我同意您对R帮助的评论。实际上,我实际上指出了您多年前在R邮件列表之一上所说的话。回应不是积极的。公平地说,我(a)可能没有很好地表达自己,没有给出具体的例子,并且(b)没有对此事进行调查。总而言之,问题1的示例过于复杂,涉及太多无关的概念。可以使用复杂的示例,但应该遵循简单的示例。问题2是几乎没有注释或解释这些示例的功能。
Faheem Mitha 2012年

关于R的“帮助”让我想起了老板对我说的话。“您通过与已经知道R坐在电脑
概率

对于其他所有人,都有书籍和堆栈溢出。是的,自己学习R很难,至少对我来说是如此。
米歇尔

10

R是一种编程语言。它不适用于数据步骤。它可以完成您想做的所有事情,因为它只是一种编程语言,是您的欲望的奴隶,用花括号和冒号表示。

可以将其像Fortran或C一样,但是具有隐式矢量化功能,因此您不必循环遍历数组,而无需进行动态内存管理,因此您不必在任何时候使用malloc()或声明数组大小。

它主要在内存中完成所有工作,但是如果您想读入文件的一部分,将其蒙上一层,然后吐出一些结果,然后读入下一部分,那么,您就继续编写一个R程序,做到这一点。

您会说模型是计算密集型的,但是SAS由于I / O而速度很慢,这与您自相矛盾。

如果您已经在Fortran中有了类似的功能,并且您说要摆脱解释型语言,那么为什么不在Fortran中也这样做呢?

R编译器可能会提高速度,但是如果您的R代码编写得当,则不会得到太大的内容-不像用C或Fortran编写。


啊,我说得不好。它对数据集的操作非常费力,这在SAS中意味着在I / O上花费了太多时间。我最初的建议是Fortran,但PI对我们切换到R感兴趣,因此他希望我检查一下。谢谢!
梅利莎(Melissa)2012年

7

我知道默认情况下,SAS可以使用大于内存的模型,但R则不是这样,除非您专门使用biglm或ff等软件包。

但是,如果您正在R中进行可以向量化的数组工作,这将非常快-在某些情况下,速度可能是C程序的一半,但是,如果您正在执行无法向量化的工作,那么看起来慢。举个例子:

# create a data.frame with 4 columns of standard normally distributed RVs
N <- 10000

# test 1
system.time( {df1 <- data.frame(h1=rnorm(N),
                h2=rpois(N, lambda=5),
                h3=runif(N),
                h4=rexp(N))
} )
# about 0.003 seconds elapsed time

# vectorised sum of columns 1 to 4
# i.e. it can work on an entire column all at once
# test 2
system.time( { df1$rowtotal1 <- df1$h1 + df1$h2 + df1$h3 + df1$h4 })
# about 0.001 seconds elapsed time

# test 3
# another version of the vectorised sum
system.time( { df1$rowtotal2 <- rowSums(df1[,c(1:4)]) })
# about 0.001 seconds elapsed time

# test 4
# using a loop... THIS IS *VERY* SLOW AND GENERALLY A BAD IDEA!!! :-)
system.time( {
        for(i in 1:nrow(df1)) {
                df1$rowtotal3 <- df1[i,1]+ df1[i,2] + df1[i,3] + df1[i,4]
        }
} )
# about 9.2 seconds elapsed time

当我将N增加十倍到100,000时,我在20分钟后放弃了测试4,但是测试1:3分别花费了61、3 和37 毫秒

对于N = 10,000,000,测试时间1:3分别为3.3秒,0.6秒和1.6秒

请注意,这是在i7笔记本电脑上完成的,并且N = 1000万的带宽为480mb,内存不是问题。

对于32位Windows上的用户,无论您有多少内存,R的内存限制均为1.5gb,但对于64位Windows或64位linux没有这种限制。这些天的内存与一个小时的时间相比非常便宜,因此我只是购买更多的内存,而不是花时间尝试解决这个问题。但这假设您的模型将适合内存。


1
(+1)肖恩,感谢您提供有用的插图!
Whuber

3

(2),理想情况下,我们想创建一个可执行文件,但是R通常用作脚本语言

是的,这是迁移到R的充分理由。编写R包的目的是使用户可以轻松地使您的函数与R提供的其他工具进行交互,例如,向他们提供引导数据……或他们想要的任何东西。如果您认为这并不重要,请坚持使用C / C ++或您喜欢的编译语言。

我要说明一下:您已经是一名程序员,学习R变得容易又快速;学习高效的R编程将更长。因为R被解释,所以常量隐藏在Ø 渐进复杂性的大小可能很大或很小...例如,如果您对数据中的运行感兴趣,则可以使用 rle(),它将很快(它具有预编译功能)。如果您编写完全相同的算法脚本,它将很慢(它将被解释)。这是一个基本示例:使用向量和矩阵有很多技巧,可以避免解释循环并让预编译函数完成所有工作。

所以要非常小心。第一次尝试后,您一定会对R感到厌恶,因为您会发现它运行缓慢,语法很奇怪等。一旦您知道它,它可能是非常有效的工具。您甚至可以通过在R中编写方法脚本作为C / C ++编码的初步阶段来结束。最终阶段将是学习R的API以创建预编译的函数,您将成为R向导:)


2

显然,内存中的阵列操作对于SAS来说是一件大事。我不了解有关R的具体信息,但是我推测R默认情况下在内存中运行,因为针对R,ff和bigmemory的内存扩展程序包将数据从内存移至磁盘。如果您想提高速度或内存使用率,我会为您提供指导。为了提高速度,您首先需要按预期使用R,即:将代码矢量化并使用字节码编译。(还:尽可能避免进行内存复制操作。)其次,使用提供的代码分析器Rprof()识别代码中的慢补丁,并在需要时用C或C ++重写它们。如果需要更多内存,则可以使用read.table()函数中的skip参数来一次读取数据块,还可以使用RMySQL之类的程序包,该程序包将数据库操作实用程序添加到R中。如果您需要更多内存并且可以承受随之而来的速度下降,则可以使用snow软件包并行运行R。(您可以在去年年底出版的诺曼·马特洛夫(Norman Matloff)的“ R编程的艺术”一书中找到有关此内容的详细信息,以及更多内容。可以在网上找到有关此软件包的详细信息。)

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.