2. data.matrix/data.frame
data.frame是个很有用的结构,但是在处理海量数据上比matrix差得不是一点半点。matrix本质是按列存储的一个vector;data frame本质和list没有区别。然后你懂得a. 存储需求 data frame大得多 b. 计算速度 data frame 慢得多。但是为什么诸如lm glm使用data fame作为默认输入?因为在数据规模很小的时候你根本看不出来。
3. R + C/Cpp/F
好处就不多说了–大家都说了很多–我个人情绪化抵制Rcpp,因为它隐藏了太多东西,而且高度模板化的东西在科学计算领域写起来和调试起来就是脱了裤子放屁。R本身很多函数都是基于编译语言实现的,仔细研究下代码改进成你要的版本是可以的。然后,重要的一点在于…如果算法很糟糕,C的版本可以比R的版本慢你信么,哪怕是你感觉非用for不可时候。你可以看我这个[例子](COS[155412] and some discussion) 理解R数据存储的特点设计算法很重要。
回复 ( 4 )
可以尝试下面的方法:
1. 通过Rprof找到速度瓶颈,在瓶颈处优化最有效。
2. 循环采用多进程并行化不行,可以尝试手动分割任务成可并行的部分,然后手工多进程并行化
3. 效率低的代码采用高性能的写法(向量化计算、矩阵计算等等)
4. 如果是矩阵计算有瓶颈,可以用采用了Intel MKL 的 RRO
4. 用Rcpp重写低效代码
5. 在Rcpp中用OpenMP等技术实现C++原生数据结构上的多线程并行化。
或许你想要的是Rcpp?
有一本书可以参考:Seamless.R.and.C++.Integration.with.Rcpp。我没看过,不知道是否有帮助。
总的来说题主说了个很大的问题。因为R的普通函数本身可能就有很多高科技,只是大家不会用。
1. apply/for/do.call/…
apply就是个隐藏的for,但是是vectorized后的;而且同样有mcapply的版本。我要说的是,使用这两个东西,本质没啥区别,连并行版本都是你有我就有这种状态。但是,做这些事情之前想想有没有矩阵内外积(*,%*%,kroneker)表示吧,比如我在这个[帖子](主题:给各位拜年了,小弟又有问题,请教能否不用循环实现?求优化的R代码。)里写的那种矩阵技巧。
2. data.matrix/data.frame
data.frame是个很有用的结构,但是在处理海量数据上比matrix差得不是一点半点。matrix本质是按列存储的一个vector;data frame本质和list没有区别。然后你懂得a. 存储需求 data frame大得多 b. 计算速度 data frame 慢得多。但是为什么诸如lm glm使用data fame作为默认输入?因为在数据规模很小的时候你根本看不出来。
3. R + C/Cpp/F
好处就不多说了–大家都说了很多–我个人情绪化抵制Rcpp,因为它隐藏了太多东西,而且高度模板化的东西在科学计算领域写起来和调试起来就是脱了裤子放屁。R本身很多函数都是基于编译语言实现的,仔细研究下代码改进成你要的版本是可以的。然后,重要的一点在于…如果算法很糟糕,C的版本可以比R的版本慢你信么,哪怕是你感觉非用for不可时候。你可以看我这个[例子](COS[155412] and some discussion) 理解R数据存储的特点设计算法很重要。
4. 有关foreach doparallel之类的东西
其实并行计算的坑是很大的,比如你考虑过你的计算是可重入的不(并行的时候还要做随机数产生)?或者真的可以并行么(EM)?何况有些时候有些隐藏的bug会让人抓狂(比如改了多线程openblas等会在某些平台会让foreach什么的效率降低:都在一个核心上做运算)。
5. OMP
你要是自己写R+Cpp(OPENMP)就应该知道,这东西平台依赖…而且,重申一点,不是什么都能并行的,而且怎么并行是个天坑。
5.1 R本身就不是thread-safe/re-entrant, 也就是原生基于R的API的基本没戏;
5.2 用GCC + Linux系列的可以自己写OMP+Rcpp可以有解决方案,看Glibc的实现可以看到
首先,要判断一下瓶颈是否是在function还是在循环。可以用system.time(…)测试运行一次function的事件,和运行比如1000次循环该function的事件。
如果确实是function的表现不佳,那就想办法优化吧。我能想到的:
我也做过(对于我的破笔记本来说)海量的数据,以下是我的建议: