COSeditor
邱怡轩
感谢师兄的这篇文章!也希望大家能把自己编程中提高效率的一些经验与大家进行分享。
此外我记得R中有一个包叫做inline,它其实就是简化了上面的writeLines()和system()的操作,通过写临时文件和删临时文件并调用系统命令来编译C程序。
shuaihuang
赞
用C写 加加减减 的程序, 尤其是矩阵计算里要用的加加减减, 速度确实提高很多.
nan.xiao
很多时候也许是因为我们没有很好地定义问题 导致效率的降低 ..
lyxmoo
再有R 的核心还应该有改进的余地,我粗粗的看了一下, src/main/names.c 中
attribute_hidden FUNTAB R_FunTab[] 这个结构在使用的时候,是通过
for 循环进行比较 R_FunTab.name 的, 这个循环方式不经济,
可以通过 hash R_FunTab.name 的方式,快速定位,这样就快了点点,
不过这个改进还只是治标的小改动。
kimboo
请问师兄为什么我直接运行第一段代码显示的是
用户 系统 流逝
0 0 0
需要做什么改动吗?另外test.t是什么格式?
yihui
[未知用户] That's an arbitrary file name; you can name it as anything you want, e.g. ttest.txt
. It is a pure text file.
I've tested the code under both Windows and Linux, so it should not be a problem with the computation. I guess the problem is whether you have enough privilege to write a file to your working directory getwd()
. (AFAIK, in Win7 or Vista there can be problems to access your C disk.)
邱怡轩
[未知用户] 我觉得当R的影响力足够大的时候,肯定会有一批人专门来研究怎么提高核心代码的效率的,就像是S语言一代一代的更新。
另:这位就是多次跟师兄提及的牟先生哦,呵呵。
kimboo
The version of R in my computer is REvolution R 1.3.0. Now I have changed to the newest R version 2.10.1 to test the same code. The problem dispeared! Maybe there is something in relation to the function source(). When using REvovlution, it create a file n my hard disk. However when sourcing it, there is nothing in computation, at the same time, the file size become to be 0 kb...
PS:My OS is Windows XP SP3.
yihui
[未知用户] 这样看来可能是REvolution对连接(?connection
)的处理还有所欠缺,R里面很多函数都支持各种连接,通过文件名访问文件只是最基础的一种,其它方式包括socket、URL、gzip等。我猜的话,source('test.t')
应该是可以运行的。
lyxmoo
[未知用户] 当时我要提自己事情主要是担心只报了上海而不能参加北京活动(不规则的参与者的行动或给组织者造成了麻烦)。我在统计学领域还只是幼儿园级别,特别感谢各位能够提供机会让我能够学习。
yihui
[未知用户] 哦,谢谢相告,我之前还搜了好半天邮件,人名和ID对不起来了。也谢谢lyxmoo的热心支持!
enthumelon
用R做像EM之类的处理通常很痛苦。问题就在循环、四则运算、拷贝等问题上面。因为R语言是变量和LISP语言一样,是一张表(当然也可以描述成树)。
普通的一个
A<-matrix(runif(100),nrow=10);
对
B<-A
和
for (i in 1:10) {for (j in 1:10) B[i,j]=A[i,j]}
可是差得太多的。虽然,如果写成Fortran或者C++,那是一样的东西。问题出在R是解释语言,不是编译后的东西(Python的速度可能要例外)。
可以想见的结果就是通常的代数运算会很慢。通常的速度问题出现在矩阵操作上。
至于使用较为底层的C/C++,F/F99,Pascal等,问题在于代码有的时候非常难写。比如说高维矩阵求逆,或者稀疏矩阵求广义逆等,这些是都是非常麻烦的。要牵涉到很复杂的算法、精度控制等(比方说双double精度)。
R提供了一个很好的接口。R本身也是通过调用Lapack/BLAS等的功能完成上述矩阵的。但是这一点是操作系统相关的。上述的库在Win平台上是很麻烦的,甚至很多功能不兼容。比如(c)BLAS至今有很多功能也不能和VS2005等Win上主流C/C++编译器兼容。所以,打开R的etc,我们发现实际上用的是GCC完成代码编译的(编译选项是 -O2, 会的同学可以试图改成 -O2 -march=[视CPU而定]。运算速度有时能提高不少。 )
所以我的建议是,在进行这种复杂操作时:
1. 底层语言和R语言混合编程,事实上,同样的问题存在于Octave/Matlab(R)上面;
2. 重要项目用LAPACK等开源库完成代码,写成R的包;
3. 如果能换平台,用Xuinx类系统,这样执行效率要高很多,也能突破内存限制。
zong0jie
在R2.10里面貌似循环速度大大加快,只比apply慢了300%,几分钟时间完全可以接受了。
我机器,笔记本酷睿2 t7300 主频2.0GHz 内存ddr2 667 2G
也搞了18万行的循环做个小测试
> b=rep(0,1800)#这里当时打错了,不过R能自动扩展向量长度的嘛
> a=matrix(rnorm(900000,10,1),nc=5)
> system.time(for(i in 1:180000){b=t.test(a[i,])})
用户 系统 流逝
331.36 2.49 339.83
警告多于50个(用warnings()来显示第一个到第五十个)
> system.time(b<-apply(a,1,t.test))
用户 系统 流逝
102.81 0.06 103.20
现在看来已经没有几个小时那么夸张了嘛,多等两分钟问题不是很大吧。这时候程序可读性貌似更重要,因为自我感觉向量化会让语句看起来比较累,然后这样可以把精力放在解决具体问题上而不是如何搞向量化......我是菜鸟了,意见仅供参考。
tctcab
跑了一下十年前的代码
zong0jie
b=rep(0,1800)#这里当时打错了,不过R能自动扩展向量长度的嘛
a=matrix(rnorm(900000,10,1),nc=5)
system.time(for(i in 1:180000){b=t.test(a[i,])})
#用户 系统 流逝
#9.67 0.06 9.84
system.time(b<-apply(a,1,t.test))
#用户 系统 流逝
#11.78 0.25 12.09
一个粗糙的结论是十年过去了电脑快了10-30倍
zong0jie
[未知用户] 补充一点,系统是xp sp3。 类似测试在fedora 12下也进行过,结果依然类似。
abel
简单来说,R底层基本上都是C做的,调用的库也是久经考验的。
程序运行的效率核心在于对语言提供的功能十分有足够的了解和体会,如果把base包中的内容认真仔细的通读下,再掌握常见运算的核心所在,相信就不会抱怨工具的问题——相对来说R对计算方面考虑的已经非常好了。
lipiji1986
嗯 尽量避免通过R来对大量数据进行预处理 数据的一些预处理可以交给C或者Java 而用R只进行实验计算等
yueliTiffany
请问dependent iteration(原谅我中英夹杂,因为我不知道怎么正确翻译)有什么好的解决方法了吗?实在是不想写for循环啊
shrektan
第一次发现还有这么个变量.Platform$dynlib.ext
?
KANG1943
第一次做运行时间超过1分钟的项目,于是开始搜索”如何提高R计算速度“,考古挖出这篇。
KANG1943
KANG1943 测试了一下将所有for
循环结构改成apply
语句后的计算速度变化。因为不知道如何描述一个代码的复杂程度,只能说一下测试代码长什么样:1000行代码,300个变量,包含60个循环结构。for
结构下运行5次的时间为145.00秒,apply
语句下为133.94秒,后者较前者快了11.06秒,即每次运行快2.21秒……总之还是快了,而且就像任何对比实验的阴性结果一样,这告诉我说循环结构不是这段代码中最占用时间的环节。
不知道用现在的data.table
代替data.frame
是否能提高运行速度呢?